mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-12-08 21:31:08 +01:00
Add method to change expiration time of subkeys
Port of e06f60f62c to kotlin
This commit is contained in:
parent
d7b6dfc8d4
commit
69f1028fd9
3 changed files with 170 additions and 0 deletions
|
|
@ -8,6 +8,7 @@ import java.util.*
|
|||
import java.util.function.Predicate
|
||||
import javax.annotation.Nonnull
|
||||
import kotlin.NoSuchElementException
|
||||
import openpgp.openPgpKeyId
|
||||
import org.bouncycastle.bcpg.sig.KeyExpirationTime
|
||||
import org.bouncycastle.extensions.getKeyExpirationDate
|
||||
import org.bouncycastle.extensions.publicKeyAlgorithm
|
||||
|
|
@ -460,6 +461,28 @@ class SecretKeyRingEditor(
|
|||
return this
|
||||
}
|
||||
|
||||
override fun setExpirationDateOfSubkey(
|
||||
expiration: Date?,
|
||||
keyId: Long,
|
||||
protector: SecretKeyRingProtector
|
||||
): SecretKeyRingEditorInterface = apply {
|
||||
// is primary key
|
||||
if (keyId == secretKeyRing.publicKey.keyID) {
|
||||
return setExpirationDate(expiration, protector)
|
||||
}
|
||||
|
||||
// is subkey
|
||||
val subkey =
|
||||
secretKeyRing.getPublicKey(keyId)
|
||||
?: throw NoSuchElementException("No subkey with ID ${keyId.openPgpKeyId()} found.")
|
||||
val prevBinding =
|
||||
inspectKeyRing(secretKeyRing).getCurrentSubkeyBindingSignature(keyId)
|
||||
?: throw NoSuchElementException(
|
||||
"Previous subkey binding signaure for ${keyId.openPgpKeyId()} MUST NOT be null.")
|
||||
val bindingSig = reissueSubkeyBindingSignature(subkey, expiration, protector, prevBinding)
|
||||
secretKeyRing = injectCertification(secretKeyRing, subkey, bindingSig)
|
||||
}
|
||||
|
||||
override fun createMinimalRevocationCertificate(
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
|
|
@ -676,6 +699,45 @@ class SecretKeyRingEditor(
|
|||
.build()
|
||||
}
|
||||
|
||||
private fun reissueSubkeyBindingSignature(
|
||||
subkey: PGPPublicKey,
|
||||
expiration: Date?,
|
||||
protector: SecretKeyRingProtector,
|
||||
prevSubkeyBindingSignature: PGPSignature
|
||||
): PGPSignature {
|
||||
val primaryKey = secretKeyRing.publicKey
|
||||
val secretPrimaryKey = secretKeyRing.secretKey
|
||||
val secretSubkey: PGPSecretKey? = secretKeyRing.getSecretKey(subkey.keyID)
|
||||
|
||||
val builder =
|
||||
SubkeyBindingSignatureBuilder(secretPrimaryKey, protector, prevSubkeyBindingSignature)
|
||||
builder.hashedSubpackets.apply {
|
||||
// set expiration
|
||||
setSignatureCreationTime(referenceTime)
|
||||
setKeyExpirationTime(subkey, expiration)
|
||||
setSignatureExpirationTime(null) // avoid copying sig exp time
|
||||
|
||||
// signing-capable subkeys need embedded primary key binding sig
|
||||
SignatureSubpacketsUtil.parseKeyFlags(prevSubkeyBindingSignature)?.let { flags ->
|
||||
if (flags.contains(KeyFlag.SIGN_DATA)) {
|
||||
if (secretSubkey == null) {
|
||||
throw NoSuchElementException(
|
||||
"Secret key does not contain secret-key" +
|
||||
" component for subkey ${subkey.keyID.openPgpKeyId()}")
|
||||
}
|
||||
|
||||
// create new embedded back-sig
|
||||
clearEmbeddedSignatures()
|
||||
addEmbeddedSignature(
|
||||
PrimaryKeyBindingSignatureBuilder(secretSubkey, protector)
|
||||
.build(primaryKey))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build(subkey)
|
||||
}
|
||||
|
||||
private fun selectUserIds(predicate: Predicate<String>): List<String> =
|
||||
inspectKeyRing(secretKeyRing).validUserIds.filter { predicate.test(it) }
|
||||
|
||||
|
|
|
|||
|
|
@ -469,6 +469,24 @@ interface SecretKeyRingEditorInterface {
|
|||
protector: SecretKeyRingProtector
|
||||
): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
* Set the expiration date for the subkey identified by the given keyId to the given expiration
|
||||
* date. If the key is supposed to never expire, then an expiration date of null is expected.
|
||||
*
|
||||
* @param expiration new expiration date of null
|
||||
* @param keyId id of the subkey
|
||||
* @param protector to unlock the secret key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a new subkey-binding or self-signature with
|
||||
* the changed expiration date
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun setExpirationDateOfSubkey(
|
||||
expiration: Date?,
|
||||
keyId: Long,
|
||||
protector: SecretKeyRingProtector
|
||||
): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
* Create a minimal, self-authorizing revocation certificate, containing only the primary key
|
||||
* and a revocation signature. This type of revocation certificates was introduced in OpenPGP
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue