mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 04:17:59 +01:00
Test new key generation API
This commit is contained in:
parent
177249dd53
commit
db01d566fd
3 changed files with 137 additions and 78 deletions
|
@ -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))
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue