mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-04-06 14:52:05 +02:00
WIP: Port SecretKeyRingEditor over to OpenPGPKeyEditor
This commit is contained in:
parent
5266fa53c8
commit
1a8c29e1ea
6 changed files with 242 additions and 396 deletions
pgpainless-core/src
main/kotlin/org/pgpainless
test/java/org/pgpainless/key
|
@ -54,6 +54,9 @@ class PGPainless(
|
|||
fun toCertificate(publicKeyRing: PGPPublicKeyRing): OpenPGPCertificate =
|
||||
OpenPGPCertificate(publicKeyRing, implementation)
|
||||
|
||||
fun modifyKey(key: OpenPGPKey, referenceTime: Date = Date()): SecretKeyRingEditor =
|
||||
SecretKeyRingEditor(key, referenceTime)
|
||||
|
||||
companion object {
|
||||
|
||||
@Volatile private var instance: PGPainless? = null
|
||||
|
|
|
@ -12,10 +12,13 @@ import openpgp.openPgpKeyId
|
|||
import org.bouncycastle.bcpg.KeyIdentifier
|
||||
import org.bouncycastle.bcpg.sig.KeyExpirationTime
|
||||
import org.bouncycastle.openpgp.*
|
||||
import org.bouncycastle.openpgp.api.OpenPGPKey
|
||||
import org.bouncycastle.openpgp.api.OpenPGPKeyEditor
|
||||
import org.bouncycastle.openpgp.api.SignatureParameters
|
||||
import org.bouncycastle.openpgp.api.SignatureParameters.Callback
|
||||
import org.bouncycastle.openpgp.api.SignatureSubpacketsFunction
|
||||
import org.pgpainless.PGPainless
|
||||
import org.pgpainless.PGPainless.Companion.inspectKeyRing
|
||||
import org.pgpainless.algorithm.AlgorithmSuite
|
||||
import org.pgpainless.algorithm.Feature
|
||||
import org.pgpainless.algorithm.KeyFlag
|
||||
import org.pgpainless.algorithm.OpenPGPKeyVersion
|
||||
import org.pgpainless.algorithm.SignatureType
|
||||
|
@ -23,8 +26,8 @@ import org.pgpainless.algorithm.negotiation.HashAlgorithmNegotiator
|
|||
import org.pgpainless.bouncycastle.extensions.getKeyExpirationDate
|
||||
import org.pgpainless.bouncycastle.extensions.publicKeyAlgorithm
|
||||
import org.pgpainless.bouncycastle.extensions.requirePublicKey
|
||||
import org.pgpainless.bouncycastle.extensions.toOpenPGPKey
|
||||
import org.pgpainless.implementation.ImplementationFactory
|
||||
import org.pgpainless.key.OpenPgpFingerprint
|
||||
import org.pgpainless.key.generation.KeyRingBuilder
|
||||
import org.pgpainless.key.generation.KeySpec
|
||||
import org.pgpainless.key.protection.*
|
||||
|
@ -38,66 +41,38 @@ import org.pgpainless.signature.subpackets.*
|
|||
import org.pgpainless.util.Passphrase
|
||||
import org.pgpainless.util.selection.userid.SelectUserId
|
||||
|
||||
class SecretKeyRingEditor(
|
||||
var secretKeyRing: PGPSecretKeyRing,
|
||||
override val referenceTime: Date = Date()
|
||||
class SecretKeyRingEditor(key: OpenPGPKey,
|
||||
keyProtector: SecretKeyRingProtector,
|
||||
override val referenceTime: Date = Date()
|
||||
) : SecretKeyRingEditorInterface {
|
||||
|
||||
private var editor: OpenPGPKeyEditor = OpenPGPKeyEditor(key, keyProtector, PGPainless.getInstance().implementation)
|
||||
|
||||
constructor(
|
||||
secretKey: PGPSecretKeyRing,
|
||||
referenceTime: Date = Date(),
|
||||
keyProtector: SecretKeyRingProtector
|
||||
) : this(secretKey.toOpenPGPKey(), keyProtector, referenceTime)
|
||||
|
||||
override fun addUserId(
|
||||
userId: CharSequence,
|
||||
callback: SelfSignatureSubpackets.Callback?,
|
||||
protector: SecretKeyRingProtector
|
||||
callback: SelfSignatureSubpackets.Callback?
|
||||
): SecretKeyRingEditorInterface {
|
||||
val sanitizedUserId = sanitizeUserId(userId).toString()
|
||||
val primaryKey = secretKeyRing.secretKey
|
||||
|
||||
val info = inspectKeyRing(secretKeyRing, referenceTime)
|
||||
require(!info.isHardRevoked(userId)) {
|
||||
"User-ID $userId is hard revoked and cannot be re-certified."
|
||||
}
|
||||
|
||||
val (
|
||||
hashAlgorithmPreferences,
|
||||
symmetricKeyAlgorithmPreferences,
|
||||
compressionAlgorithmPreferences) =
|
||||
try {
|
||||
Triple(
|
||||
info.preferredHashAlgorithms,
|
||||
info.preferredSymmetricKeyAlgorithms,
|
||||
info.preferredCompressionAlgorithms)
|
||||
} catch (e: IllegalStateException) { // missing user-id sig
|
||||
val algorithmSuite = AlgorithmSuite.defaultAlgorithmSuite
|
||||
Triple(
|
||||
algorithmSuite.hashAlgorithms,
|
||||
algorithmSuite.symmetricKeyAlgorithms,
|
||||
algorithmSuite.compressionAlgorithms)
|
||||
editor.addUserId(sanitizedUserId, object : Callback {
|
||||
override fun apply(parameters: SignatureParameters): SignatureParameters {
|
||||
return parameters.setSignatureCreationTime(referenceTime)
|
||||
}
|
||||
|
||||
val builder =
|
||||
SelfSignatureBuilder(primaryKey, protector).apply {
|
||||
hashedSubpackets.setSignatureCreationTime(referenceTime)
|
||||
setSignatureType(SignatureType.POSITIVE_CERTIFICATION)
|
||||
}
|
||||
builder.hashedSubpackets.apply {
|
||||
setKeyFlags(info.getKeyFlagsOf(primaryKey.keyID))
|
||||
setPreferredHashAlgorithms(hashAlgorithmPreferences)
|
||||
setPreferredSymmetricKeyAlgorithms(symmetricKeyAlgorithmPreferences)
|
||||
setPreferredCompressionAlgorithms(compressionAlgorithmPreferences)
|
||||
setFeatures(Feature.MODIFICATION_DETECTION)
|
||||
}
|
||||
builder.applyCallback(callback)
|
||||
secretKeyRing =
|
||||
injectCertification(secretKeyRing, sanitizedUserId, builder.build(sanitizedUserId))
|
||||
})
|
||||
return this
|
||||
}
|
||||
|
||||
override fun addPrimaryUserId(
|
||||
userId: CharSequence,
|
||||
protector: SecretKeyRingProtector
|
||||
): SecretKeyRingEditorInterface {
|
||||
val uid = sanitizeUserId(userId)
|
||||
val primaryKey = secretKeyRing.publicKey
|
||||
var info = inspectKeyRing(secretKeyRing, referenceTime)
|
||||
val primaryKey = key.publicKey
|
||||
var info = inspectKeyRing(key, referenceTime)
|
||||
val primaryUserId = info.primaryUserId
|
||||
val signature =
|
||||
if (primaryUserId == null) info.latestDirectKeySelfSignature
|
||||
|
@ -116,18 +91,17 @@ class SecretKeyRingEditor(
|
|||
else setKeyExpirationTime(null)
|
||||
}
|
||||
}
|
||||
},
|
||||
protector)
|
||||
})
|
||||
|
||||
// unmark previous primary user-ids to be non-primary
|
||||
info = inspectKeyRing(secretKeyRing, referenceTime)
|
||||
info = inspectKeyRing(key, referenceTime)
|
||||
info.validAndExpiredUserIds
|
||||
.filterNot { it == uid }
|
||||
.forEach { otherUserId ->
|
||||
if (info
|
||||
.getLatestUserIdCertification(otherUserId)!!
|
||||
.hashedSubPackets
|
||||
.isPrimaryUserID) {
|
||||
.getLatestUserIdCertification(otherUserId)!!
|
||||
.hashedSubPackets
|
||||
.isPrimaryUserID) {
|
||||
// We need to unmark this user-id as primary
|
||||
addUserId(
|
||||
otherUserId,
|
||||
|
@ -140,34 +114,16 @@ class SecretKeyRingEditor(
|
|||
setKeyExpirationTime(null) // non-primary
|
||||
}
|
||||
}
|
||||
},
|
||||
protector)
|
||||
})
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
@Deprecated(
|
||||
"Use of SelectUserId class is deprecated.",
|
||||
replaceWith = ReplaceWith("removeUserId(protector, predicate)"))
|
||||
override fun removeUserId(
|
||||
selector: SelectUserId,
|
||||
protector: SecretKeyRingProtector
|
||||
): SecretKeyRingEditorInterface {
|
||||
return revokeUserIds(
|
||||
selector,
|
||||
protector,
|
||||
RevocationAttributes.createCertificateRevocation()
|
||||
.withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID)
|
||||
.withoutDescription())
|
||||
}
|
||||
|
||||
override fun removeUserId(
|
||||
protector: SecretKeyRingProtector,
|
||||
predicate: (String) -> Boolean
|
||||
): SecretKeyRingEditorInterface {
|
||||
return revokeUserIds(
|
||||
protector,
|
||||
RevocationAttributes.createCertificateRevocation()
|
||||
.withReason(RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID)
|
||||
.withoutDescription(),
|
||||
|
@ -175,23 +131,21 @@ class SecretKeyRingEditor(
|
|||
}
|
||||
|
||||
override fun removeUserId(
|
||||
userId: CharSequence,
|
||||
protector: SecretKeyRingProtector
|
||||
userId: CharSequence
|
||||
): SecretKeyRingEditorInterface {
|
||||
return removeUserId(protector) { uid -> userId == uid }
|
||||
return removeUserId { uid -> userId == uid }
|
||||
}
|
||||
|
||||
override fun replaceUserId(
|
||||
oldUserId: CharSequence,
|
||||
newUserId: CharSequence,
|
||||
protector: SecretKeyRingProtector
|
||||
newUserId: CharSequence
|
||||
): SecretKeyRingEditorInterface {
|
||||
val oldUID = sanitizeUserId(oldUserId)
|
||||
val newUID = sanitizeUserId(newUserId)
|
||||
require(oldUID.isNotBlank()) { "Old user-ID cannot be empty." }
|
||||
require(newUID.isNotBlank()) { "New user-ID cannot be empty." }
|
||||
|
||||
val info = inspectKeyRing(secretKeyRing, referenceTime)
|
||||
val info = inspectKeyRing(key, referenceTime)
|
||||
if (!info.isUserIdValid(oldUID)) {
|
||||
throw NoSuchElementException(
|
||||
"Key does not carry user-ID '$oldUID', or it is not valid.")
|
||||
|
@ -218,16 +172,14 @@ class SecretKeyRingEditor(
|
|||
oldCertification.unhashedSubPackets,
|
||||
unhashedSubpackets as SignatureSubpackets)
|
||||
}
|
||||
},
|
||||
protector)
|
||||
})
|
||||
|
||||
return revokeUserId(oldUID, protector)
|
||||
return revokeUserId(oldUID)
|
||||
}
|
||||
|
||||
override fun addSubKey(
|
||||
override fun addSubkey(
|
||||
keySpec: KeySpec,
|
||||
subkeyPassphrase: Passphrase,
|
||||
protector: SecretKeyRingProtector
|
||||
subkeyPassphrase: Passphrase
|
||||
): SecretKeyRingEditorInterface {
|
||||
val callback =
|
||||
object : SelfSignatureSubpackets.Callback {
|
||||
|
@ -237,34 +189,31 @@ class SecretKeyRingEditor(
|
|||
hashedSubpackets.setSignatureCreationTime(referenceTime)
|
||||
}
|
||||
}
|
||||
return addSubKey(keySpec, subkeyPassphrase, callback, protector)
|
||||
return addSubkey(keySpec, subkeyPassphrase, callback)
|
||||
}
|
||||
|
||||
override fun addSubKey(
|
||||
override fun addSubkey(
|
||||
keySpec: KeySpec,
|
||||
subkeyPassphrase: Passphrase,
|
||||
callback: SelfSignatureSubpackets.Callback?,
|
||||
protector: SecretKeyRingProtector
|
||||
callback: SelfSignatureSubpackets.Callback?
|
||||
): SecretKeyRingEditorInterface {
|
||||
val version = OpenPGPKeyVersion.from(secretKeyRing.getPublicKey().version)
|
||||
val version = OpenPGPKeyVersion.from(key.getPublicKey().version)
|
||||
val keyPair = KeyRingBuilder.generateKeyPair(keySpec, OpenPGPKeyVersion.v4, referenceTime)
|
||||
val subkeyProtector =
|
||||
PasswordBasedSecretKeyRingProtector.forKeyId(keyPair.keyIdentifier, subkeyPassphrase)
|
||||
val keyFlags = KeyFlag.fromBitmask(keySpec.subpackets.keyFlags).toMutableList()
|
||||
return addSubKey(
|
||||
return addSubkey(
|
||||
keyPair,
|
||||
callback,
|
||||
subkeyProtector,
|
||||
protector,
|
||||
keyFlags.removeFirst(),
|
||||
*keyFlags.toTypedArray())
|
||||
}
|
||||
|
||||
override fun addSubKey(
|
||||
override fun addSubkey(
|
||||
subkey: PGPKeyPair,
|
||||
callback: SelfSignatureSubpackets.Callback?,
|
||||
subkeyProtector: SecretKeyRingProtector,
|
||||
primaryKeyProtector: SecretKeyRingProtector,
|
||||
keyFlag: KeyFlag,
|
||||
vararg keyFlags: KeyFlag
|
||||
): SecretKeyRingEditorInterface {
|
||||
|
@ -277,11 +226,11 @@ class SecretKeyRingEditor(
|
|||
PGPainless.getPolicy()
|
||||
.publicKeyAlgorithmPolicy
|
||||
.isAcceptable(subkeyAlgorithm, bitStrength)) {
|
||||
"Public key algorithm policy violation: $subkeyAlgorithm with bit strength $bitStrength is not acceptable."
|
||||
}
|
||||
"Public key algorithm policy violation: $subkeyAlgorithm with bit strength $bitStrength is not acceptable."
|
||||
}
|
||||
|
||||
val primaryKey = secretKeyRing.secretKey
|
||||
val info = inspectKeyRing(secretKeyRing, referenceTime)
|
||||
val primaryKey = key.secretKey
|
||||
val info = inspectKeyRing(key, referenceTime)
|
||||
val hashAlgorithm =
|
||||
HashAlgorithmNegotiator.negotiateSignatureHashAlgorithm(PGPainless.getPolicy())
|
||||
.negotiateHashAlgorithm(info.preferredHashAlgorithms)
|
||||
|
@ -309,61 +258,60 @@ class SecretKeyRingEditor(
|
|||
secretSubkey =
|
||||
KeyRingUtils.secretKeyPlusSignature(
|
||||
secretSubkey, skBindingBuilder.build(secretSubkey.publicKey))
|
||||
secretKeyRing = KeyRingUtils.keysPlusSecretKey(secretKeyRing, secretSubkey)
|
||||
key = KeyRingUtils.keysPlusSecretKey(key, secretSubkey)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun revoke(
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): SecretKeyRingEditorInterface {
|
||||
return revoke(protector, callbackFromRevocationAttributes(revocationAttributes))
|
||||
return revoke(callbackFromRevocationAttributes(revocationAttributes))
|
||||
}
|
||||
|
||||
override fun revoke(
|
||||
protector: SecretKeyRingProtector,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
): SecretKeyRingEditorInterface {
|
||||
return revokeSubKey(secretKeyRing.secretKey.keyID, protector, callback)
|
||||
editor.revokeKey(object : SignatureParameters.Callback {
|
||||
override fun apply(parameters: SignatureParameters?): SignatureParameters {
|
||||
if (callback != null) {
|
||||
callback.modifyHashedSubpackets()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun revokeSubKey(
|
||||
subkeyId: Long,
|
||||
protector: SecretKeyRingProtector,
|
||||
override fun revokeSubkey(
|
||||
subkeyIdentifier: KeyIdentifier,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): SecretKeyRingEditorInterface {
|
||||
return revokeSubKey(
|
||||
subkeyId, protector, callbackFromRevocationAttributes(revocationAttributes))
|
||||
return revokeSubkey(subkeyIdentifier, callbackFromRevocationAttributes(revocationAttributes))
|
||||
}
|
||||
|
||||
override fun revokeSubKey(
|
||||
override fun revokeSubkey(
|
||||
subkeyId: Long,
|
||||
protector: SecretKeyRingProtector,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
): SecretKeyRingEditorInterface {
|
||||
val revokeeSubKey = secretKeyRing.requirePublicKey(subkeyId)
|
||||
val subkeyRevocation = generateRevocation(protector, revokeeSubKey, callback)
|
||||
secretKeyRing = injectCertification(secretKeyRing, revokeeSubKey, subkeyRevocation)
|
||||
val revokeeSubKey = key.requirePublicKey(subkeyId)
|
||||
val subkeyRevocation = generateRevocation(revokeeSubKey, callback)
|
||||
key = injectCertification(key, revokeeSubKey, subkeyRevocation)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun revokeUserId(
|
||||
userId: CharSequence,
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): SecretKeyRingEditorInterface {
|
||||
if (revocationAttributes != null) {
|
||||
require(
|
||||
revocationAttributes.reason == RevocationAttributes.Reason.NO_REASON ||
|
||||
revocationAttributes.reason ==
|
||||
RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID) {
|
||||
"Revocation reason must either be NO_REASON or USER_ID_NO_LONGER_VALID"
|
||||
}
|
||||
RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID) {
|
||||
"Revocation reason must either be NO_REASON or USER_ID_NO_LONGER_VALID"
|
||||
}
|
||||
}
|
||||
|
||||
return revokeUserId(
|
||||
userId,
|
||||
protector,
|
||||
object : RevocationSignatureSubpackets.Callback {
|
||||
override fun modifyHashedSubpackets(
|
||||
hashedSubpackets: RevocationSignatureSubpackets
|
||||
|
@ -377,19 +325,16 @@ class SecretKeyRingEditor(
|
|||
|
||||
override fun revokeUserId(
|
||||
userId: CharSequence,
|
||||
protector: SecretKeyRingProtector,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
): SecretKeyRingEditorInterface {
|
||||
return revokeUserIds(protector, callback, SelectUserId.exactMatch(sanitizeUserId(userId)))
|
||||
return revokeUserIds(callback, SelectUserId.exactMatch(sanitizeUserId(userId)))
|
||||
}
|
||||
|
||||
override fun revokeUserIds(
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?,
|
||||
predicate: (String) -> Boolean
|
||||
): SecretKeyRingEditorInterface {
|
||||
return revokeUserIds(
|
||||
protector,
|
||||
object : RevocationSignatureSubpackets.Callback {
|
||||
override fun modifyHashedSubpackets(
|
||||
hashedSubpackets: RevocationSignatureSubpackets
|
||||
|
@ -402,7 +347,6 @@ class SecretKeyRingEditor(
|
|||
}
|
||||
|
||||
override fun revokeUserIds(
|
||||
protector: SecretKeyRingProtector,
|
||||
callback: RevocationSignatureSubpackets.Callback?,
|
||||
predicate: (String) -> Boolean
|
||||
): SecretKeyRingEditorInterface {
|
||||
|
@ -411,38 +355,36 @@ class SecretKeyRingEditor(
|
|||
if (it.isEmpty())
|
||||
throw NoSuchElementException("No matching user-ids found on the key.")
|
||||
}
|
||||
.forEach { userId -> doRevokeUserId(userId, protector, callback) }
|
||||
.forEach { userId -> doRevokeUserId(userId, callback) }
|
||||
return this
|
||||
}
|
||||
|
||||
override fun setExpirationDate(
|
||||
expiration: Date?,
|
||||
protector: SecretKeyRingProtector
|
||||
expiration: Date?
|
||||
): SecretKeyRingEditorInterface {
|
||||
require(secretKeyRing.secretKey.isMasterKey) {
|
||||
require(key.secretKey.isMasterKey) {
|
||||
"OpenPGP key does not appear to contain a primary secret key."
|
||||
}
|
||||
|
||||
val prevDirectKeySig = getPreviousDirectKeySignature()
|
||||
// reissue direct key sig
|
||||
if (prevDirectKeySig != null) {
|
||||
secretKeyRing =
|
||||
key =
|
||||
injectCertification(
|
||||
secretKeyRing,
|
||||
secretKeyRing.publicKey,
|
||||
reissueDirectKeySignature(expiration, protector, prevDirectKeySig))
|
||||
key,
|
||||
key.publicKey,
|
||||
reissueDirectKeySignature(expiration, prevDirectKeySig))
|
||||
}
|
||||
|
||||
val primaryUserId =
|
||||
inspectKeyRing(secretKeyRing, referenceTime).getPossiblyExpiredPrimaryUserId()
|
||||
val primaryUserId = inspectKeyRing(key, referenceTime).getPossiblyExpiredPrimaryUserId()
|
||||
if (primaryUserId != null) {
|
||||
val prevUserIdSig = getPreviousUserIdSignatures(primaryUserId)
|
||||
val userIdSig =
|
||||
reissuePrimaryUserIdSig(expiration, protector, primaryUserId, prevUserIdSig!!)
|
||||
secretKeyRing = injectCertification(secretKeyRing, primaryUserId, userIdSig)
|
||||
reissuePrimaryUserIdSig(expiration, primaryUserId, prevUserIdSig!!)
|
||||
key = injectCertification(key, primaryUserId, userIdSig)
|
||||
}
|
||||
|
||||
val info = inspectKeyRing(secretKeyRing, referenceTime)
|
||||
val info = inspectKeyRing(key, referenceTime)
|
||||
for (userId in info.validUserIds) {
|
||||
if (userId == primaryUserId) {
|
||||
continue
|
||||
|
@ -453,11 +395,11 @@ class SecretKeyRingEditor(
|
|||
?: throw AssertionError(
|
||||
"A valid user-id shall never have no user-id signature.")
|
||||
if (prevUserIdSig.hashedSubPackets.isPrimaryUserID) {
|
||||
secretKeyRing =
|
||||
key =
|
||||
injectCertification(
|
||||
secretKeyRing,
|
||||
key,
|
||||
primaryUserId!!,
|
||||
reissueNonPrimaryUserId(protector, userId, prevUserIdSig))
|
||||
reissueNonPrimaryUserId(userId, prevUserIdSig))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,28 +408,26 @@ class SecretKeyRingEditor(
|
|||
|
||||
override fun setExpirationDateOfSubkey(
|
||||
expiration: Date?,
|
||||
keyId: Long,
|
||||
protector: SecretKeyRingProtector
|
||||
keyIdentifier: KeyIdentifier
|
||||
): SecretKeyRingEditorInterface = apply {
|
||||
// is primary key
|
||||
if (keyId == secretKeyRing.publicKey.keyID) {
|
||||
return setExpirationDate(expiration, protector)
|
||||
if (keyId == key.publicKey.keyID) {
|
||||
return setExpirationDate(expiration)
|
||||
}
|
||||
|
||||
// is subkey
|
||||
val subkey =
|
||||
secretKeyRing.getPublicKey(keyId)
|
||||
key.getPublicKey(keyId)
|
||||
?: throw NoSuchElementException("No subkey with ID ${keyId.openPgpKeyId()} found.")
|
||||
val prevBinding =
|
||||
inspectKeyRing(secretKeyRing).getCurrentSubkeyBindingSignature(keyId)
|
||||
inspectKeyRing(key).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)
|
||||
val bindingSig = reissueSubkeyBindingSignature(subkey, expiration, prevBinding)
|
||||
key = injectCertification(key, subkey, bindingSig)
|
||||
}
|
||||
|
||||
override fun createMinimalRevocationCertificate(
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): PGPPublicKeyRing {
|
||||
// Check reason
|
||||
|
@ -497,51 +437,34 @@ class SecretKeyRingEditor(
|
|||
}
|
||||
}
|
||||
|
||||
val revocation = createRevocation(protector, revocationAttributes)
|
||||
var primaryKey = secretKeyRing.secretKey.publicKey
|
||||
val revocation = createRevocation(revocationAttributes)
|
||||
var primaryKey = key.secretKey.publicKey
|
||||
primaryKey = KeyRingUtils.getStrippedDownPublicKey(primaryKey)
|
||||
primaryKey = PGPPublicKey.addCertification(primaryKey, revocation)
|
||||
return PGPPublicKeyRing(listOf(primaryKey))
|
||||
}
|
||||
|
||||
override fun createRevocation(
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): PGPSignature {
|
||||
return generateRevocation(
|
||||
protector,
|
||||
secretKeyRing.publicKey,
|
||||
key.publicKey, callbackFromRevocationAttributes(revocationAttributes))
|
||||
}
|
||||
|
||||
override fun createRevocation(
|
||||
subkeyIdentifier: KeyIdentifier,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): PGPSignature {
|
||||
return generateRevocation(
|
||||
key.requirePublicKey(subkeyId),
|
||||
callbackFromRevocationAttributes(revocationAttributes))
|
||||
}
|
||||
|
||||
override fun createRevocation(
|
||||
subkeyId: Long,
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): PGPSignature {
|
||||
return generateRevocation(
|
||||
protector,
|
||||
secretKeyRing.requirePublicKey(subkeyId),
|
||||
callbackFromRevocationAttributes(revocationAttributes))
|
||||
}
|
||||
|
||||
override fun createRevocation(
|
||||
subkeyId: Long,
|
||||
protector: SecretKeyRingProtector,
|
||||
subkeyIdentifier: KeyIdentifier,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
): PGPSignature {
|
||||
return generateRevocation(protector, secretKeyRing.requirePublicKey(subkeyId), callback)
|
||||
}
|
||||
|
||||
override fun createRevocation(
|
||||
subkeyFingerprint: OpenPgpFingerprint,
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): PGPSignature {
|
||||
return generateRevocation(
|
||||
protector,
|
||||
secretKeyRing.requirePublicKey(subkeyFingerprint),
|
||||
callbackFromRevocationAttributes(revocationAttributes))
|
||||
return generateRevocation(key.requirePublicKey(subkeyId), callback)
|
||||
}
|
||||
|
||||
override fun changePassphraseFromOldPassphrase(
|
||||
|
@ -567,12 +490,12 @@ class SecretKeyRingEditor(
|
|||
mapOf(keyIdentifier to oldPassphrase), oldProtectionSettings, null))
|
||||
}
|
||||
|
||||
override fun done(): PGPSecretKeyRing {
|
||||
return secretKeyRing
|
||||
override fun done(): OpenPGPKey {
|
||||
return editor.done()
|
||||
}
|
||||
|
||||
private fun sanitizeUserId(userId: CharSequence): CharSequence =
|
||||
// TODO: Further research how to sanitize user IDs.
|
||||
// TODO: Further research how to sanitize user IDs.
|
||||
// e.g. what about newlines?
|
||||
userId.toString().trim()
|
||||
|
||||
|
@ -586,45 +509,39 @@ class SecretKeyRingEditor(
|
|||
}
|
||||
|
||||
private fun generateRevocation(
|
||||
protector: SecretKeyRingProtector,
|
||||
revokeeSubkey: PGPPublicKey,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
): PGPSignature {
|
||||
val primaryKey = secretKeyRing.secretKey
|
||||
val primaryKey = key.secretKey
|
||||
val signatureType =
|
||||
if (revokeeSubkey.isMasterKey) SignatureType.KEY_REVOCATION
|
||||
else SignatureType.SUBKEY_REVOCATION
|
||||
|
||||
return RevocationSignatureBuilder(signatureType, primaryKey, protector)
|
||||
return RevocationSignatureBuilder(signatureType, primaryKey)
|
||||
.apply { applyCallback(callback) }
|
||||
.build(revokeeSubkey)
|
||||
}
|
||||
|
||||
private fun doRevokeUserId(
|
||||
userId: CharSequence,
|
||||
protector: SecretKeyRingProtector,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
): SecretKeyRingEditorInterface {
|
||||
RevocationSignatureBuilder(
|
||||
SignatureType.CERTIFICATION_REVOCATION, secretKeyRing.secretKey, protector)
|
||||
RevocationSignatureBuilder(SignatureType.CERTIFICATION_REVOCATION, key.secretKey)
|
||||
.apply {
|
||||
hashedSubpackets.setSignatureCreationTime(referenceTime)
|
||||
applyCallback(callback)
|
||||
}
|
||||
.let {
|
||||
secretKeyRing =
|
||||
injectCertification(secretKeyRing, userId, it.build(userId.toString()))
|
||||
}
|
||||
.let { key = injectCertification(key, userId, it.build(userId.toString())) }
|
||||
return this
|
||||
}
|
||||
|
||||
private fun getPreviousDirectKeySignature(): PGPSignature? {
|
||||
val info = inspectKeyRing(secretKeyRing, referenceTime)
|
||||
val info = inspectKeyRing(key, referenceTime)
|
||||
return info.latestDirectKeySelfSignature
|
||||
}
|
||||
|
||||
private fun getPreviousUserIdSignatures(userId: String): PGPSignature? {
|
||||
val info = inspectKeyRing(secretKeyRing, referenceTime)
|
||||
val info = inspectKeyRing(key, referenceTime)
|
||||
return info.getLatestUserIdCertification(userId)
|
||||
}
|
||||
|
||||
|
@ -634,8 +551,7 @@ class SecretKeyRingEditor(
|
|||
userId: String,
|
||||
prevUserIdSig: PGPSignature
|
||||
): PGPSignature {
|
||||
val builder =
|
||||
SelfSignatureBuilder(secretKeyRing.secretKey, secretKeyRingProtector, prevUserIdSig)
|
||||
val builder = SelfSignatureBuilder(key.secretKey, secretKeyRingProtector, prevUserIdSig)
|
||||
builder.hashedSubpackets.setSignatureCreationTime(referenceTime)
|
||||
builder.applyCallback(
|
||||
object : SelfSignatureSubpackets.Callback {
|
||||
|
@ -654,7 +570,7 @@ class SecretKeyRingEditor(
|
|||
@Nonnull primaryUserId: String,
|
||||
@Nonnull prevUserIdSig: PGPSignature
|
||||
): PGPSignature {
|
||||
return SelfSignatureBuilder(secretKeyRing.secretKey, secretKeyRingProtector, prevUserIdSig)
|
||||
return SelfSignatureBuilder(key.secretKey, secretKeyRingProtector, prevUserIdSig)
|
||||
.apply {
|
||||
hashedSubpackets.setSignatureCreationTime(referenceTime)
|
||||
applyCallback(
|
||||
|
@ -664,7 +580,7 @@ class SecretKeyRingEditor(
|
|||
) {
|
||||
if (expiration != null) {
|
||||
hashedSubpackets.setKeyExpirationTime(
|
||||
true, secretKeyRing.publicKey.creationTime, expiration)
|
||||
true, key.publicKey.creationTime, expiration)
|
||||
} else {
|
||||
hashedSubpackets.setKeyExpirationTime(KeyExpirationTime(true, 0))
|
||||
}
|
||||
|
@ -682,7 +598,7 @@ class SecretKeyRingEditor(
|
|||
prevDirectKeySig: PGPSignature
|
||||
): PGPSignature {
|
||||
return DirectKeySelfSignatureBuilder(
|
||||
secretKeyRing.secretKey, secretKeyRingProtector, prevDirectKeySig)
|
||||
key.secretKey, secretKeyRingProtector, prevDirectKeySig)
|
||||
.apply {
|
||||
hashedSubpackets.setSignatureCreationTime(referenceTime)
|
||||
applyCallback(
|
||||
|
@ -692,7 +608,7 @@ class SecretKeyRingEditor(
|
|||
) {
|
||||
if (expiration != null) {
|
||||
hashedSubpackets.setKeyExpirationTime(
|
||||
secretKeyRing.publicKey.creationTime, expiration)
|
||||
key.publicKey.creationTime, expiration)
|
||||
} else {
|
||||
hashedSubpackets.setKeyExpirationTime(null)
|
||||
}
|
||||
|
@ -708,9 +624,9 @@ class SecretKeyRingEditor(
|
|||
protector: SecretKeyRingProtector,
|
||||
prevSubkeyBindingSignature: PGPSignature
|
||||
): PGPSignature {
|
||||
val primaryKey = secretKeyRing.publicKey
|
||||
val secretPrimaryKey = secretKeyRing.secretKey
|
||||
val secretSubkey: PGPSecretKey? = secretKeyRing.getSecretKey(subkey.keyID)
|
||||
val primaryKey = key.publicKey
|
||||
val secretPrimaryKey = key.secretKey
|
||||
val secretSubkey: PGPSecretKey? = key.getSecretKey(subkey.keyID)
|
||||
|
||||
val builder =
|
||||
SubkeyBindingSignatureBuilder(secretPrimaryKey, protector, prevSubkeyBindingSignature)
|
||||
|
@ -742,7 +658,7 @@ class SecretKeyRingEditor(
|
|||
}
|
||||
|
||||
private fun selectUserIds(predicate: Predicate<String>): List<String> =
|
||||
inspectKeyRing(secretKeyRing).validUserIds.filter { predicate.test(it) }
|
||||
inspectKeyRing(key).validUserIds.filter { predicate.test(it) }
|
||||
|
||||
private class WithKeyRingEncryptionSettingsImpl(
|
||||
private val editor: SecretKeyRingEditor,
|
||||
|
@ -772,15 +688,15 @@ class SecretKeyRingEditor(
|
|||
val protector =
|
||||
PasswordBasedSecretKeyRingProtector(
|
||||
newProtectionSettings, SolitaryPassphraseProvider(passphrase))
|
||||
val secretKeys = changePassphrase(keyId, editor.secretKeyRing, oldProtector, protector)
|
||||
editor.secretKeyRing = secretKeys
|
||||
val secretKeys = changePassphrase(keyId, editor.key, oldProtector, protector)
|
||||
editor.key = secretKeys
|
||||
return editor
|
||||
}
|
||||
|
||||
override fun toNoPassphrase(): SecretKeyRingEditorInterface {
|
||||
val protector = UnprotectedKeysProtector()
|
||||
val secretKeys = changePassphrase(keyId, editor.secretKeyRing, oldProtector, protector)
|
||||
editor.secretKeyRing = secretKeys
|
||||
val secretKeys = changePassphrase(keyId, editor.key, oldProtector, protector)
|
||||
editor.key = secretKeys
|
||||
return editor
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.security.NoSuchAlgorithmException
|
|||
import java.util.*
|
||||
import org.bouncycastle.bcpg.KeyIdentifier
|
||||
import org.bouncycastle.openpgp.*
|
||||
import org.bouncycastle.openpgp.api.OpenPGPKey
|
||||
import org.pgpainless.algorithm.KeyFlag
|
||||
import org.pgpainless.key.OpenPgpFingerprint
|
||||
import org.pgpainless.key.generation.KeySpec
|
||||
|
@ -19,7 +20,6 @@ import org.pgpainless.key.util.RevocationAttributes
|
|||
import org.pgpainless.signature.subpackets.RevocationSignatureSubpackets
|
||||
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets
|
||||
import org.pgpainless.util.Passphrase
|
||||
import org.pgpainless.util.selection.userid.SelectUserId
|
||||
|
||||
interface SecretKeyRingEditorInterface {
|
||||
|
||||
|
@ -33,28 +33,23 @@ interface SecretKeyRingEditorInterface {
|
|||
* Add a user-id to the key ring.
|
||||
*
|
||||
* @param userId user-id
|
||||
* @param protector protector to unlock the secret key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a signature for the user-id
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun addUserId(userId: CharSequence, protector: SecretKeyRingProtector) =
|
||||
addUserId(userId, null, protector)
|
||||
@Throws(PGPException::class) fun addUserId(userId: CharSequence) = addUserId(userId, null)
|
||||
|
||||
/**
|
||||
* Add a user-id to the key ring.
|
||||
*
|
||||
* @param userId user-id
|
||||
* @param callback callback to modify the self-signature subpackets
|
||||
* @param protector protector to unlock the secret key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a signature for the user-id
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun addUserId(
|
||||
userId: CharSequence,
|
||||
callback: SelfSignatureSubpackets.Callback? = null,
|
||||
protector: SecretKeyRingProtector
|
||||
callback: SelfSignatureSubpackets.Callback? = null
|
||||
): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
|
@ -62,48 +57,23 @@ interface SecretKeyRingEditorInterface {
|
|||
* new certification signature will be created.
|
||||
*
|
||||
* @param userId user id
|
||||
* @param protector protector to unlock the secret key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a signature for the user-id
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun addPrimaryUserId(
|
||||
userId: CharSequence,
|
||||
protector: SecretKeyRingProtector
|
||||
): SecretKeyRingEditorInterface
|
||||
fun addPrimaryUserId(userId: CharSequence): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
* Convenience method to revoke selected user-ids using soft revocation signatures. The
|
||||
* revocation will use [RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID], so that the
|
||||
* user-id can be re-certified at a later point.
|
||||
*
|
||||
* @param selector selector to select user-ids
|
||||
* @param protector protector to unlock the primary key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the user-id
|
||||
*/
|
||||
@Deprecated(
|
||||
"Use of SelectUserId class is deprecated.",
|
||||
ReplaceWith("removeUserId(protector, predicate)"))
|
||||
@Throws(PGPException::class)
|
||||
fun removeUserId(selector: SelectUserId, protector: SecretKeyRingProtector) =
|
||||
removeUserId(protector, selector)
|
||||
|
||||
/**
|
||||
* Convenience method to revoke selected user-ids using soft revocation signatures. The
|
||||
* revocation will use [RevocationAttributes.Reason.USER_ID_NO_LONGER_VALID], so that the
|
||||
* user-id can be re-certified at a later point.
|
||||
*
|
||||
* @param protector protector to unlock the primary key
|
||||
* @param predicate predicate to select user-ids for revocation
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the user-id
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun removeUserId(
|
||||
protector: SecretKeyRingProtector,
|
||||
predicate: (String) -> Boolean
|
||||
): SecretKeyRingEditorInterface
|
||||
fun removeUserId(predicate: (String) -> Boolean): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
* Convenience method to revoke a single user-id using a soft revocation signature. The
|
||||
|
@ -111,15 +81,11 @@ interface SecretKeyRingEditorInterface {
|
|||
* can be re-certified at a later point.
|
||||
*
|
||||
* @param userId user-id to revoke
|
||||
* @param protector protector to unlock the primary key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the user-id
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun removeUserId(
|
||||
userId: CharSequence,
|
||||
protector: SecretKeyRingProtector
|
||||
): SecretKeyRingEditorInterface
|
||||
fun removeUserId(userId: CharSequence): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
* Replace a user-id on the key with a new one. The old user-id gets soft revoked and the new
|
||||
|
@ -130,7 +96,6 @@ interface SecretKeyRingEditorInterface {
|
|||
*
|
||||
* @param oldUserId old user-id
|
||||
* @param newUserId new user-id
|
||||
* @param protector protector to unlock the secret key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation and certification signature
|
||||
* @throws java.util.NoSuchElementException if the old user-id was not found on the key; or if
|
||||
|
@ -139,8 +104,7 @@ interface SecretKeyRingEditorInterface {
|
|||
@Throws(PGPException::class)
|
||||
fun replaceUserId(
|
||||
oldUserId: CharSequence,
|
||||
newUserId: CharSequence,
|
||||
protector: SecretKeyRingProtector
|
||||
newUserId: CharSequence
|
||||
): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
|
@ -149,7 +113,6 @@ interface SecretKeyRingEditorInterface {
|
|||
* @param keySpec key specification
|
||||
* @param subkeyPassphrase passphrase to encrypt the sub key
|
||||
* @param callback callback to modify the subpackets of the subkey binding signature
|
||||
* @param protector protector to unlock the secret key of the key ring
|
||||
* @return the builder
|
||||
* @throws InvalidAlgorithmParameterException in case the user wants to use invalid parameters
|
||||
* for the key
|
||||
|
@ -162,11 +125,10 @@ interface SecretKeyRingEditorInterface {
|
|||
IOException::class,
|
||||
InvalidAlgorithmParameterException::class,
|
||||
NoSuchAlgorithmException::class)
|
||||
fun addSubKey(
|
||||
fun addSubkey(
|
||||
keySpec: KeySpec,
|
||||
subkeyPassphrase: Passphrase,
|
||||
callback: SelfSignatureSubpackets.Callback? = null,
|
||||
protector: SecretKeyRingProtector
|
||||
callback: SelfSignatureSubpackets.Callback? = null
|
||||
): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
|
@ -175,7 +137,6 @@ interface SecretKeyRingEditorInterface {
|
|||
* @param subkey subkey key pair
|
||||
* @param callback callback to modify the subpackets of the subkey binding signature
|
||||
* @param subkeyProtector protector to unlock and encrypt the subkey
|
||||
* @param primaryKeyProtector protector to unlock the primary key
|
||||
* @param keyFlag first mandatory key flag for the subkey
|
||||
* @param keyFlags optional additional key flags
|
||||
* @return builder
|
||||
|
@ -183,11 +144,10 @@ interface SecretKeyRingEditorInterface {
|
|||
* @throws IOException in case of an IO error
|
||||
*/
|
||||
@Throws(PGPException::class, IOException::class)
|
||||
fun addSubKey(
|
||||
fun addSubkey(
|
||||
subkey: PGPKeyPair,
|
||||
callback: SelfSignatureSubpackets.Callback?,
|
||||
subkeyProtector: SecretKeyRingProtector,
|
||||
primaryKeyProtector: SecretKeyRingProtector,
|
||||
keyFlag: KeyFlag,
|
||||
vararg keyFlags: KeyFlag
|
||||
): SecretKeyRingEditorInterface
|
||||
|
@ -195,42 +155,60 @@ interface SecretKeyRingEditorInterface {
|
|||
/**
|
||||
* Revoke the key ring using a hard revocation.
|
||||
*
|
||||
* @param protector protector of the primary key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revoke(protector: SecretKeyRingProtector) = revoke(protector, null as RevocationAttributes?)
|
||||
@Throws(PGPException::class) fun revoke() = revoke(null as RevocationAttributes?)
|
||||
|
||||
/**
|
||||
* Revoke the key ring using the provided revocation attributes. The attributes define, whether
|
||||
* the revocation was a hard revocation or not.
|
||||
*
|
||||
* @param protector protector of the primary key
|
||||
* @param revocationAttributes reason for the revocation
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revoke(
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes? = null
|
||||
): SecretKeyRingEditorInterface
|
||||
fun revoke(revocationAttributes: RevocationAttributes? = null): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
* Revoke the key ring. You can use the [RevocationSignatureSubpackets.Callback] to modify the
|
||||
* revocation signatures subpackets, e.g. in order to define whether this is a hard or soft
|
||||
* revocation.
|
||||
*
|
||||
* @param protector protector to unlock the primary secret key
|
||||
* @param callback callback to modify the revocations subpackets
|
||||
* @return builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revoke(
|
||||
protector: SecretKeyRingProtector,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
fun revoke(callback: RevocationSignatureSubpackets.Callback?): SecretKeyRingEditorInterface
|
||||
|
||||
fun revokeSubkey(subkeyIdentifier: KeyIdentifier) = revokeSubkey(subkeyIdentifier, null)
|
||||
|
||||
/**
|
||||
* Revoke the subkey binding signature of a subkey. The subkey with the provided fingerprint
|
||||
* will be revoked. If no suitable subkey is found, a [NoSuchElementException] will be thrown.
|
||||
*
|
||||
* @param fingerprint fingerprint of the subkey to be revoked
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the subkey
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
@Deprecated("Pass in the subkeys KeyIdentifier instead.")
|
||||
fun revokeSubkey(fingerprint: OpenPgpFingerprint) = revokeSubkey(fingerprint.keyIdentifier)
|
||||
|
||||
/**
|
||||
* Revoke the subkey binding signature of a subkey. The subkey with the provided fingerprint
|
||||
* will be revoked. If no suitable subkey is found, a [NoSuchElementException] will be thrown.
|
||||
*
|
||||
* @param subkeyIdentifier identifier of the subkey to be revoked
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the subkey
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revokeSubkey(
|
||||
subkeyIdentifier: KeyIdentifier,
|
||||
revocationAttributes: RevocationAttributes? = null
|
||||
): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
|
@ -238,61 +216,44 @@ interface SecretKeyRingEditorInterface {
|
|||
* will be revoked. If no suitable subkey is found, a [NoSuchElementException] will be thrown.
|
||||
*
|
||||
* @param fingerprint fingerprint of the subkey to be revoked
|
||||
* @param protector protector to unlock the primary key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the subkey
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revokeSubKey(fingerprint: OpenPgpFingerprint, protector: SecretKeyRingProtector) =
|
||||
revokeSubKey(fingerprint, protector, null)
|
||||
|
||||
/**
|
||||
* Revoke the subkey binding signature of a subkey. The subkey with the provided fingerprint
|
||||
* will be revoked. If no suitable subkey is found, a [NoSuchElementException] will be thrown.
|
||||
*
|
||||
* @param fingerprint fingerprint of the subkey to be revoked
|
||||
* @param protector protector to unlock the primary key
|
||||
* @param revocationAttributes reason for the revocation
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the subkey
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revokeSubKey(
|
||||
@Deprecated("Pass in the subkeys KeyIdentifier instead.")
|
||||
fun revokeSubkey(
|
||||
fingerprint: OpenPgpFingerprint,
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes? = null
|
||||
): SecretKeyRingEditorInterface =
|
||||
revokeSubKey(fingerprint.keyId, protector, revocationAttributes)
|
||||
): SecretKeyRingEditorInterface = revokeSubkey(fingerprint.keyIdentifier, revocationAttributes)
|
||||
|
||||
/**
|
||||
* Revoke the subkey binding signature of a subkey. The subkey with the provided key-id will be
|
||||
* revoked. If no suitable subkey is found, a [NoSuchElementException] will be thrown.
|
||||
*
|
||||
* @param subkeyId id of the subkey
|
||||
* @param protector protector to unlock the primary key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the subkey
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revokeSubKey(subkeyId: Long, protector: SecretKeyRingProtector) =
|
||||
revokeSubKey(subkeyId, protector, null as RevocationAttributes?)
|
||||
@Deprecated("Pass in the keys KeyIdentifier instead.")
|
||||
fun revokeSubkey(subkeyId: Long) =
|
||||
revokeSubkey(KeyIdentifier(subkeyId), null as RevocationAttributes?)
|
||||
|
||||
/**
|
||||
* Revoke the subkey binding signature of a subkey. The subkey with the provided key-id will be
|
||||
* revoked. If no suitable subkey is found, a [NoSuchElementException] will be thrown.
|
||||
*
|
||||
* @param subkeyId id of the subkey
|
||||
* @param protector protector to unlock the primary key
|
||||
* @param revocationAttributes reason for the revocation
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the subkey
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revokeSubKey(
|
||||
fun revokeSubkey(
|
||||
subkeyId: Long,
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes? = null
|
||||
): SecretKeyRingEditorInterface
|
||||
): SecretKeyRingEditorInterface = revokeSubkey(KeyIdentifier(subkeyId), revocationAttributes)
|
||||
|
||||
/**
|
||||
* Revoke the subkey binding signature of a subkey. The subkey with the provided key-id will be
|
||||
|
@ -301,16 +262,14 @@ interface SecretKeyRingEditorInterface {
|
|||
* The provided subpackets callback is used to modify the revocation signatures subpackets.
|
||||
*
|
||||
* @param subkeyId id of the subkey
|
||||
* @param protector protector to unlock the secret key ring
|
||||
* @param callback callback which can be used to modify the subpackets of the revocation
|
||||
* signature
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the subkey
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revokeSubKey(
|
||||
fun revokeSubkey(
|
||||
subkeyId: Long,
|
||||
protector: SecretKeyRingProtector,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
): SecretKeyRingEditorInterface
|
||||
|
||||
|
@ -318,19 +277,16 @@ interface SecretKeyRingEditorInterface {
|
|||
* Hard-revoke the given userID.
|
||||
*
|
||||
* @param userId userId to revoke
|
||||
* @param protector protector to unlock the primary key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the user-id
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revokeUserId(userId: CharSequence, protector: SecretKeyRingProtector) =
|
||||
revokeUserId(userId, protector, null as RevocationAttributes?)
|
||||
fun revokeUserId(userId: CharSequence) = revokeUserId(userId, null as RevocationAttributes?)
|
||||
|
||||
/**
|
||||
* Revoke the given userID using the provided revocation attributes.
|
||||
*
|
||||
* @param userId userId to revoke
|
||||
* @param protector protector to unlock the primary key
|
||||
* @param revocationAttributes reason for the revocation
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the user-id
|
||||
|
@ -338,7 +294,6 @@ interface SecretKeyRingEditorInterface {
|
|||
@Throws(PGPException::class)
|
||||
fun revokeUserId(
|
||||
userId: CharSequence,
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes? = null
|
||||
): SecretKeyRingEditorInterface
|
||||
|
||||
|
@ -350,7 +305,6 @@ interface SecretKeyRingEditorInterface {
|
|||
* revocation reason in the signatures hashed area using the subpacket callback.
|
||||
*
|
||||
* @param userId userid to be revoked
|
||||
* @param protector protector to unlock the primary secret key
|
||||
* @param callback callback to modify the revocations subpackets
|
||||
* @return builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the user-id
|
||||
|
@ -358,41 +312,16 @@ interface SecretKeyRingEditorInterface {
|
|||
@Throws(PGPException::class)
|
||||
fun revokeUserId(
|
||||
userId: CharSequence,
|
||||
protector: SecretKeyRingProtector,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
* Revoke all user-ids that match the provided [SelectUserId] filter. The provided
|
||||
* [RevocationAttributes] will be set as reason for revocation in each revocation signature.
|
||||
* Revoke all user-ids that match the provided [predicate]. The provided [RevocationAttributes]
|
||||
* will be set as reason for revocation in each revocation signature.
|
||||
*
|
||||
* Note: If you intend to re-certify these user-ids at a later point, make sure to choose a soft
|
||||
* revocation reason. See [RevocationAttributes.Reason] for more information.
|
||||
*
|
||||
* @param selector user-id selector
|
||||
* @param protector protector to unlock the primary secret key
|
||||
* @param revocationAttributes revocation attributes
|
||||
* @return builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the user-id
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
@Deprecated(
|
||||
"Use of SelectUserId class is deprecated.",
|
||||
ReplaceWith("revokeUserIds(protector, revocationAttributes, predicate)"))
|
||||
fun revokeUserIds(
|
||||
selector: SelectUserId,
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
) = revokeUserIds(protector, revocationAttributes, selector)
|
||||
|
||||
/**
|
||||
* Revoke all user-ids that match the provided [SelectUserId] filter. The provided
|
||||
* [RevocationAttributes] will be set as reason for revocation in each revocation signature.
|
||||
*
|
||||
* Note: If you intend to re-certify these user-ids at a later point, make sure to choose a soft
|
||||
* revocation reason. See [RevocationAttributes.Reason] for more information.
|
||||
*
|
||||
* @param protector protector to unlock the primary secret key
|
||||
* @param revocationAttributes revocation attributes
|
||||
* @param predicate to select user-ids for revocation
|
||||
* @return builder
|
||||
|
@ -400,13 +329,12 @@ interface SecretKeyRingEditorInterface {
|
|||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revokeUserIds(
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?,
|
||||
predicate: (String) -> Boolean
|
||||
): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
* Revoke all user-ids that match the provided [SelectUserId] filter. The provided
|
||||
* Revoke all user-ids that match the provided [predicate]. The provided
|
||||
* [RevocationSignatureSubpackets.Callback] will be used to modify the revocation signatures
|
||||
* subpackets.
|
||||
*
|
||||
|
@ -415,33 +343,6 @@ interface SecretKeyRingEditorInterface {
|
|||
*
|
||||
* See [RevocationAttributes.Reason] for more information.
|
||||
*
|
||||
* @param selector user-id selector
|
||||
* @param protector protector to unlock the primary secret key
|
||||
* @param callback callback to modify the revocations subpackets
|
||||
* @return builder
|
||||
* @throws PGPException in case we cannot generate a revocation signature for the user-id
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
@Deprecated(
|
||||
"Use of SelectUserId class is deprecated.",
|
||||
ReplaceWith("revokeUserIds(protector, callback, predicate)"))
|
||||
fun revokeUserIds(
|
||||
selector: SelectUserId,
|
||||
protector: SecretKeyRingProtector,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
) = revokeUserIds(protector, callback, selector)
|
||||
|
||||
/**
|
||||
* Revoke all user-ids that match the provided [SelectUserId] filter. The provided
|
||||
* [RevocationSignatureSubpackets.Callback] will be used to modify the revocation signatures
|
||||
* subpackets.
|
||||
*
|
||||
* Note: If you intend to re-certify these user-ids at a later point, make sure to set a soft
|
||||
* revocation reason in the revocation signatures hashed subpacket area using the callback.
|
||||
*
|
||||
* See [RevocationAttributes.Reason] for more information.
|
||||
*
|
||||
* @param protector protector to unlock the primary secret key
|
||||
* @param callback callback to modify the revocations subpackets
|
||||
* @param predicate to select user-ids for revocation
|
||||
* @return builder
|
||||
|
@ -449,7 +350,6 @@ interface SecretKeyRingEditorInterface {
|
|||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun revokeUserIds(
|
||||
protector: SecretKeyRingProtector,
|
||||
callback: RevocationSignatureSubpackets.Callback?,
|
||||
predicate: (String) -> Boolean
|
||||
): SecretKeyRingEditorInterface
|
||||
|
@ -459,15 +359,28 @@ interface SecretKeyRingEditorInterface {
|
|||
* expire, then an expiration date of null is expected.
|
||||
*
|
||||
* @param expiration new expiration date or null
|
||||
* @param protector to unlock the secret key
|
||||
* @return the builder
|
||||
* @throws PGPException in case we cannot generate a new self-signature with the changed
|
||||
* expiration date
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun setExpirationDate(
|
||||
fun setExpirationDate(expiration: Date?): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
* Set the expiration date for the subkey identified by the given [KeyIdentifier] 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 keyIdentifier identifier of the subkey
|
||||
* @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?,
|
||||
protector: SecretKeyRingProtector
|
||||
keyIdentifier: KeyIdentifier
|
||||
): SecretKeyRingEditorInterface
|
||||
|
||||
/**
|
||||
|
@ -476,31 +389,26 @@ interface SecretKeyRingEditorInterface {
|
|||
*
|
||||
* @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
|
||||
@Deprecated("Pass in the subkeys KeyIdentifier instead.")
|
||||
fun setExpirationDateOfSubkey(expiration: Date?, keyId: Long): SecretKeyRingEditorInterface =
|
||||
setExpirationDateOfSubkey(expiration, KeyIdentifier(keyId))
|
||||
|
||||
/**
|
||||
* 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
|
||||
* v6. This method has no side effects on the original key and will leave it intact.
|
||||
*
|
||||
* @param protector protector to unlock the primary key.
|
||||
* @param revocationAttributes reason for the revocation (key revocation)
|
||||
* @return minimal revocation certificate
|
||||
* @throws PGPException in case we cannot generate a revocation signature
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun createMinimalRevocationCertificate(
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): PGPPublicKeyRing
|
||||
|
||||
|
@ -508,14 +416,25 @@ interface SecretKeyRingEditorInterface {
|
|||
* Create a detached revocation certificate, which can be used to revoke the whole key. The
|
||||
* original key will not be modified by this method.
|
||||
*
|
||||
* @param protector protector to unlock the primary key.
|
||||
* @param revocationAttributes reason for the revocation
|
||||
* @return revocation certificate
|
||||
* @throws PGPException in case we cannot generate a revocation certificate
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun createRevocation(revocationAttributes: RevocationAttributes?): PGPSignature
|
||||
|
||||
/**
|
||||
* Create a detached revocation certificate, which can be used to revoke the specified subkey.
|
||||
* The original key will not be modified by this method.
|
||||
*
|
||||
* @param subkeyIdentifier identifier of the subkey to be revoked
|
||||
* @param revocationAttributes reason for the revocation
|
||||
* @return revocation certificate
|
||||
* @throws PGPException in case we cannot generate a revocation certificate
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun createRevocation(
|
||||
protector: SecretKeyRingProtector,
|
||||
subkeyIdentifier: KeyIdentifier,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): PGPSignature
|
||||
|
||||
|
@ -524,51 +443,63 @@ interface SecretKeyRingEditorInterface {
|
|||
* The original key will not be modified by this method.
|
||||
*
|
||||
* @param subkeyId id of the subkey to be revoked
|
||||
* @param protector protector to unlock the primary key.
|
||||
* @param revocationAttributes reason for the revocation
|
||||
* @return revocation certificate
|
||||
* @throws PGPException in case we cannot generate a revocation certificate
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
@Deprecated("Pass in the subkeys KeyIdentifier instead.")
|
||||
fun createRevocation(
|
||||
subkeyId: Long,
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): PGPSignature
|
||||
): PGPSignature = createRevocation(KeyIdentifier(subkeyId), revocationAttributes)
|
||||
|
||||
/**
|
||||
* Create a detached revocation certificate, which can be used to revoke the specified subkey.
|
||||
* The original key will not be modified by this method.
|
||||
*
|
||||
* @param subkeyId id of the subkey to be revoked
|
||||
* @param protector protector to unlock the primary key.
|
||||
* @param subkeyIdentifier identifier of the subkey to be revoked
|
||||
* @param callback callback to modify the subpackets of the revocation certificate.
|
||||
* @return revocation certificate
|
||||
* @throws PGPException in case we cannot generate a revocation certificate
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
fun createRevocation(
|
||||
subkeyId: Long,
|
||||
protector: SecretKeyRingProtector,
|
||||
subkeyIdentifier: KeyIdentifier,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
): PGPSignature
|
||||
|
||||
/**
|
||||
* Create a detached revocation certificate, which can be used to revoke the specified subkey.
|
||||
* The original key will not be modified by this method.
|
||||
*
|
||||
* @param subkeyId id of the subkey to be revoked
|
||||
* @param callback callback to modify the subpackets of the revocation certificate.
|
||||
* @return revocation certificate
|
||||
* @throws PGPException in case we cannot generate a revocation certificate
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
@Deprecated("Pass in the subkeys KeyIdentifier instead.")
|
||||
fun createRevocation(
|
||||
subkeyId: Long,
|
||||
callback: RevocationSignatureSubpackets.Callback?
|
||||
): PGPSignature = createRevocation(KeyIdentifier(subkeyId), callback)
|
||||
|
||||
/**
|
||||
* Create a detached revocation certificate, which can be used to revoke the specified subkey.
|
||||
* The original key will not be modified by this method.
|
||||
*
|
||||
* @param subkeyFingerprint fingerprint of the subkey to be revoked
|
||||
* @param protector protector to unlock the primary key.
|
||||
* @param revocationAttributes reason for the revocation
|
||||
* @return revocation certificate
|
||||
* @throws PGPException in case we cannot generate a revocation certificate
|
||||
*/
|
||||
@Throws(PGPException::class)
|
||||
@Deprecated("Pass in the subkey KeyIdentifier instead.")
|
||||
fun createRevocation(
|
||||
subkeyFingerprint: OpenPgpFingerprint,
|
||||
protector: SecretKeyRingProtector,
|
||||
revocationAttributes: RevocationAttributes?
|
||||
): PGPSignature
|
||||
): PGPSignature = createRevocation(subkeyFingerprint.keyIdentifier, revocationAttributes)
|
||||
|
||||
/**
|
||||
* Change the passphrase of the whole key ring.
|
||||
|
@ -676,11 +607,7 @@ interface SecretKeyRingEditorInterface {
|
|||
*
|
||||
* @return the key
|
||||
*/
|
||||
fun done(): PGPSecretKeyRing
|
||||
fun done(): OpenPGPKey
|
||||
|
||||
fun addSubKey(
|
||||
keySpec: KeySpec,
|
||||
subkeyPassphrase: Passphrase,
|
||||
protector: SecretKeyRingProtector
|
||||
): SecretKeyRingEditorInterface
|
||||
fun addSubkey(keySpec: KeySpec, subkeyPassphrase: Passphrase): SecretKeyRingEditorInterface
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ public class UserIdRevocationTest {
|
|||
.forKey(secretKeys.getSecretKey(), TestKeys.CRYPTIE_PASSPHRASE);
|
||||
|
||||
assertThrows(NoSuchElementException.class, () -> PGPainless.modifyKeyRing(secretKeys)
|
||||
.revokeSubKey(1L, protector));
|
||||
.revokeSubkey(1L, protector));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -38,7 +38,7 @@ public class RefuseToAddWeakSubkeyTest {
|
|||
KeySpec spec = KeySpec.getBuilder(KeyType.RSA(RsaLength._1024), KeyFlag.ENCRYPT_COMMS).build();
|
||||
|
||||
assertThrows(IllegalArgumentException.class, () ->
|
||||
editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys()));
|
||||
editor.addSubkey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -75,7 +75,7 @@ public class RefuseToAddWeakSubkeyTest {
|
|||
.setKeyCreationDate(editor.getReferenceTime()) // The key gets created after we instantiate the editor.
|
||||
.build();
|
||||
|
||||
secretKeys = editor.addSubKey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys())
|
||||
secretKeys = editor.addSubkey(spec, Passphrase.emptyPassphrase(), SecretKeyRingProtector.unprotectedKeys())
|
||||
.done();
|
||||
|
||||
assertEquals(2, PGPainless.inspectKeyRing(secretKeys).getEncryptionSubkeys(EncryptionPurpose.ANY).size());
|
||||
|
|
|
@ -56,7 +56,7 @@ public class RevokeSubKeyTest {
|
|||
.forKey(secretKeys, Passphrase.fromPassword("password123"));
|
||||
|
||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
||||
.revokeSubKey(new OpenPgpV4Fingerprint(subKey), protector)
|
||||
.revokeSubkey(new OpenPgpV4Fingerprint(subKey), protector)
|
||||
.done();
|
||||
keysIterator = secretKeys.iterator();
|
||||
primaryKey = keysIterator.next();
|
||||
|
@ -133,7 +133,7 @@ public class RevokeSubKeyTest {
|
|||
.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0).getPGPPublicKey();
|
||||
|
||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
||||
.revokeSubKey(encryptionSubkey.getKeyID(), protector)
|
||||
.revokeSubkey(encryptionSubkey.getKeyID(), protector)
|
||||
.done();
|
||||
|
||||
encryptionSubkey = secretKeys.getPublicKey(encryptionSubkey.getKeyID());
|
||||
|
@ -158,7 +158,7 @@ public class RevokeSubKeyTest {
|
|||
.getEncryptionSubkeys(EncryptionPurpose.ANY).get(0).getPGPPublicKey();
|
||||
|
||||
secretKeys = PGPainless.modifyKeyRing(secretKeys)
|
||||
.revokeSubKey(encryptionSubkey.getKeyID(), protector, new RevocationSignatureSubpackets.Callback() {
|
||||
.revokeSubkey(encryptionSubkey.getKeyID(), protector, new RevocationSignatureSubpackets.Callback() {
|
||||
@Override
|
||||
public void modifyHashedSubpackets(RevocationSignatureSubpackets hashedSubpackets) {
|
||||
hashedSubpackets.setRevocationReason(
|
||||
|
|
Loading…
Add table
Reference in a new issue