1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-12-25 12:27:58 +01:00
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( class AlgorithmSuite(
symmetricKeyAlgorithms: List<SymmetricKeyAlgorithm>, symmetricKeyAlgorithms: List<SymmetricKeyAlgorithm>,
hashAlgorithms: List<HashAlgorithm>, hashAlgorithms: List<HashAlgorithm>,
compressionAlgorithms: List<CompressionAlgorithm> compressionAlgorithms: List<CompressionAlgorithm>,
features: List<Feature>
) { ) {
val symmetricKeyAlgorithms: Set<SymmetricKeyAlgorithm> = symmetricKeyAlgorithms.toSet() val symmetricKeyAlgorithms: Set<SymmetricKeyAlgorithm> = symmetricKeyAlgorithms.toSet()
val hashAlgorithms: Set<HashAlgorithm> = hashAlgorithms.toSet() val hashAlgorithms: Set<HashAlgorithm> = hashAlgorithms.toSet()
val compressionAlgorithms: Set<CompressionAlgorithm> = compressionAlgorithms.toSet() val compressionAlgorithms: Set<CompressionAlgorithm> = compressionAlgorithms.toSet()
val features: Set<Feature> = features.toSet()
companion object { companion object {
@JvmStatic @JvmStatic
val defaultSymmetricKeyAlgorithms = val v4SymmetricKeyAlgorithms =
listOf( listOf(
SymmetricKeyAlgorithm.AES_256, SymmetricKeyAlgorithm.AES_256,
SymmetricKeyAlgorithm.AES_192, SymmetricKeyAlgorithm.AES_192,
SymmetricKeyAlgorithm.AES_128) SymmetricKeyAlgorithm.AES_128)
@JvmStatic val defaultSymmetricKeyAlgorithms = v4SymmetricKeyAlgorithms
@JvmStatic @JvmStatic
val defaultHashAlgorithms = val v4HashAlgorithms =
listOf( listOf(
HashAlgorithm.SHA512, HashAlgorithm.SHA512,
HashAlgorithm.SHA384, HashAlgorithm.SHA384,
@ -32,7 +36,18 @@ class AlgorithmSuite(
HashAlgorithm.SHA224) HashAlgorithm.SHA224)
@JvmStatic @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( listOf(
CompressionAlgorithm.ZLIB, CompressionAlgorithm.ZLIB,
CompressionAlgorithm.BZIP2, CompressionAlgorithm.BZIP2,
@ -40,8 +55,32 @@ class AlgorithmSuite(
CompressionAlgorithm.UNCOMPRESSED) CompressionAlgorithm.UNCOMPRESSED)
@JvmStatic @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( 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 internal abstract fun primaryKey(): BaseV4PrimaryKeyBuilder
// Note: The result is a *primary* key pair, so subkeys need adjustment (toPrimaryOrSubkey)
private fun generateKeyPair(): PGPKeyPair { private fun generateKeyPair(): PGPKeyPair {
// Create raw Key Pair // Create raw Key Pair
val keyPair = val keyPair =
@ -54,14 +55,14 @@ class BaseOpenPgpKeyBuilder {
// Form PGP Key Pair // Form PGP Key Pair
return ImplementationFactory.getInstance() return ImplementationFactory.getInstance()
.getPGPV4KeyPair(type.algorithm, keyPair, creationTime) .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 * Make sure, the PGP key packet is a subkey packet for subkeys, and a primary key packet
* for primary keys. * 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) : class BaseV4PrimaryKeyBuilder(type: KeyType, creationTime: Date, policy: Policy) :
@ -76,12 +77,16 @@ class BaseOpenPgpKeyBuilder {
bindingTime: Date = creationTime, bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm = hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm, policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback = subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
SelfSignatureSubpackets.defaultCallback()
) = apply { ) = apply {
val sig = val sig =
buildCertificationFor( buildCertificationFor(
userId, algorithmSuite, certificationType, bindingTime, hashAlgorithm, subpacketsCallback) userId,
algorithmSuite,
certificationType,
bindingTime,
hashAlgorithm,
subpacketsCallback)
key = key =
PGPKeyPair( PGPKeyPair(
PGPPublicKey.addCertification(key.publicKey, userId.toString(), sig), PGPPublicKey.addCertification(key.publicKey, userId.toString(), sig),
@ -116,8 +121,7 @@ class BaseOpenPgpKeyBuilder {
bindingTime: Date = creationTime, bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm = hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm, policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback = subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
SelfSignatureSubpackets.defaultCallback()
) = apply { ) = apply {
val sig = val sig =
buildCertificationFor( buildCertificationFor(
@ -159,10 +163,11 @@ class BaseOpenPgpKeyBuilder {
algorithmSuite: AlgorithmSuite = policy.keyGenerationAlgorithmSuite, algorithmSuite: AlgorithmSuite = policy.keyGenerationAlgorithmSuite,
hashAlgorithm: HashAlgorithm = hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm(), policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm(),
subpacketsCallback: SelfSignatureSubpackets.Callback = subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
SelfSignatureSubpackets.defaultCallback()
) = apply { ) = apply {
val sig = buildDirectKeySignature(bindingTime, algorithmSuite, hashAlgorithm, subpacketsCallback) val sig =
buildDirectKeySignature(
bindingTime, algorithmSuite, hashAlgorithm, subpacketsCallback)
key = PGPKeyPair(PGPPublicKey.addCertification(key.publicKey, sig), key.privateKey) key = PGPKeyPair(PGPPublicKey.addCertification(key.publicKey, sig), key.privateKey)
} }
@ -187,7 +192,9 @@ class BaseOpenPgpKeyBuilder {
return builder.build() 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 return keyPair // is already a secret key packet
} }
@ -205,8 +212,7 @@ class BaseOpenPgpKeyBuilder {
bindingTime: Date = creationTime, bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm = hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm, policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback = subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
SelfSignatureSubpackets.defaultCallback()
) = apply { ) = apply {
val sig = buildBindingSignature(bindingTime, hashAlgorithm, subpacketsCallback) val sig = buildBindingSignature(bindingTime, hashAlgorithm, subpacketsCallback)
key = PGPKeyPair(PGPPublicKey.addCertification(key.publicKey, sig), key.privateKey) key = PGPKeyPair(PGPPublicKey.addCertification(key.publicKey, sig), key.privateKey)
@ -216,8 +222,7 @@ class BaseOpenPgpKeyBuilder {
bindingTime: Date = creationTime, bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm = hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm, policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback = subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
SelfSignatureSubpackets.defaultCallback()
): PGPSignature { ): PGPSignature {
val builder = val builder =
SubkeyBindingSignatureBuilder( SubkeyBindingSignatureBuilder(
@ -245,7 +250,9 @@ class BaseOpenPgpKeyBuilder {
return builder.build(key.publicKey) 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 fpCalc = ImplementationFactory.getInstance().keyFingerprintCalculator
val pubkey = keyPair.publicKey val pubkey = keyPair.publicKey
val privkey = keyPair.privateKey val privkey = keyPair.privateKey

View file

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

View file

@ -10,27 +10,23 @@ import org.pgpainless.util.DateUtil
import org.pgpainless.util.NotationRegistry import org.pgpainless.util.NotationRegistry
class Policy( class Policy(
var certificationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy, var certificationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy =
var revocationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy, HashAlgorithmPolicy.smartCertificationSignatureHashAlgorithmPolicy(),
var dataSignatureHashAlgorithmPolicy: HashAlgorithmPolicy, var revocationSignatureHashAlgorithmPolicy: HashAlgorithmPolicy =
var symmetricKeyEncryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy, certificationSignatureHashAlgorithmPolicy,
var symmetricKeyDecryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy, var dataSignatureHashAlgorithmPolicy: HashAlgorithmPolicy =
var compressionAlgorithmPolicy: CompressionAlgorithmPolicy, HashAlgorithmPolicy.smartDataSignatureHashAlgorithmPolicy(),
var publicKeyAlgorithmPolicy: PublicKeyAlgorithmPolicy, var symmetricKeyEncryptionAlgorithmPolicy: SymmetricKeyAlgorithmPolicy =
var notationRegistry: NotationRegistry 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 keyGenerationAlgorithmSuite = AlgorithmSuite.defaultAlgorithmSuite
var signerUserIdValidationLevel = SignerUserIdValidationLevel.DISABLED var signerUserIdValidationLevel = SignerUserIdValidationLevel.DISABLED
var enableKeyParameterValidation = false 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) { fun modifyUnhashedSubpackets(unhashedSubpackets: S) {
// Empty default implementation to allow for cleaner overriding // 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 @Test
fun test() { fun test() {
val date = DateUtil.parseUTCDate("2020-04-01 10:00:00 UTC") val date = DateUtil.parseUTCDate("2020-04-01 10:00:00 UTC")
val key = OpenPgpKeyBuilder(Policy.getInstance(), date) val key =
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519)) OpenPgpKeyBuilder(Policy.getInstance(), date)
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519))
.addUserId("Alice") .addUserId("Alice")
.addUserAttribute( .addUserAttribute(
PGPUserAttributeSubpacketVectorGenerator() PGPUserAttributeSubpacketVectorGenerator()
@ -31,18 +32,20 @@ class OpenPgpKeyBuilderTest {
@Test @Test
fun minimal() { fun minimal() {
val key = OpenPgpKeyBuilder(Policy.getInstance()) val key =
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519)) OpenPgpKeyBuilder(Policy.getInstance())
.build() .buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519))
.build()
println(PGPainless.asciiArmor(key)) println(PGPainless.asciiArmor(key))
} }
@Test @Test
fun minimalWithUserId() { fun minimalWithUserId() {
val key = OpenPgpKeyBuilder(Policy.getInstance()) val key =
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519)) OpenPgpKeyBuilder(Policy.getInstance())
.addUserId("Alice <alice@pgpainless.org>") .buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519))
.build() .addUserId("Alice <alice@pgpainless.org>")
.build()
println(PGPainless.asciiArmor(key)) println(PGPainless.asciiArmor(key))
} }
} }