Test new key generation API

This commit is contained in:
Paul Schaub 2024-02-13 16:02:22 +01:00
parent 177249dd53
commit db01d566fd
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
3 changed files with 137 additions and 78 deletions

View File

@ -5,7 +5,6 @@
package org.pgpainless.key.generation package org.pgpainless.key.generation
import org.bouncycastle.openpgp.PGPSecretKeyRing import org.bouncycastle.openpgp.PGPSecretKeyRing
import org.pgpainless.PGPainless
import org.pgpainless.PGPainless.Companion.buildKeyRing import org.pgpainless.PGPainless.Companion.buildKeyRing
import org.pgpainless.algorithm.KeyFlag import org.pgpainless.algorithm.KeyFlag
import org.pgpainless.key.generation.KeySpec.Companion.getBuilder import org.pgpainless.key.generation.KeySpec.Companion.getBuilder
@ -179,15 +178,15 @@ class KeyRingTemplates {
userId: CharSequence?, userId: CharSequence?,
passphrase: Passphrase = Passphrase.emptyPassphrase() passphrase: Passphrase = Passphrase.emptyPassphrase()
): PGPSecretKeyRing = ): PGPSecretKeyRing =
GenerateOpenPgpKey(PGPainless.getPolicy()) OpenPgpKeyGenerator.buildV4()
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519)) .setCertificationKey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
.apply {
if (userId != null) { if (userId != null) {
addUserId(userId) addUserId(userId)
} }
addEncryptionSubkey(KeyType.XDH(XDHSpec._X25519)) keyPair
addSigningSubkey(KeyType.EDDSA(EdDSACurve._Ed25519))
} }
.addEncryptionSubkey(KeyType.XDH(XDHSpec._X25519))
.addSigningSubkey(KeyType.EDDSA(EdDSACurve._Ed25519))
.build( .build(
if (passphrase.isEmpty) SecretKeyRingProtector.unprotectedKeys() if (passphrase.isEmpty) SecretKeyRingProtector.unprotectedKeys()
else SecretKeyRingProtector.unlockAnyKeyWith(passphrase)) else SecretKeyRingProtector.unlockAnyKeyWith(passphrase))

View File

@ -1,3 +1,7 @@
// SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.key.generation package org.pgpainless.key.generation
import java.io.InputStream import java.io.InputStream
@ -21,40 +25,49 @@ import org.pgpainless.key.generation.type.KeyType
import org.pgpainless.key.generation.type.eddsa.EdDSACurve import org.pgpainless.key.generation.type.eddsa.EdDSACurve
import org.pgpainless.key.generation.type.rsa.RsaLength import org.pgpainless.key.generation.type.rsa.RsaLength
import org.pgpainless.key.generation.type.xdh.XDHSpec import org.pgpainless.key.generation.type.xdh.XDHSpec
import org.pgpainless.key.protection.SecretKeyRingProtector
import org.pgpainless.policy.Policy import org.pgpainless.policy.Policy
import org.pgpainless.signature.builder.DirectKeySelfSignatureBuilder import org.pgpainless.signature.builder.DirectKeySelfSignatureBuilder
import org.pgpainless.signature.builder.PrimaryKeyBindingSignatureBuilder import org.pgpainless.signature.builder.PrimaryKeyBindingSignatureBuilder
import org.pgpainless.signature.builder.SelfSignatureBuilder import org.pgpainless.signature.builder.SelfSignatureBuilder
import org.pgpainless.signature.builder.SubkeyBindingSignatureBuilder import org.pgpainless.signature.builder.SubkeyBindingSignatureBuilder
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets import org.pgpainless.signature.subpackets.SelfSignatureSubpackets
import org.pgpainless.util.Passphrase
/** class OpenPgpKeyGenerator internal constructor() {
* Build a version 4 OpenPGP secret key.
*
* @param policy policy to ensure algorithm compliance and to determine default algorithms
* @param creationTime creation time for the secret key
* @param preferences suite of algorithm preferences and enabled features
*/
fun buildV4(
policy: Policy = PGPainless.getPolicy(),
creationTime: Date = Date(),
preferences: AlgorithmSuite = policy.keyGenerationAlgorithmSuite
): OpinionatedDefinePrimaryKey.V4 {
return OpinionatedDefinePrimaryKey.V4(policy, creationTime, preferences)
}
/** companion object {
* Build a version 6 OpenPGP secret key. /**
* * Build a version 4 OpenPGP secret key.
* @param policy policy to ensure algorithm compliance and to determine default algorithms *
* @param creationTime creation time for the secret key * @param policy policy to ensure algorithm compliance and to determine default algorithms
*/ * @param creationTime creation time for the secret key
fun buildV6( * @param preferences suite of algorithm preferences and enabled features
policy: Policy = PGPainless.getPolicy(), */
creationTime: Date = Date(), @JvmStatic
preferences: AlgorithmSuite = AlgorithmSuite.v6AlgorithmSuite fun buildV4(
): OpinionatedDefinePrimaryKey.V6 { policy: Policy = PGPainless.getPolicy(),
return OpinionatedDefinePrimaryKey.V6(policy, creationTime, preferences) creationTime: Date = Date(),
preferences: AlgorithmSuite = policy.keyGenerationAlgorithmSuite
): OpinionatedDefinePrimaryKey.V4 {
return OpinionatedDefinePrimaryKey.V4(policy, creationTime, preferences)
}
/**
* Build a version 6 OpenPGP secret key.
*
* @param policy policy to ensure algorithm compliance and to determine default algorithms
* @param creationTime creation time for the secret key
*/
@JvmStatic
fun buildV6(
policy: Policy = PGPainless.getPolicy(),
creationTime: Date = Date(),
preferences: AlgorithmSuite = AlgorithmSuite.v6AlgorithmSuite
): OpinionatedDefinePrimaryKey.V6 {
return OpinionatedDefinePrimaryKey.V6(policy, creationTime, preferences)
}
}
} }
/** /**
@ -63,7 +76,8 @@ fun buildV6(
* @param policy algorithm policy * @param policy algorithm policy
* @param creationTime default value for the creation time of the primary key. * @param creationTime default value for the creation time of the primary key.
*/ */
abstract class DefinePrimaryKey<B : DefineSubkeys<B>>( abstract class DefinePrimaryKey<B : DefineSubkeys<B>>
internal constructor(
val policy: Policy, val policy: Policy,
val creationTime: Date, val creationTime: Date,
) { ) {
@ -84,7 +98,7 @@ abstract class DefinePrimaryKey<B : DefineSubkeys<B>>(
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)? = null // default: do nothing applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)? = null // default: do nothing
): B ): B
abstract fun preferencesSubpackets(): SelfSignatureSubpackets.Callback internal abstract fun preferencesSubpackets(): SelfSignatureSubpackets.Callback
} }
/** /**
@ -100,7 +114,8 @@ abstract class DefinePrimaryKey<B : DefineSubkeys<B>>(
* @param U unopinionated builder type * @param U unopinionated builder type
*/ */
abstract class OpinionatedDefinePrimaryKey< abstract class OpinionatedDefinePrimaryKey<
B : OpinionatedDefineSubkeys, U : UnopinionatedDefineSubkeys>( B : OpinionatedDefineSubkeys, U : UnopinionatedDefineSubkeys>
internal constructor(
policy: Policy, policy: Policy,
creationTime: Date, creationTime: Date,
val preferences: AlgorithmSuite, val preferences: AlgorithmSuite,
@ -145,7 +160,7 @@ abstract class OpinionatedDefinePrimaryKey<
* @param policy policy for algorithm compliance and fallbacks * @param policy policy for algorithm compliance and fallbacks
* @param creationTime creation time of the primary key * @param creationTime creation time of the primary key
*/ */
class V4(policy: Policy, creationTime: Date, preferences: AlgorithmSuite) : class V4 internal constructor(policy: Policy, creationTime: Date, preferences: AlgorithmSuite) :
OpinionatedDefinePrimaryKey<OpinionatedDefineSubkeys.V4, UnopinionatedDefineSubkeys.V4>( OpinionatedDefinePrimaryKey<OpinionatedDefineSubkeys.V4, UnopinionatedDefineSubkeys.V4>(
policy, policy,
creationTime, creationTime,
@ -186,7 +201,7 @@ abstract class OpinionatedDefinePrimaryKey<
* @param policy policy for algorithm compliance and fallbacks * @param policy policy for algorithm compliance and fallbacks
* @param creationTime creation time of the primary key * @param creationTime creation time of the primary key
*/ */
class V6(policy: Policy, creationTime: Date, preferences: AlgorithmSuite) : class V6 internal constructor(policy: Policy, creationTime: Date, preferences: AlgorithmSuite) :
OpinionatedDefinePrimaryKey<OpinionatedDefineSubkeys.V6, UnopinionatedDefineSubkeys.V6>( OpinionatedDefinePrimaryKey<OpinionatedDefineSubkeys.V6, UnopinionatedDefineSubkeys.V6>(
policy, policy,
creationTime, creationTime,
@ -218,7 +233,8 @@ abstract class OpinionatedDefinePrimaryKey<
* @param creationTime creation time of the primary key * @param creationTime creation time of the primary key
* @param U unopinionated builder type * @param U unopinionated builder type
*/ */
abstract class UnopinionatedDefinePrimaryKey<U : UnopinionatedDefineSubkeys>( abstract class UnopinionatedDefinePrimaryKey<U : UnopinionatedDefineSubkeys>
internal constructor(
policy: Policy, policy: Policy,
creationTime: Date, creationTime: Date,
) : DefinePrimaryKey<UnopinionatedDefineSubkeys>(policy, creationTime) { ) : DefinePrimaryKey<UnopinionatedDefineSubkeys>(policy, creationTime) {
@ -231,7 +247,7 @@ abstract class UnopinionatedDefinePrimaryKey<U : UnopinionatedDefineSubkeys>(
* *
* @param creationTime creation time of the primary key * @param creationTime creation time of the primary key
*/ */
class V4(policy: Policy, creationTime: Date) : class V4 internal constructor(policy: Policy, creationTime: Date) :
UnopinionatedDefinePrimaryKey<UnopinionatedDefineSubkeys.V4>(policy, creationTime) { UnopinionatedDefinePrimaryKey<UnopinionatedDefineSubkeys.V4>(policy, creationTime) {
override fun setPrimaryKey( override fun setPrimaryKey(
@ -257,7 +273,7 @@ abstract class UnopinionatedDefinePrimaryKey<U : UnopinionatedDefineSubkeys>(
* *
* @param creationTime creation time of the primary key * @param creationTime creation time of the primary key
*/ */
class V6(policy: Policy, creationTime: Date) : class V6 internal constructor(policy: Policy, creationTime: Date) :
UnopinionatedDefinePrimaryKey<UnopinionatedDefineSubkeys.V6>(policy, creationTime) { UnopinionatedDefinePrimaryKey<UnopinionatedDefineSubkeys.V6>(policy, creationTime) {
override fun setPrimaryKey( override fun setPrimaryKey(
type: KeyType, type: KeyType,
@ -269,8 +285,14 @@ abstract class UnopinionatedDefinePrimaryKey<U : UnopinionatedDefineSubkeys>(
} }
} }
/** Interface for key builder that can */ /**
abstract class DefineSubkeys<B : DefineSubkeys<B>>(val policy: Policy, val creationTime: Date) { * Interface for key builder that can be used to add additional subkeys to an OpenPGP key.
*
* @param policy policy to sanitize algorithms against
* @param creationTime creation time of the OpenPGP key
*/
abstract class DefineSubkeys<B : DefineSubkeys<B>>
internal constructor(val policy: Policy, val creationTime: Date) {
/** /**
* Add a subkey to the OpenPGP key. * Add a subkey to the OpenPGP key.
@ -289,20 +311,48 @@ abstract class DefineSubkeys<B : DefineSubkeys<B>>(val policy: Policy, val creat
/** /**
* Finish the key generation and return the OpenPGP [PGPSecretKeyRing]. * Finish the key generation and return the OpenPGP [PGPSecretKeyRing].
* *
* @param protector protector to protect the OpenPGP key's secret components with
* @return finished [PGPSecretKeyRing] * @return finished [PGPSecretKeyRing]
*/ */
abstract fun build(): PGPSecretKeyRing abstract fun build(
protector: SecretKeyRingProtector = SecretKeyRingProtector.unprotectedKeys()
): PGPSecretKeyRing
/**
* Finish the key generation and return the OpenPGP [PGPSecretKeyRing] protected with the given
* [passphrase].
*
* @param passphrase passphrase to protect the OpenPGP key's secret components with
* @return finished [PGPSecretKeyRing]
*/
fun build(passphrase: Passphrase) = build(SecretKeyRingProtector.unlockAnyKeyWith(passphrase))
} }
abstract class OpinionatedDefineSubkeys(policy: Policy, creationTime: Date) : /**
* Opinionated builder for adding subkeys to an OpenPGP key.
*
* @param policy policy to sanitize algorithms with
* @param creationTime creation time of the OpenPGP key
*/
abstract class OpinionatedDefineSubkeys internal constructor(policy: Policy, creationTime: Date) :
DefineSubkeys<OpinionatedDefineSubkeys>(policy, creationTime) { DefineSubkeys<OpinionatedDefineSubkeys>(policy, creationTime) {
// unopinionated builder // unopinionated builder
abstract val unopinionated: UnopinionatedDefineSubkeys abstract val unopinionated: UnopinionatedDefineSubkeys
override fun build(): PGPSecretKeyRing = unopinionated.build() override fun build(protector: SecretKeyRingProtector): PGPSecretKeyRing =
unopinionated.build(protector)
class V4( /**
* Implementation of an [OpinionatedDefineSubkeys] builder for version 4 OpenPGP keys.
*
* @param primaryKey version 4 OpenPGP primary key
* @param policy policy
* @param creationTime creation time of the OpenPGP key
* @param unopinionated unopinionated variant of this builder
*/
class V4
internal constructor(
primaryKey: PGPKeyPair, primaryKey: PGPKeyPair,
policy: Policy, policy: Policy,
creationTime: Date, creationTime: Date,
@ -341,7 +391,8 @@ abstract class OpinionatedDefineSubkeys(policy: Policy, creationTime: Date) :
) = addSubkey(type, creationTime, applyToSubkey) ) = addSubkey(type, creationTime, applyToSubkey)
} }
class V6( class V6
internal constructor(
policy: Policy, policy: Policy,
creationTime: Date, creationTime: Date,
override val unopinionated: UnopinionatedDefineSubkeys.V6 = override val unopinionated: UnopinionatedDefineSubkeys.V6 =
@ -356,13 +407,13 @@ abstract class OpinionatedDefineSubkeys(policy: Policy, creationTime: Date) :
} }
} }
abstract class UnopinionatedDefineSubkeys(policy: Policy, creationTime: Date) : abstract class UnopinionatedDefineSubkeys internal constructor(policy: Policy, creationTime: Date) :
DefineSubkeys<UnopinionatedDefineSubkeys>(policy, creationTime) { DefineSubkeys<UnopinionatedDefineSubkeys>(policy, creationTime) {
class V4(val primaryKey: PGPKeyPair, policy: Policy, creationTime: Date) : class V4 internal constructor(val primaryKey: PGPKeyPair, policy: Policy, creationTime: Date) :
UnopinionatedDefineSubkeys(policy, creationTime) { UnopinionatedDefineSubkeys(policy, creationTime) {
val subkeys: MutableList<PGPKeyPair> = mutableListOf() private val subkeys: MutableList<PGPKeyPair> = mutableListOf()
override fun addSubkey( override fun addSubkey(
type: KeyType, type: KeyType,
@ -378,14 +429,14 @@ abstract class UnopinionatedDefineSubkeys(policy: Policy, creationTime: Date) :
}) })
} }
override fun build(): PGPSecretKeyRing { override fun build(protector: SecretKeyRingProtector): PGPSecretKeyRing {
val primary = val primary =
PGPSecretKey( PGPSecretKey(
primaryKey.privateKey, primaryKey.privateKey,
primaryKey.publicKey, primaryKey.publicKey,
ImplementationFactory.getInstance().v4FingerprintCalculator, ImplementationFactory.getInstance().v4FingerprintCalculator,
true, true,
null) protector.getEncryptor(primaryKey.keyID))
return PGPSecretKeyRing( return PGPSecretKeyRing(
buildList { buildList {
add(primary) add(primary)
@ -396,13 +447,13 @@ abstract class UnopinionatedDefineSubkeys(policy: Policy, creationTime: Date) :
it.publicKey, it.publicKey,
ImplementationFactory.getInstance().v4FingerprintCalculator, ImplementationFactory.getInstance().v4FingerprintCalculator,
false, false,
null)) protector.getEncryptor(it.keyID)))
} }
}) })
} }
} }
class V6(policy: Policy, creationTime: Date) : class V6 internal constructor(policy: Policy, creationTime: Date) :
UnopinionatedDefineSubkeys(policy, creationTime) { UnopinionatedDefineSubkeys(policy, creationTime) {
override fun addSubkey( override fun addSubkey(
@ -413,7 +464,7 @@ abstract class UnopinionatedDefineSubkeys(policy: Policy, creationTime: Date) :
TODO("Not yet implemented") TODO("Not yet implemented")
} }
override fun build(): PGPSecretKeyRing { override fun build(protector: SecretKeyRingProtector): PGPSecretKeyRing {
TODO("Not yet implemented") TODO("Not yet implemented")
} }
} }
@ -425,7 +476,8 @@ abstract class UnopinionatedDefineSubkeys(policy: Policy, creationTime: Date) :
* @param keyPair primary key pair * @param keyPair primary key pair
* @param builder builder instance that generated the primary key * @param builder builder instance that generated the primary key
*/ */
abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePrimaryKey<*>) { abstract class ApplyToPrimaryKey
internal constructor(var keyPair: PGPKeyPair, val builder: DefinePrimaryKey<*>) {
/** /**
* Add a UserID to the primary key. * Add a UserID to the primary key.
@ -516,7 +568,7 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
*/ */
abstract fun then(other: (ApplyToPrimaryKey.() -> PGPKeyPair)?): PGPKeyPair abstract fun then(other: (ApplyToPrimaryKey.() -> PGPKeyPair)?): PGPKeyPair
class V4(keyPair: PGPKeyPair, builder: DefinePrimaryKey<*>) : class V4 internal constructor(keyPair: PGPKeyPair, builder: DefinePrimaryKey<*>) :
ApplyToPrimaryKey(keyPair, builder) { ApplyToPrimaryKey(keyPair, builder) {
override fun addUserId( override fun addUserId(
@ -595,7 +647,7 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
* @param subpacketsCallback callback to modify the binding signatures subpackets * @param subpacketsCallback callback to modify the binding signatures subpackets
* @return binding signature * @return binding signature
*/ */
fun buildCertificationFor( private fun buildCertificationFor(
pair: PGPKeyPair, pair: PGPKeyPair,
userId: CharSequence, userId: CharSequence,
certificationType: CertificationType, certificationType: CertificationType,
@ -623,7 +675,7 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
* @param subpacketsCallback callback to modify the binding signatures subpackets * @param subpacketsCallback callback to modify the binding signatures subpackets
* @return binding signature * @return binding signature
*/ */
fun buildCertificationFor( private fun buildCertificationFor(
pair: PGPKeyPair, pair: PGPKeyPair,
userAttribute: PGPUserAttributeSubpacketVector, userAttribute: PGPUserAttributeSubpacketVector,
certificationType: CertificationType, certificationType: CertificationType,
@ -647,7 +699,7 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
* @param subpacketsCallback callback to modify the subpackets of the direct-key signature * @param subpacketsCallback callback to modify the subpackets of the direct-key signature
* @return direct-key self signature * @return direct-key self signature
*/ */
fun buildDirectKeySignature( private fun buildDirectKeySignature(
pair: PGPKeyPair, pair: PGPKeyPair,
hashAlgorithm: HashAlgorithm, hashAlgorithm: HashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback subpacketsCallback: SelfSignatureSubpackets.Callback
@ -669,7 +721,8 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
* @param subkey subkey pair * @param subkey subkey pair
* @param builder builder instance that generated the subkey * @param builder builder instance that generated the subkey
*/ */
abstract class ApplyToSubkey( abstract class ApplyToSubkey
internal constructor(
val primaryKey: PGPKeyPair, val primaryKey: PGPKeyPair,
var subkey: PGPKeyPair, var subkey: PGPKeyPair,
val builder: DefineSubkeys<*> val builder: DefineSubkeys<*>
@ -697,7 +750,8 @@ abstract class ApplyToSubkey(
* @param subkey subkey pair * @param subkey subkey pair
* @param builder builder instance that generated the subkey * @param builder builder instance that generated the subkey
*/ */
class V4(primaryKey: PGPKeyPair, subkey: PGPKeyPair, builder: DefineSubkeys<*>) : class V4
internal constructor(primaryKey: PGPKeyPair, subkey: PGPKeyPair, builder: DefineSubkeys<*>) :
ApplyToSubkey(primaryKey, subkey, builder) { ApplyToSubkey(primaryKey, subkey, builder) {
override fun addBindingSignature( override fun addBindingSignature(
@ -723,7 +777,7 @@ abstract class ApplyToSubkey(
* @param subpacketsCallback callback to modify the subpackets of the binding signature * @param subpacketsCallback callback to modify the subpackets of the binding signature
* @return subkey binding signature * @return subkey binding signature
*/ */
fun buildBindingSignature( private fun buildBindingSignature(
primaryKey: PGPKeyPair, primaryKey: PGPKeyPair,
subkey: PGPKeyPair, subkey: PGPKeyPair,
hashAlgorithm: HashAlgorithm, hashAlgorithm: HashAlgorithm,
@ -756,7 +810,7 @@ abstract class ApplyToSubkey(
} }
/** Templates for OpenPGP key generation. */ /** Templates for OpenPGP key generation. */
class OpenPgpKeyTemplates { class OpenPgpKeyTemplates private constructor() {
companion object { companion object {
@ -769,7 +823,7 @@ class OpenPgpKeyTemplates {
} }
/** Templates for version 4 OpenPGP keys. Version 4 keys are compliant to RFC4880. */ /** Templates for version 4 OpenPGP keys. Version 4 keys are compliant to RFC4880. */
class V4 { class V4 internal constructor() {
/** /**
* Generate an OpenPGP key that consists of an Ed25519 primary key used for certification of * Generate an OpenPGP key that consists of an Ed25519 primary key used for certification of
@ -783,7 +837,7 @@ class OpenPgpKeyTemplates {
vararg userId: CharSequence, vararg userId: CharSequence,
creationTime: Date = Date() creationTime: Date = Date()
): PGPSecretKeyRing = ): PGPSecretKeyRing =
buildV4(creationTime = creationTime) OpenPgpKeyGenerator.buildV4(creationTime = creationTime)
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)) { .setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
// Add UserIDs // Add UserIDs
userId.forEachIndexed { index, uid -> userId.forEachIndexed { index, uid ->
@ -827,7 +881,7 @@ class OpenPgpKeyTemplates {
creationTime: Date = Date(), creationTime: Date = Date(),
length: RsaLength = RsaLength._4096 length: RsaLength = RsaLength._4096
): PGPSecretKeyRing = ): PGPSecretKeyRing =
buildV4(creationTime = creationTime) OpenPgpKeyGenerator.buildV4(creationTime = creationTime)
.setPrimaryKey(KeyType.RSA(length)) { .setPrimaryKey(KeyType.RSA(length)) {
// Add UserIDs // Add UserIDs
userId.forEachIndexed { index, uid -> userId.forEachIndexed { index, uid ->
@ -870,7 +924,7 @@ class OpenPgpKeyTemplates {
creationTime: Date = Date(), creationTime: Date = Date(),
length: RsaLength = RsaLength._4096 length: RsaLength = RsaLength._4096
): PGPSecretKeyRing = ): PGPSecretKeyRing =
buildV4(creationTime = creationTime) OpenPgpKeyGenerator.buildV4(creationTime = creationTime)
.setPrimaryKey(KeyType.RSA(length)) { .setPrimaryKey(KeyType.RSA(length)) {
userId.forEach { addUserId(it) } userId.forEach { addUserId(it) }
addDirectKeySignature( addDirectKeySignature(

View File

@ -17,7 +17,8 @@ class OpenPgpKeyGeneratorTest {
@Test @Test
fun `minimal call with opinionated builder adds a default DK sig but no user info`() { fun `minimal call with opinionated builder adds a default DK sig but no user info`() {
val key = buildV4().setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)).build() val key =
OpenPgpKeyGenerator.buildV4().setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)).build()
assertFalse(key.publicKey.userIDs.hasNext(), "Key MUST NOT have a UserID") assertFalse(key.publicKey.userIDs.hasNext(), "Key MUST NOT have a UserID")
assertFalse(key.publicKey.userAttributes.hasNext(), "Key MUST NOT have a UserAttribute") assertFalse(key.publicKey.userAttributes.hasNext(), "Key MUST NOT have a UserAttribute")
@ -32,7 +33,10 @@ class OpenPgpKeyGeneratorTest {
@Test @Test
fun `minimal call with unopinionated builder does not add a default DK sig`() { fun `minimal call with unopinionated builder does not add a default DK sig`() {
val key = val key =
buildV4().unopinionated().setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)).build() OpenPgpKeyGenerator.buildV4()
.unopinionated()
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519))
.build()
assertFalse(key.publicKey.keySignatures.hasNext()) assertFalse(key.publicKey.keySignatures.hasNext())
@ -42,7 +46,7 @@ class OpenPgpKeyGeneratorTest {
@Test @Test
fun `adding a direct-key signature with the opinionated builder omits the default DK sig`() { fun `adding a direct-key signature with the opinionated builder omits the default DK sig`() {
val key = val key =
buildV4() OpenPgpKeyGenerator.buildV4()
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)) { .setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
addDirectKeySignature() // "overwrites" the default dk sig addDirectKeySignature() // "overwrites" the default dk sig
} }
@ -56,7 +60,7 @@ class OpenPgpKeyGeneratorTest {
@Test @Test
fun testUnopinionatedV4() { fun testUnopinionatedV4() {
// Unopinionated // Unopinionated
buildV4() OpenPgpKeyGenerator.buildV4()
.unopinionated() .unopinionated()
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)) { .setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
addDirectKeySignature() addDirectKeySignature()
@ -71,7 +75,7 @@ class OpenPgpKeyGeneratorTest {
fun testOpinionatedV4() { fun testOpinionatedV4() {
// Opinionated // Opinionated
val time = DateUtil.parseUTCDate("2024-01-01 00:00:00 UTC") val time = DateUtil.parseUTCDate("2024-01-01 00:00:00 UTC")
buildV4(creationTime = time) OpenPgpKeyGenerator.buildV4(creationTime = time)
.setCertificationKey(KeyType.EDDSA(EdDSACurve._Ed25519)) { .setCertificationKey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
addUserId("Alice <alice@pgpainless.org>") addUserId("Alice <alice@pgpainless.org>")
} }
@ -104,9 +108,11 @@ class OpenPgpKeyGeneratorTest {
@Test @Test
fun test() { fun test() {
buildV4().setCertificationKey(KeyType.RSA(RsaLength._3072)).build().toAsciiArmor().let { OpenPgpKeyGenerator.buildV4()
println(it) .setCertificationKey(KeyType.RSA(RsaLength._3072))
} .build()
.toAsciiArmor()
.let { println(it) }
} }
@Test @Test
@ -116,7 +122,7 @@ class OpenPgpKeyGeneratorTest {
Policy.PublicKeyAlgorithmPolicy(buildMap { put(PublicKeyAlgorithm.RSA_GENERAL, 3072) }) Policy.PublicKeyAlgorithmPolicy(buildMap { put(PublicKeyAlgorithm.RSA_GENERAL, 3072) })
assertThrows<IllegalArgumentException> { assertThrows<IllegalArgumentException> {
buildV4(policy) OpenPgpKeyGenerator.buildV4(policy)
// opinionated builder verifies PK parameters // opinionated builder verifies PK parameters
.setPrimaryKey(KeyType.RSA(RsaLength._2048)) // too weak .setPrimaryKey(KeyType.RSA(RsaLength._2048)) // too weak
} }
@ -128,7 +134,7 @@ class OpenPgpKeyGeneratorTest {
policy.publicKeyAlgorithmPolicy = policy.publicKeyAlgorithmPolicy =
Policy.PublicKeyAlgorithmPolicy(buildMap { put(PublicKeyAlgorithm.RSA_GENERAL, 3072) }) Policy.PublicKeyAlgorithmPolicy(buildMap { put(PublicKeyAlgorithm.RSA_GENERAL, 3072) })
buildV4(policy) OpenPgpKeyGenerator.buildV4(policy)
.unopinionated() // unopinionated builder allows for non-compliant configurations .unopinionated() // unopinionated builder allows for non-compliant configurations
.setPrimaryKey(KeyType.RSA(RsaLength._2048)) .setPrimaryKey(KeyType.RSA(RsaLength._2048))
} }