This commit is contained in:
Paul Schaub 2024-01-24 11:27:42 +01:00
parent f611f54cad
commit 6416ef1e07
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
7 changed files with 108 additions and 80 deletions

View File

@ -7,24 +7,28 @@ package org.pgpainless.algorithm
class AlgorithmSuite(
symmetricKeyAlgorithms: List<SymmetricKeyAlgorithm>,
hashAlgorithms: List<HashAlgorithm>,
compressionAlgorithms: List<CompressionAlgorithm>
compressionAlgorithms: List<CompressionAlgorithm>,
features: List<Feature>
) {
val symmetricKeyAlgorithms: Set<SymmetricKeyAlgorithm> = symmetricKeyAlgorithms.toSet()
val hashAlgorithms: Set<HashAlgorithm> = hashAlgorithms.toSet()
val compressionAlgorithms: Set<CompressionAlgorithm> = compressionAlgorithms.toSet()
val features: Set<Feature> = features.toSet()
companion object {
@JvmStatic
val defaultSymmetricKeyAlgorithms =
val v4SymmetricKeyAlgorithms =
listOf(
SymmetricKeyAlgorithm.AES_256,
SymmetricKeyAlgorithm.AES_192,
SymmetricKeyAlgorithm.AES_128)
@JvmStatic val defaultSymmetricKeyAlgorithms = v4SymmetricKeyAlgorithms
@JvmStatic
val defaultHashAlgorithms =
val v4HashAlgorithms =
listOf(
HashAlgorithm.SHA512,
HashAlgorithm.SHA384,
@ -32,7 +36,18 @@ class AlgorithmSuite(
HashAlgorithm.SHA224)
@JvmStatic
val defaultCompressionAlgorithms =
val v6HashAlgorithms =
listOf(
HashAlgorithm.SHA3_512,
HashAlgorithm.SHA3_256,
HashAlgorithm.SHA512,
HashAlgorithm.SHA384,
HashAlgorithm.SHA256)
@JvmStatic val defaultHashAlgorithms = v4HashAlgorithms
@JvmStatic
val v4CompressionAlgorithms =
listOf(
CompressionAlgorithm.ZLIB,
CompressionAlgorithm.BZIP2,
@ -40,8 +55,32 @@ class AlgorithmSuite(
CompressionAlgorithm.UNCOMPRESSED)
@JvmStatic
val defaultAlgorithmSuite =
val v6CompressionAlgorithms =
listOf(
CompressionAlgorithm.ZLIB,
CompressionAlgorithm.BZIP2,
CompressionAlgorithm.ZIP,
CompressionAlgorithm.UNCOMPRESSED)
@JvmStatic val defaultCompressionAlgorithms = v4CompressionAlgorithms
@JvmStatic val v4Features = listOf(Feature.MODIFICATION_DETECTION)
@JvmStatic
val v6Features = listOf(Feature.MODIFICATION_DETECTION, Feature.MODIFICATION_DETECTION_2)
@JvmStatic val defaultFeatures = v4Features
@JvmStatic
val v4AlgorithmSuite =
AlgorithmSuite(
defaultSymmetricKeyAlgorithms, defaultHashAlgorithms, defaultCompressionAlgorithms)
v4SymmetricKeyAlgorithms, v4HashAlgorithms, v4CompressionAlgorithms, v4Features)
@JvmStatic
val v6AlgorithmSuite =
AlgorithmSuite(
v4SymmetricKeyAlgorithms, v6HashAlgorithms, v6CompressionAlgorithms, v6Features)
@JvmStatic val defaultAlgorithmSuite = v4AlgorithmSuite
}
}

View File

@ -44,6 +44,7 @@ class BaseOpenPgpKeyBuilder {
internal abstract fun primaryKey(): BaseV4PrimaryKeyBuilder
// Note: The result is a *primary* key pair, so subkeys need adjustment (toPrimaryOrSubkey)
private fun generateKeyPair(): PGPKeyPair {
// Create raw Key Pair
val keyPair =
@ -54,14 +55,14 @@ class BaseOpenPgpKeyBuilder {
// Form PGP Key Pair
return ImplementationFactory.getInstance()
.getPGPV4KeyPair(type.algorithm, keyPair, creationTime)
.let { adjustKeyPacket(it) }
.let { toPrimaryOrSubkey(it) }
}
/**
* Make sure, the PGP key packet is a subkey packet for subkeys, and a primary key packet
* for primary keys.
*/
protected abstract fun adjustKeyPacket(keyPair: PGPKeyPair): PGPKeyPair
protected abstract fun toPrimaryOrSubkey(keyPair: PGPKeyPair): PGPKeyPair
}
class BaseV4PrimaryKeyBuilder(type: KeyType, creationTime: Date, policy: Policy) :
@ -76,12 +77,16 @@ class BaseOpenPgpKeyBuilder {
bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback =
SelfSignatureSubpackets.defaultCallback()
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
) = apply {
val sig =
buildCertificationFor(
userId, algorithmSuite, certificationType, bindingTime, hashAlgorithm, subpacketsCallback)
userId,
algorithmSuite,
certificationType,
bindingTime,
hashAlgorithm,
subpacketsCallback)
key =
PGPKeyPair(
PGPPublicKey.addCertification(key.publicKey, userId.toString(), sig),
@ -116,8 +121,7 @@ class BaseOpenPgpKeyBuilder {
bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback =
SelfSignatureSubpackets.defaultCallback()
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
) = apply {
val sig =
buildCertificationFor(
@ -159,10 +163,11 @@ class BaseOpenPgpKeyBuilder {
algorithmSuite: AlgorithmSuite = policy.keyGenerationAlgorithmSuite,
hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm(),
subpacketsCallback: SelfSignatureSubpackets.Callback =
SelfSignatureSubpackets.defaultCallback()
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
) = apply {
val sig = buildDirectKeySignature(bindingTime, algorithmSuite, hashAlgorithm, subpacketsCallback)
val sig =
buildDirectKeySignature(
bindingTime, algorithmSuite, hashAlgorithm, subpacketsCallback)
key = PGPKeyPair(PGPPublicKey.addCertification(key.publicKey, sig), key.privateKey)
}
@ -187,7 +192,9 @@ class BaseOpenPgpKeyBuilder {
return builder.build()
}
override fun adjustKeyPacket(keyPair: PGPKeyPair): PGPKeyPair {
override fun toPrimaryOrSubkey(keyPair: PGPKeyPair) = toPrimaryKey(keyPair)
private fun toPrimaryKey(keyPair: PGPKeyPair): PGPKeyPair {
return keyPair // is already a secret key packet
}
@ -205,8 +212,7 @@ class BaseOpenPgpKeyBuilder {
bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback =
SelfSignatureSubpackets.defaultCallback()
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
) = apply {
val sig = buildBindingSignature(bindingTime, hashAlgorithm, subpacketsCallback)
key = PGPKeyPair(PGPPublicKey.addCertification(key.publicKey, sig), key.privateKey)
@ -216,8 +222,7 @@ class BaseOpenPgpKeyBuilder {
bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback =
SelfSignatureSubpackets.defaultCallback()
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
): PGPSignature {
val builder =
SubkeyBindingSignatureBuilder(
@ -245,7 +250,9 @@ class BaseOpenPgpKeyBuilder {
return builder.build(key.publicKey)
}
override fun adjustKeyPacket(keyPair: PGPKeyPair): PGPKeyPair {
override fun toPrimaryOrSubkey(keyPair: PGPKeyPair) = toSubkey(keyPair)
private fun toSubkey(keyPair: PGPKeyPair): PGPKeyPair {
val fpCalc = ImplementationFactory.getInstance().keyFingerprintCalculator
val pubkey = keyPair.publicKey
val privkey = keyPair.privateKey

View File

@ -43,16 +43,19 @@ open class OpenPgpKeyBuilder(
fun addUserId(
userId: CharSequence,
algorithmSuite: AlgorithmSuite = keyGenerationPolicy,
subpacketsCallback: SelfSignatureSubpackets.Callback =
SelfSignatureSubpackets.defaultCallback()
) = apply { primaryKey.userId(userId, algorithmSuite, subpacketsCallback = subpacketsCallback) }
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
) = apply {
primaryKey.userId(userId, algorithmSuite, subpacketsCallback = subpacketsCallback)
}
fun addUserAttribute(
attribute: PGPUserAttributeSubpacketVector,
algorithmSuite: AlgorithmSuite = keyGenerationPolicy,
subpacketsCallback: SelfSignatureSubpackets.Callback =
SelfSignatureSubpackets.defaultCallback()
) = apply { primaryKey.userAttribute(attribute, algorithmSuite, subpacketsCallback = subpacketsCallback) }
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
) = apply {
primaryKey.userAttribute(
attribute, algorithmSuite, subpacketsCallback = subpacketsCallback)
}
fun addSubkey(
keyType: KeyType,
@ -112,7 +115,8 @@ open class OpenPgpKeyBuilder(
// Add DK sig in case of no user-id
if (primaryKey.isWithoutUserIds()) {
primaryKey.directKeySignature()
primaryKey.directKeySignature(
subpacketsCallback = defaultPrimarySubpacketsCallback())
}
return PGPSecretKeyRing(
@ -139,7 +143,8 @@ open class OpenPgpKeyBuilder(
override fun modifyHashedSubpackets(hashedSubpackets: SelfSignatureSubpackets) {
hashedSubpackets.apply {
setPreferredHashAlgorithms(keyGenerationPolicy.hashAlgorithms)
setPreferredSymmetricKeyAlgorithms(keyGenerationPolicy.symmetricKeyAlgorithms)
setPreferredSymmetricKeyAlgorithms(
keyGenerationPolicy.symmetricKeyAlgorithms)
setPreferredCompressionAlgorithms(keyGenerationPolicy.compressionAlgorithms)
setKeyFlags(KeyFlag.CERTIFY_OTHER)
}

View File

@ -10,27 +10,23 @@ import org.pgpainless.util.DateUtil
import org.pgpainless.util.NotationRegistry
class Policy(
var certificationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy,
var revocationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy,
var dataSignatureHashAlgorithmPolicy: HashAlgorithmPolicy,
var symmetricKeyEncryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy,
var symmetricKeyDecryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy,
var compressionAlgorithmPolicy: CompressionAlgorithmPolicy,
var publicKeyAlgorithmPolicy: PublicKeyAlgorithmPolicy,
var notationRegistry: NotationRegistry
var certificationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy =
HashAlgorithmPolicy.smartCertificationSignatureHashAlgorithmPolicy(),
var revocationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy =
certificationSignatureHashAlgorithmPolicy,
var dataSignatureHashAlgorithmPolicy: HashAlgorithmPolicy =
HashAlgorithmPolicy.smartDataSignatureHashAlgorithmPolicy(),
var symmetricKeyEncryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy =
SymmetricKeyAlgorithmPolicy.symmetricKeyEncryptionPolicy2022(),
var symmetricKeyDecryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy =
symmetricKeyEncryptionAlgorithmPolicy,
var compressionAlgorithmPolicy: CompressionAlgorithmPolicy =
CompressionAlgorithmPolicy.anyCompressionAlgorithmPolicy(),
var publicKeyAlgorithmPolicy: PublicKeyAlgorithmPolicy =
PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy(),
var notationRegistry: NotationRegistry = NotationRegistry()
) {
constructor() :
this(
HashAlgorithmPolicy.smartCertificationSignatureHashAlgorithmPolicy(),
HashAlgorithmPolicy.smartCertificationSignatureHashAlgorithmPolicy(),
HashAlgorithmPolicy.smartDataSignatureHashAlgorithmPolicy(),
SymmetricKeyAlgorithmPolicy.symmetricKeyEncryptionPolicy2022(),
SymmetricKeyAlgorithmPolicy.symmetricKeyDecryptionPolicy2022(),
CompressionAlgorithmPolicy.anyCompressionAlgorithmPolicy(),
PublicKeyAlgorithmPolicy.bsi2021PublicKeyAlgorithmPolicy(),
NotationRegistry())
var keyGenerationAlgorithmSuite = AlgorithmSuite.defaultAlgorithmSuite
var signerUserIdValidationLevel = SignerUserIdValidationLevel.DISABLED
var enableKeyParameterValidation = false

View File

@ -217,7 +217,5 @@ interface SelfSignatureSubpackets : BaseSignatureSubpackets {
}
}
}
@JvmStatic fun defaultCallback() = object : Callback {}
}
}

View File

@ -23,24 +23,4 @@ interface SignatureSubpacketCallback<S : BaseSignatureSubpackets> {
fun modifyUnhashedSubpackets(unhashedSubpackets: S) {
// Empty default implementation to allow for cleaner overriding
}
/**
* Return a new [SignatureSubpacketCallback] which first applies the current callback instance,
* followed by the passed in [nextCallback].
* This is useful to composite different [SignatureSubpacketCallback] instances.
*/
fun then(nextCallback: SignatureSubpacketCallback<S>): SignatureSubpacketCallback<S> {
val currCallback = this
return object : SignatureSubpacketCallback<S> {
override fun modifyHashedSubpackets(hashedSubpackets: S) {
currCallback.modifyHashedSubpackets(hashedSubpackets)
nextCallback.modifyHashedSubpackets(hashedSubpackets)
}
override fun modifyUnhashedSubpackets(unhashedSubpackets: S) {
currCallback.modifyUnhashedSubpackets(unhashedSubpackets)
nextCallback.modifyUnhashedSubpackets(unhashedSubpackets)
}
}
}
}

View File

@ -16,8 +16,9 @@ class OpenPgpKeyBuilderTest {
@Test
fun test() {
val date = DateUtil.parseUTCDate("2020-04-01 10:00:00 UTC")
val key = OpenPgpKeyBuilder(Policy.getInstance(), date)
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519))
val key =
OpenPgpKeyBuilder(Policy.getInstance(), date)
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519))
.addUserId("Alice")
.addUserAttribute(
PGPUserAttributeSubpacketVectorGenerator()
@ -31,18 +32,20 @@ class OpenPgpKeyBuilderTest {
@Test
fun minimal() {
val key = OpenPgpKeyBuilder(Policy.getInstance())
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519))
.build()
val key =
OpenPgpKeyBuilder(Policy.getInstance())
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519))
.build()
println(PGPainless.asciiArmor(key))
}
@Test
fun minimalWithUserId() {
val key = OpenPgpKeyBuilder(Policy.getInstance())
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519))
.addUserId("Alice <alice@pgpainless.org>")
.build()
val key =
OpenPgpKeyBuilder(Policy.getInstance())
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519))
.addUserId("Alice <alice@pgpainless.org>")
.build()
println(PGPainless.asciiArmor(key))
}
}