mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-09 10:19:39 +02:00
WIP: Migrate SecretKeyRingEditor
This commit is contained in:
parent
3abc2a4e39
commit
18cdf6bbc7
6 changed files with 99 additions and 96 deletions
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -482,7 +482,7 @@ class SigningOptions {
|
|||
* @return selected hash algorithm
|
||||
*/
|
||||
private fun negotiateHashAlgorithm(
|
||||
preferences: Set<HashAlgorithm>,
|
||||
preferences: Set<HashAlgorithm>?,
|
||||
policy: Policy
|
||||
): HashAlgorithm {
|
||||
return _hashAlgorithmOverride
|
||||
|
|
|
@ -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)
|
||||
?.toHashAlgorithms()
|
||||
fun getPreferredHashAlgorithms(keyIdentifier: KeyIdentifier): Set<HashAlgorithm>? {
|
||||
return (keys.getKey(keyIdentifier)
|
||||
?: throw NoSuchElementException(
|
||||
"No subkey with key-id $keyIdentifier found on this key.")
|
||||
"No subkey with key-id $keyIdentifier found on this key."))
|
||||
.getHashAlgorithmPreferences(referenceDate)
|
||||
?.toHashAlgorithms()
|
||||
}
|
||||
|
||||
/** [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)
|
||||
?.toSymmetricKeyAlgorithms()
|
||||
): Set<SymmetricKeyAlgorithm>? {
|
||||
return (keys.getKey(keyIdentifier)
|
||||
?: throw NoSuchElementException(
|
||||
"No subkey with key-id $keyIdentifier found on this key.")
|
||||
"No subkey with key-id $keyIdentifier found on this key."))
|
||||
.getSymmetricCipherPreferences(referenceDate)
|
||||
?.toSymmetricKeyAlgorithms()
|
||||
}
|
||||
|
||||
/** [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)
|
||||
?.toCompressionAlgorithms()
|
||||
fun getPreferredCompressionAlgorithms(
|
||||
keyIdentifier: KeyIdentifier
|
||||
): Set<CompressionAlgorithm>? {
|
||||
return (keys.getKey(keyIdentifier)
|
||||
?: throw NoSuchElementException(
|
||||
"No subkey with key-id $keyIdentifier found on this key.")
|
||||
"No subkey with key-id $keyIdentifier found on this key."))
|
||||
.getCompressionAlgorithmPreferences(referenceDate)
|
||||
?.toCompressionAlgorithms()
|
||||
}
|
||||
|
||||
/** [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)
|
||||
?.toAEADCipherModes()
|
||||
fun getPreferredAEADCipherSuites(keyIdentifier: KeyIdentifier): Set<AEADCipherMode>? {
|
||||
return (keys.getKey(keyIdentifier)
|
||||
?: throw NoSuchElementException(
|
||||
"No subkey with key-id $keyIdentifier found on this key.")
|
||||
"No subkey with key-id $keyIdentifier found on this key."))
|
||||
.getAEADCipherSuitePreferences(referenceDate)
|
||||
?.toAEADCipherModes()
|
||||
}
|
||||
|
||||
@Deprecated("Pass KeyIdentifier instead.")
|
||||
fun getPreferredAEADCipherSuites(keyId: Long): Set<AEADCipherMode> {
|
||||
fun getPreferredAEADCipherSuites(keyId: Long): Set<AEADCipherMode>? {
|
||||
return getPreferredAEADCipherSuites(KeyIdentifier(keyId))
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
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
|
||||
}
|
||||
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)
|
||||
.setUnhashedSubpacketsFunction { subpacketGenerator ->
|
||||
callback?.modifyUnhashedSubpackets(
|
||||
SignatureSubpackets(subpacketGenerator))
|
||||
subpacketGenerator
|
||||
}
|
||||
builder.applyCallback(callback)
|
||||
secretKeyRing =
|
||||
injectCertification(secretKeyRing, sanitizedUserId, builder.build(sanitizedUserId))
|
||||
key = PGPainless.getInstance().toKey(secretKeyRing)
|
||||
}
|
||||
})
|
||||
.done()
|
||||
secretKeyRing = key.pgpSecretKeyRing
|
||||
return this
|
||||
}
|
||||
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -314,7 +314,7 @@ class SignatureSubpackets(
|
|||
}
|
||||
|
||||
override fun setPreferredAEADCiphersuites(
|
||||
aeadAlgorithms: Set<AEADCipherMode>
|
||||
aeadAlgorithms: Collection<AEADCipherMode>
|
||||
): SignatureSubpackets =
|
||||
setPreferredAEADCiphersuites(
|
||||
PreferredAEADCiphersuites.builder(false).apply {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue