1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-09 02:09:38 +02:00

WIP: Migrate SecretKeyRingEditor

This commit is contained in:
Paul Schaub 2025-03-10 14:14:41 +01:00
parent 3abc2a4e39
commit 18cdf6bbc7
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
6 changed files with 99 additions and 96 deletions

View file

@ -21,7 +21,7 @@ interface HashAlgorithmNegotiator {
* @param orderedPrefs hash algorithm preferences
* @return picked algorithms
*/
fun negotiateHashAlgorithm(orderedPrefs: Set<HashAlgorithm>): HashAlgorithm
fun negotiateHashAlgorithm(orderedPrefs: Set<HashAlgorithm>?): HashAlgorithm
companion object {
@ -62,9 +62,9 @@ interface HashAlgorithmNegotiator {
): HashAlgorithmNegotiator {
return object : HashAlgorithmNegotiator {
override fun negotiateHashAlgorithm(
orderedPrefs: Set<HashAlgorithm>
orderedPrefs: Set<HashAlgorithm>?
): HashAlgorithm {
return orderedPrefs.firstOrNull { hashAlgorithmPolicy.isAcceptable(it) }
return orderedPrefs?.firstOrNull { hashAlgorithmPolicy.isAcceptable(it) }
?: hashAlgorithmPolicy.defaultHashAlgorithm()
}
}

View file

@ -482,7 +482,7 @@ class SigningOptions {
* @return selected hash algorithm
*/
private fun negotiateHashAlgorithm(
preferences: Set<HashAlgorithm>,
preferences: Set<HashAlgorithm>?,
policy: Policy
): HashAlgorithm {
return _hashAlgorithmOverride

View file

@ -240,7 +240,7 @@ class KeyRingInfo(
getKeyFlagsOf(keyIdentifier).contains(KeyFlag.CERTIFY_OTHER)
/** [HashAlgorithm] preferences of the primary user-ID or if absent, of the primary key. */
val preferredHashAlgorithms: Set<HashAlgorithm>
val preferredHashAlgorithms: Set<HashAlgorithm>?
get() =
primaryUserId?.let { getPreferredHashAlgorithms(it) }
?: getPreferredHashAlgorithms(keyIdentifier)
@ -248,19 +248,19 @@ class KeyRingInfo(
/**
* [SymmetricKeyAlgorithm] preferences of the primary user-ID or if absent of the primary key.
*/
val preferredSymmetricKeyAlgorithms: Set<SymmetricKeyAlgorithm>
val preferredSymmetricKeyAlgorithms: Set<SymmetricKeyAlgorithm>?
get() =
primaryUserId?.let { getPreferredSymmetricKeyAlgorithms(it) }
?: getPreferredSymmetricKeyAlgorithms(keyIdentifier)
/** [CompressionAlgorithm] preferences of the primary user-ID or if absent, the primary key. */
val preferredCompressionAlgorithms: Set<CompressionAlgorithm>
val preferredCompressionAlgorithms: Set<CompressionAlgorithm>?
get() =
primaryUserId?.let { getPreferredCompressionAlgorithms(it) }
?: getPreferredCompressionAlgorithms(keyIdentifier)
/** [AEADCipherMode] preferences of the primary user-id, or if absent, the primary key. */
val preferredAEADCipherSuites: Set<AEADCipherMode>
val preferredAEADCipherSuites: Set<AEADCipherMode>?
get() =
primaryUserId?.let { getPreferredAEADCipherSuites(it) }
?: getPreferredAEADCipherSuites(keyIdentifier)
@ -738,12 +738,11 @@ class KeyRingInfo(
* @param userId user-id
* @return ordered set of preferred [HashAlgorithms][HashAlgorithm] (descending order)
*/
fun getPreferredHashAlgorithms(userId: CharSequence): Set<HashAlgorithm> {
return keys
.getUserId(userId.toString())
?.getHashAlgorithmPreferences(referenceDate)
fun getPreferredHashAlgorithms(userId: CharSequence): Set<HashAlgorithm>? {
return (keys.getUserId(userId.toString())
?: throw NoSuchElementException("No user-id '$userId' found on this key."))
.getHashAlgorithmPreferences(referenceDate)
?.toHashAlgorithms()
?: throw NoSuchElementException("No user-id '$userId' found on this key.")
}
/**
@ -752,18 +751,17 @@ class KeyRingInfo(
* @param keyIdentifier identifier of a [OpenPGPComponentKey]
* @return ordered set of preferred [HashAlgorithms][HashAlgorithm] (descending order)
*/
fun getPreferredHashAlgorithms(keyIdentifier: KeyIdentifier): Set<HashAlgorithm> {
return keys
.getKey(keyIdentifier)
?.getHashAlgorithmPreferences(referenceDate)
fun getPreferredHashAlgorithms(keyIdentifier: KeyIdentifier): Set<HashAlgorithm>? {
return (keys.getKey(keyIdentifier)
?: throw NoSuchElementException(
"No subkey with key-id $keyIdentifier found on this key."))
.getHashAlgorithmPreferences(referenceDate)
?.toHashAlgorithms()
?: throw NoSuchElementException(
"No subkey with key-id $keyIdentifier found on this key.")
}
/** [HashAlgorithm] preferences of the given key. */
@Deprecated("Pass KeyIdentifier instead.")
fun getPreferredHashAlgorithms(keyId: Long): Set<HashAlgorithm> {
fun getPreferredHashAlgorithms(keyId: Long): Set<HashAlgorithm>? {
return getPreferredHashAlgorithms(KeyIdentifier(keyId))
}
@ -774,12 +772,11 @@ class KeyRingInfo(
* @return ordered set of preferred [SymmetricKeyAlgorithms][SymmetricKeyAlgorithm] (descending
* order)
*/
fun getPreferredSymmetricKeyAlgorithms(userId: CharSequence): Set<SymmetricKeyAlgorithm> {
return keys
.getUserId(userId.toString())
?.getSymmetricCipherPreferences(referenceDate)
fun getPreferredSymmetricKeyAlgorithms(userId: CharSequence): Set<SymmetricKeyAlgorithm>? {
return (keys.getUserId(userId.toString())
?: throw NoSuchElementException("No user-id '$userId' found on this key."))
.getSymmetricCipherPreferences(referenceDate)
?.toSymmetricKeyAlgorithms()
?: throw NoSuchElementException("No user-id '$userId' found on this key.")
}
/**
@ -792,18 +789,17 @@ class KeyRingInfo(
*/
fun getPreferredSymmetricKeyAlgorithms(
keyIdentifier: KeyIdentifier
): Set<SymmetricKeyAlgorithm> {
return keys
.getKey(keyIdentifier)
?.getSymmetricCipherPreferences(referenceDate)
): Set<SymmetricKeyAlgorithm>? {
return (keys.getKey(keyIdentifier)
?: throw NoSuchElementException(
"No subkey with key-id $keyIdentifier found on this key."))
.getSymmetricCipherPreferences(referenceDate)
?.toSymmetricKeyAlgorithms()
?: throw NoSuchElementException(
"No subkey with key-id $keyIdentifier found on this key.")
}
/** [SymmetricKeyAlgorithm] preferences of the given key. */
@Deprecated("Pass KeyIdentifier instead.")
fun getPreferredSymmetricKeyAlgorithms(keyId: Long): Set<SymmetricKeyAlgorithm> {
fun getPreferredSymmetricKeyAlgorithms(keyId: Long): Set<SymmetricKeyAlgorithm>? {
return getPreferredSymmetricKeyAlgorithms(KeyIdentifier(keyId))
}
@ -814,12 +810,11 @@ class KeyRingInfo(
* @return ordered set of preferred [CompressionAlgorithms][CompressionAlgorithm] (descending
* order)
*/
fun getPreferredCompressionAlgorithms(userId: CharSequence): Set<CompressionAlgorithm> {
return keys
.getUserId(userId.toString())
?.getCompressionAlgorithmPreferences(referenceDate)
fun getPreferredCompressionAlgorithms(userId: CharSequence): Set<CompressionAlgorithm>? {
return (keys.getUserId(userId.toString())
?: throw NoSuchElementException("No user-id '$userId' found on this key."))
.getCompressionAlgorithmPreferences(referenceDate)
?.toCompressionAlgorithms()
?: throw NoSuchElementException("No user-id '$userId' found on this key.")
}
/**
@ -830,18 +825,19 @@ class KeyRingInfo(
* @return ordered set of preferred [CompressionAlgorithms][CompressionAlgorithm] (descending
* order)
*/
fun getPreferredCompressionAlgorithms(keyIdentifier: KeyIdentifier): Set<CompressionAlgorithm> {
return keys
.getKey(keyIdentifier)
?.getCompressionAlgorithmPreferences(referenceDate)
fun getPreferredCompressionAlgorithms(
keyIdentifier: KeyIdentifier
): Set<CompressionAlgorithm>? {
return (keys.getKey(keyIdentifier)
?: throw NoSuchElementException(
"No subkey with key-id $keyIdentifier found on this key."))
.getCompressionAlgorithmPreferences(referenceDate)
?.toCompressionAlgorithms()
?: throw NoSuchElementException(
"No subkey with key-id $keyIdentifier found on this key.")
}
/** [CompressionAlgorithm] preferences of the given key. */
@Deprecated("Pass in a KeyIdentifier instead.")
fun getPreferredCompressionAlgorithms(keyId: Long): Set<CompressionAlgorithm> {
fun getPreferredCompressionAlgorithms(keyId: Long): Set<CompressionAlgorithm>? {
return getPreferredCompressionAlgorithms(KeyIdentifier(keyId))
}
@ -852,12 +848,11 @@ class KeyRingInfo(
* @return ordered set of [AEADCipherModes][AEADCipherMode] (descending order, including
* implicitly supported AEAD modes)
*/
fun getPreferredAEADCipherSuites(userId: CharSequence): Set<AEADCipherMode> {
return keys
.getUserId(userId.toString())
?.getAEADCipherSuitePreferences(referenceDate)
fun getPreferredAEADCipherSuites(userId: CharSequence): Set<AEADCipherMode>? {
return (keys.getUserId(userId.toString())
?: throw NoSuchElementException("No user-id '$userId' found on this key."))
.getAEADCipherSuitePreferences(referenceDate)
?.toAEADCipherModes()
?: throw NoSuchElementException("No user-id '$userId' found on this key.")
}
/**
@ -868,17 +863,16 @@ class KeyRingInfo(
* @return ordered set of [AEADCipherModes][AEADCipherMode] (descending order, including
* implicitly supported AEAD modes)
*/
fun getPreferredAEADCipherSuites(keyIdentifier: KeyIdentifier): Set<AEADCipherMode> {
return keys
.getKey(keyIdentifier)
?.getAEADCipherSuitePreferences(referenceDate)
fun getPreferredAEADCipherSuites(keyIdentifier: KeyIdentifier): Set<AEADCipherMode>? {
return (keys.getKey(keyIdentifier)
?: throw NoSuchElementException(
"No subkey with key-id $keyIdentifier found on this key."))
.getAEADCipherSuitePreferences(referenceDate)
?.toAEADCipherModes()
?: throw NoSuchElementException(
"No subkey with key-id $keyIdentifier found on this key.")
}
@Deprecated("Pass KeyIdentifier instead.")
fun getPreferredAEADCipherSuites(keyId: Long): Set<AEADCipherMode> {
fun getPreferredAEADCipherSuites(keyId: Long): Set<AEADCipherMode>? {
return getPreferredAEADCipherSuites(KeyIdentifier(keyId))
}

View file

@ -17,11 +17,12 @@ import org.bouncycastle.openpgp.api.OpenPGPCertificate.OpenPGPSubkey
import org.bouncycastle.openpgp.api.OpenPGPImplementation
import org.bouncycastle.openpgp.api.OpenPGPKey
import org.bouncycastle.openpgp.api.OpenPGPKey.OpenPGPSecretKey
import org.bouncycastle.openpgp.api.OpenPGPKeyEditor
import org.bouncycastle.openpgp.api.OpenPGPSignature
import org.bouncycastle.openpgp.api.SignatureParameters
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
@ -59,48 +60,54 @@ class SecretKeyRingEditor(var key: OpenPGPKey, override val referenceTime: Date
callback: SelfSignatureSubpackets.Callback?,
protector: SecretKeyRingProtector
): SecretKeyRingEditorInterface {
val sanitizedUserId = sanitizeUserId(userId).toString()
val primaryKey = secretKeyRing.secretKey
val info = inspectKeyRing(secretKeyRing, referenceTime)
key = PGPainless.getInstance().toKey(secretKeyRing)
val info = inspectKeyRing(key, 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)
}
val hashAlgorithmPreferences =
info.preferredHashAlgorithms ?: AlgorithmSuite.defaultHashAlgorithms
val symmetricAlgorithmPreferences =
info.preferredSymmetricKeyAlgorithms ?: AlgorithmSuite.defaultSymmetricKeyAlgorithms
val compressionAlgorithmPreferences =
info.preferredCompressionAlgorithms ?: AlgorithmSuite.defaultCompressionAlgorithms
val aeadAlgorithmPreferences =
info.preferredAEADCipherSuites ?: AlgorithmSuite.defaultAEADAlgorithmSuites
val builder =
SelfSignatureBuilder(key.primarySecretKey, protector).apply {
hashedSubpackets.setSignatureCreationTime(referenceTime)
setSignatureType(SignatureType.POSITIVE_CERTIFICATION)
}
builder.hashedSubpackets.apply {
setKeyFlags(info.getKeyFlagsOf(primaryKey.keyID))
hashAlgorithmPreferences
hashAlgorithmPreferences?.let { setPreferredHashAlgorithms(it) }
symmetricKeyAlgorithmPreferences?.let { setPreferredSymmetricKeyAlgorithms(it) }
compressionAlgorithmPreferences?.let { setPreferredCompressionAlgorithms(it) }
setFeatures(Feature.MODIFICATION_DETECTION)
}
builder.applyCallback(callback)
secretKeyRing =
injectCertification(secretKeyRing, sanitizedUserId, builder.build(sanitizedUserId))
key = PGPainless.getInstance().toKey(secretKeyRing)
key =
OpenPGPKeyEditor(key, protector)
.addUserId(
sanitizeUserId(userId).toString(),
object : SignatureParameters.Callback {
override fun apply(parameters: SignatureParameters): SignatureParameters {
return parameters
.setSignatureCreationTime(referenceTime)
.setHashedSubpacketsFunction { subpacketGenerator ->
val subpackets = SignatureSubpackets(subpacketGenerator)
subpackets.setAppropriateIssuerInfo(secretKeyRing.publicKey)
subpackets.setKeyFlags(info.getKeyFlagsOf(key.keyIdentifier))
subpackets.setPreferredHashAlgorithms(hashAlgorithmPreferences)
subpackets.setPreferredSymmetricKeyAlgorithms(
symmetricAlgorithmPreferences)
subpackets.setPreferredCompressionAlgorithms(
compressionAlgorithmPreferences)
subpackets.setPreferredAEADCiphersuites(
aeadAlgorithmPreferences)
callback?.modifyHashedSubpackets(subpackets)
subpacketGenerator
}
.setUnhashedSubpacketsFunction { subpacketGenerator ->
callback?.modifyUnhashedSubpackets(
SignatureSubpackets(subpacketGenerator))
subpacketGenerator
}
}
})
.done()
secretKeyRing = key.pgpSecretKeyRing
return this
}

View file

@ -113,7 +113,9 @@ interface SelfSignatureSubpackets : BaseSignatureSubpackets {
fun setPreferredHashAlgorithms(algorithms: PreferredAlgorithms?): SelfSignatureSubpackets
fun setPreferredAEADCiphersuites(aeadAlgorithms: Set<AEADCipherMode>): SelfSignatureSubpackets
fun setPreferredAEADCiphersuites(
aeadAlgorithms: Collection<AEADCipherMode>
): SelfSignatureSubpackets
fun setPreferredAEADCiphersuites(
algorithms: PreferredAEADCiphersuites.Builder?

View file

@ -314,7 +314,7 @@ class SignatureSubpackets(
}
override fun setPreferredAEADCiphersuites(
aeadAlgorithms: Set<AEADCipherMode>
aeadAlgorithms: Collection<AEADCipherMode>
): SignatureSubpackets =
setPreferredAEADCiphersuites(
PreferredAEADCiphersuites.builder(false).apply {