mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 12:27:58 +01:00
Restructure hierarchy of OpenPgpKeyGenerator classes
This commit is contained in:
parent
900860c1fa
commit
f7d389c8d3
4 changed files with 312 additions and 304 deletions
|
@ -23,7 +23,7 @@ class KeyRingTemplates {
|
||||||
*
|
*
|
||||||
* @param userId userId or null
|
* @param userId userId or null
|
||||||
* @param length length of the RSA keys
|
* @param length length of the RSA keys
|
||||||
* @param passphrase passphrase to encrypt the key with. Can be empty for an unencrytped key.
|
* @param passphrase passphrase to encrypt the key with. Can be empty for an unencrypted key.
|
||||||
* @return key
|
* @return key
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
|
@ -179,7 +179,7 @@ class KeyRingTemplates {
|
||||||
passphrase: Passphrase = Passphrase.emptyPassphrase()
|
passphrase: Passphrase = Passphrase.emptyPassphrase()
|
||||||
): PGPSecretKeyRing =
|
): PGPSecretKeyRing =
|
||||||
OpenPgpKeyGenerator.buildV4()
|
OpenPgpKeyGenerator.buildV4()
|
||||||
.setCertificationKey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
|
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519), listOf(KeyFlag.CERTIFY_OTHER)) {
|
||||||
if (userId != null) {
|
if (userId != null) {
|
||||||
addUserId(userId)
|
addUserId(userId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,21 +52,6 @@ class OpenPgpKeyGenerator internal constructor() {
|
||||||
): OpinionatedDefinePrimaryKeyV4 {
|
): OpinionatedDefinePrimaryKeyV4 {
|
||||||
return OpinionatedDefinePrimaryKeyV4(policy, creationTime, preferences)
|
return OpinionatedDefinePrimaryKeyV4(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
|
|
||||||
): OpinionatedDefinePrimaryKeyV6 {
|
|
||||||
return OpinionatedDefinePrimaryKeyV6(policy, creationTime, preferences)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,219 +60,82 @@ class OpenPgpKeyGenerator internal constructor() {
|
||||||
*
|
*
|
||||||
* @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.
|
||||||
|
* @param preferences algorithm preferences
|
||||||
|
* @param O versioned subkeys builder
|
||||||
*/
|
*/
|
||||||
abstract class DefinePrimaryKey<B : DefineSubkeys<B>>
|
abstract class DefinePrimaryKey<O : DefineSubkeys<O>>
|
||||||
internal constructor(
|
internal constructor(val policy: Policy, val creationTime: Date, val preferences: AlgorithmSuite) {
|
||||||
val policy: Policy,
|
|
||||||
val creationTime: Date,
|
// If set to true, no default direct-key signature will be added to the key
|
||||||
) {
|
internal var skipDefaultDirectKeySignature = false
|
||||||
|
|
||||||
|
internal var keyFlags: List<KeyFlag>? = null
|
||||||
|
|
||||||
|
internal abstract fun preferencesSubpackets(): SelfSignatureSubpackets.Callback
|
||||||
|
|
||||||
|
internal abstract fun generatePrimaryKey(type: KeyType, creationTime: Date): PGPKeyPair
|
||||||
|
|
||||||
|
internal abstract fun applyToPrimaryKey(
|
||||||
|
primaryKey: PGPKeyPair,
|
||||||
|
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)?
|
||||||
|
): PGPKeyPair
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the primary key of the OpenPGP key.
|
* Define the primary key for the OpenPGP key.
|
||||||
*
|
*
|
||||||
* @param type primary key type
|
* @param type primary key type
|
||||||
* @param creationTime creation time of the primary key. Defaults to the [DefinePrimaryKey]'s
|
* @param keyFlags list of key flags that denote the primary keys capabilities
|
||||||
* [creationTime].
|
* @param creationTime creation time of the primary key
|
||||||
* @param applyToPrimaryKey function that gets applied to the primary key. Is used to add
|
* @param applyToPrimaryKey function block to apply to the primary key
|
||||||
* binding signatures, UserIDs and user-attributes on the primary key.
|
* @return subkey builder
|
||||||
* @return next step key builder
|
|
||||||
*/
|
*/
|
||||||
abstract fun setPrimaryKey(
|
abstract fun setPrimaryKey(
|
||||||
type: KeyType,
|
type: KeyType,
|
||||||
|
keyFlags: List<KeyFlag>? = listOf(KeyFlag.CERTIFY_OTHER),
|
||||||
creationTime: Date = this.creationTime,
|
creationTime: Date = this.creationTime,
|
||||||
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)? = null // default: do nothing
|
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)? = null
|
||||||
): B
|
): O
|
||||||
|
|
||||||
internal abstract fun preferencesSubpackets(): SelfSignatureSubpackets.Callback
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Implementation of [DefinePrimaryKey] build for version 4 OpenPGP keys. */
|
||||||
* Opinionated implementation of [DefinePrimaryKey]. Contrary to an unopinionated implementation, an
|
abstract class DefinePrimaryKeyV4<O : DefineSubkeys<O>>(
|
||||||
* opinionated [DefinePrimaryKey] will sanity check user-provided parameters and make sure, required
|
|
||||||
* signatures are placed on the key etc.
|
|
||||||
*
|
|
||||||
* @param policy policy to sanity check algorithms, key strengths etc. and to determine fallback
|
|
||||||
* algorithms with
|
|
||||||
* @param creationTime creation time of the primary key
|
|
||||||
* @param unopinionated unopinionated implementation
|
|
||||||
* @param B opinionated builder type
|
|
||||||
* @param U unopinionated builder type
|
|
||||||
*/
|
|
||||||
abstract class OpinionatedDefinePrimaryKey<
|
|
||||||
B : OpinionatedDefineSubkeys, U : UnopinionatedDefineSubkeys>
|
|
||||||
internal constructor(
|
|
||||||
policy: Policy,
|
policy: Policy,
|
||||||
creationTime: Date,
|
creationTime: Date,
|
||||||
val preferences: AlgorithmSuite,
|
preferences: AlgorithmSuite
|
||||||
protected val unopinionated: UnopinionatedDefinePrimaryKey<U>
|
) : DefinePrimaryKey<O>(policy, creationTime, preferences) {
|
||||||
) : DefinePrimaryKey<OpinionatedDefineSubkeys>(policy, creationTime) {
|
|
||||||
|
|
||||||
/**
|
override fun generatePrimaryKey(type: KeyType, creationTime: Date): PGPKeyPair {
|
||||||
* Turn this builder into an unopinionated one by returning the underlying unopinionated
|
return OpenPgpKeyPairGenerator.V4().generatePrimaryKey(type, creationTime)
|
||||||
* implementation.
|
|
||||||
*
|
|
||||||
* @return unopinionated implementation
|
|
||||||
*/
|
|
||||||
abstract fun unopinionated(): UnopinionatedDefinePrimaryKey<U>
|
|
||||||
|
|
||||||
override fun preferencesSubpackets(): SelfSignatureSubpackets.Callback =
|
|
||||||
SelfSignatureSubpackets.applyHashed {
|
|
||||||
setSignatureCreationTime(creationTime)
|
|
||||||
setPreferredHashAlgorithms(preferences.hashAlgorithms)
|
|
||||||
setPreferredSymmetricKeyAlgorithms(preferences.symmetricKeyAlgorithms)
|
|
||||||
setPreferredCompressionAlgorithms(preferences.compressionAlgorithms)
|
|
||||||
setFeatures(preferences.features)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setCertificationKey(
|
|
||||||
type: KeyType,
|
|
||||||
creationTime: Date = this.creationTime,
|
|
||||||
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)? = { keyPair }
|
|
||||||
): B {
|
|
||||||
return setPrimaryKey(type, creationTime) {
|
|
||||||
addDirectKeySignature(
|
|
||||||
preferencesSubpackets()
|
|
||||||
.then(
|
|
||||||
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.CERTIFY_OTHER) }))
|
|
||||||
then(applyToPrimaryKey)
|
|
||||||
}
|
|
||||||
as B
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
override fun applyToPrimaryKey(
|
||||||
* Implementation of an [OpinionatedDefinePrimaryKey] for OpenPGP v4 keys.
|
primaryKey: PGPKeyPair,
|
||||||
*
|
|
||||||
* @param policy policy for algorithm compliance and fallbacks
|
|
||||||
* @param creationTime creation time of the primary key
|
|
||||||
*/
|
|
||||||
class OpinionatedDefinePrimaryKeyV4
|
|
||||||
internal constructor(policy: Policy, creationTime: Date, preferences: AlgorithmSuite) :
|
|
||||||
OpinionatedDefinePrimaryKey<OpinionatedDefineSubkeysV4, UnopinionatedDefineSubkeysV4>(
|
|
||||||
policy, creationTime, preferences, UnopinionatedDefinePrimaryKeyV4(policy, creationTime)) {
|
|
||||||
|
|
||||||
override fun unopinionated(): UnopinionatedDefinePrimaryKeyV4 =
|
|
||||||
unopinionated as UnopinionatedDefinePrimaryKeyV4
|
|
||||||
|
|
||||||
override fun setPrimaryKey(
|
|
||||||
type: KeyType,
|
|
||||||
creationTime: Date,
|
|
||||||
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)?
|
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)?
|
||||||
): OpinionatedDefineSubkeysV4 {
|
): PGPKeyPair {
|
||||||
|
return if (applyToPrimaryKey == null) {
|
||||||
require(policy.publicKeyAlgorithmPolicy.isAcceptable(type.algorithm, type.bitStrength)) {
|
primaryKey
|
||||||
"Public Key algorithm ${type.algorithm} with ${type.bitStrength} is too weak" +
|
} else {
|
||||||
" for the current public key algorithm policy."
|
ApplyToPrimaryKeyV4(primaryKey, this).applyToPrimaryKey()
|
||||||
}
|
}
|
||||||
|
|
||||||
val applier =
|
|
||||||
applyToPrimaryKey
|
|
||||||
?: {
|
|
||||||
// Add default direct-key signature containing preferences
|
|
||||||
addDirectKeySignature(preferencesSubpackets())
|
|
||||||
}
|
|
||||||
|
|
||||||
val unopinionatedSubkeys = unopinionated().setPrimaryKey(type, creationTime, applier)
|
|
||||||
return OpinionatedDefineSubkeysV4(
|
|
||||||
unopinionatedSubkeys.primaryKey, policy, creationTime, unopinionatedSubkeys)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of an [OpinionatedDefinePrimaryKey] for OpenPGP v6 keys.
|
|
||||||
*
|
|
||||||
* @param policy policy for algorithm compliance and fallbacks
|
|
||||||
* @param creationTime creation time of the primary key
|
|
||||||
*/
|
|
||||||
class OpinionatedDefinePrimaryKeyV6
|
|
||||||
internal constructor(policy: Policy, creationTime: Date, preferences: AlgorithmSuite) :
|
|
||||||
OpinionatedDefinePrimaryKey<OpinionatedDefineSubkeysV6, UnopinionatedDefineSubkeysV6>(
|
|
||||||
policy, creationTime, preferences, UnopinionatedDefinePrimaryKeyV6(policy, creationTime)) {
|
|
||||||
|
|
||||||
override fun unopinionated(): UnopinionatedDefinePrimaryKeyV6 =
|
|
||||||
unopinionated as UnopinionatedDefinePrimaryKeyV6
|
|
||||||
|
|
||||||
override fun setPrimaryKey(
|
|
||||||
type: KeyType,
|
|
||||||
creationTime: Date,
|
|
||||||
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)?
|
|
||||||
): OpinionatedDefineSubkeysV6 {
|
|
||||||
val applier = applyToPrimaryKey ?: { addDirectKeySignature(preferencesSubpackets()) }
|
|
||||||
return OpinionatedDefineSubkeysV6(
|
|
||||||
policy,
|
|
||||||
creationTime,
|
|
||||||
unopinionated.setPrimaryKey(type, creationTime, applier)
|
|
||||||
as UnopinionatedDefineSubkeysV6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unopinionated implementation of [DefinePrimaryKey]. An unopinionated [DefinePrimaryKey] will not
|
|
||||||
* perform any sanity checks on user-provided algorithms.
|
|
||||||
*
|
|
||||||
* @param creationTime creation time of the primary key
|
|
||||||
* @param U unopinionated builder type
|
|
||||||
*/
|
|
||||||
abstract class UnopinionatedDefinePrimaryKey<U : UnopinionatedDefineSubkeys>
|
|
||||||
internal constructor(
|
|
||||||
policy: Policy,
|
|
||||||
creationTime: Date,
|
|
||||||
) : DefinePrimaryKey<UnopinionatedDefineSubkeys>(policy, creationTime) {
|
|
||||||
|
|
||||||
override fun preferencesSubpackets(): SelfSignatureSubpackets.Callback =
|
|
||||||
SelfSignatureSubpackets.nop()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of an [UnopinionatedDefinePrimaryKey] for OpenPGP v4 keys.
|
|
||||||
*
|
|
||||||
* @param creationTime creation time of the primary key
|
|
||||||
*/
|
|
||||||
class UnopinionatedDefinePrimaryKeyV4 internal constructor(policy: Policy, creationTime: Date) :
|
|
||||||
UnopinionatedDefinePrimaryKey<UnopinionatedDefineSubkeysV4>(policy, creationTime) {
|
|
||||||
|
|
||||||
override fun setPrimaryKey(
|
|
||||||
type: KeyType,
|
|
||||||
creationTime: Date,
|
|
||||||
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)?
|
|
||||||
): UnopinionatedDefineSubkeysV4 {
|
|
||||||
// generate primary key
|
|
||||||
var primaryKey = OpenPgpKeyPairGenerator.V4().generatePrimaryKey(type, creationTime)
|
|
||||||
|
|
||||||
// add user-ids and direct-key signatures if requested
|
|
||||||
if (applyToPrimaryKey != null) {
|
|
||||||
primaryKey = ApplyToPrimaryKeyV4(primaryKey, this).applyToPrimaryKey()
|
|
||||||
}
|
|
||||||
|
|
||||||
// return builder for adding subkeys
|
|
||||||
return UnopinionatedDefineSubkeysV4(primaryKey, policy, creationTime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of an [UnopinionatedDefinePrimaryKey] for OpenPGP v6 keys.
|
|
||||||
*
|
|
||||||
* @param creationTime creation time of the primary key
|
|
||||||
*/
|
|
||||||
class UnopinionatedDefinePrimaryKeyV6 internal constructor(policy: Policy, creationTime: Date) :
|
|
||||||
UnopinionatedDefinePrimaryKey<UnopinionatedDefineSubkeysV6>(policy, creationTime) {
|
|
||||||
override fun setPrimaryKey(
|
|
||||||
type: KeyType,
|
|
||||||
creationTime: Date,
|
|
||||||
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)?
|
|
||||||
): UnopinionatedDefineSubkeysV6 {
|
|
||||||
return UnopinionatedDefineSubkeysV6(policy, creationTime)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for key builder that can be used to add additional subkeys to an OpenPGP key.
|
* Interface for key builder that can be used to add additional subkeys to an OpenPGP key.
|
||||||
*
|
*
|
||||||
|
* @param primaryKey primary key of the OpenPGP key
|
||||||
* @param policy policy to sanitize algorithms against
|
* @param policy policy to sanitize algorithms against
|
||||||
* @param creationTime creation time of the OpenPGP key
|
* @param creationTime creation time of the OpenPGP key
|
||||||
|
* @param subkeys list of subkeys that were already added
|
||||||
|
* @param B type of this builder
|
||||||
*/
|
*/
|
||||||
abstract class DefineSubkeys<B : DefineSubkeys<B>>
|
abstract class DefineSubkeys<B : DefineSubkeys<B>>
|
||||||
internal constructor(val policy: Policy, val creationTime: Date) {
|
internal constructor(
|
||||||
|
internal var primaryKey: PGPKeyPair,
|
||||||
|
internal val policy: Policy,
|
||||||
|
internal val creationTime: Date,
|
||||||
|
internal val subkeys: MutableList<PGPKeyPair> = mutableListOf()
|
||||||
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a subkey to the OpenPGP key.
|
* Add a subkey to the OpenPGP key.
|
||||||
|
@ -297,11 +145,26 @@ internal constructor(val policy: Policy, val creationTime: Date) {
|
||||||
* @param applyToSubkey function to apply to the subkey. Used to add binding signatures.
|
* @param applyToSubkey function to apply to the subkey. Used to add binding signatures.
|
||||||
* @return this
|
* @return this
|
||||||
*/
|
*/
|
||||||
abstract fun addSubkey(
|
fun addSubkey(
|
||||||
type: KeyType,
|
type: KeyType,
|
||||||
creationTime: Date = this.creationTime,
|
creationTime: Date = this.creationTime,
|
||||||
applyToSubkey: (ApplyToSubkey.() -> PGPKeyPair)? = null
|
applyToSubkey: (ApplyToSubkey.() -> PGPKeyPair)? = null
|
||||||
): B
|
): B =
|
||||||
|
apply {
|
||||||
|
val subkey = generateSubkey(type, creationTime)
|
||||||
|
subkeys.add(applyToSubkey(subkey, applyToSubkey))
|
||||||
|
}
|
||||||
|
as B
|
||||||
|
|
||||||
|
internal abstract fun applyToSubkey(
|
||||||
|
subkey: PGPKeyPair,
|
||||||
|
applyToSubkey: (ApplyToSubkey.() -> PGPKeyPair)?
|
||||||
|
): PGPKeyPair
|
||||||
|
|
||||||
|
internal abstract fun generateSubkey(
|
||||||
|
type: KeyType,
|
||||||
|
creationTime: Date = this.creationTime
|
||||||
|
): PGPKeyPair
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finish the key generation and return the OpenPGP [PGPSecretKeyRing].
|
* Finish the key generation and return the OpenPGP [PGPSecretKeyRing].
|
||||||
|
@ -323,20 +186,138 @@ internal constructor(val policy: Policy, val creationTime: Date) {
|
||||||
fun build(passphrase: Passphrase) = build(SecretKeyRingProtector.unlockAnyKeyWith(passphrase))
|
fun build(passphrase: Passphrase) = build(SecretKeyRingProtector.unlockAnyKeyWith(passphrase))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class DefineSubkeysV4<O : DefineSubkeys<O>>(
|
||||||
|
primaryKey: PGPKeyPair,
|
||||||
|
policy: Policy,
|
||||||
|
creationTime: Date,
|
||||||
|
subkeys: List<PGPKeyPair>
|
||||||
|
) : DefineSubkeys<O>(primaryKey, policy, creationTime, subkeys.toMutableList()) {
|
||||||
|
|
||||||
|
override fun generateSubkey(type: KeyType, creationTime: Date): PGPKeyPair {
|
||||||
|
return OpenPgpKeyPairGenerator.V4().generateSubkey(type, creationTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun applyToSubkey(
|
||||||
|
subkey: PGPKeyPair,
|
||||||
|
applyToSubkey: (ApplyToSubkey.() -> PGPKeyPair)?
|
||||||
|
): PGPKeyPair {
|
||||||
|
return if (applyToSubkey == null) {
|
||||||
|
subkey
|
||||||
|
} else {
|
||||||
|
ApplyToSubkeyV4(primaryKey, subkey, this).applyToSubkey()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun build(protector: SecretKeyRingProtector): PGPSecretKeyRing {
|
||||||
|
return PGPSecretKeyRing(
|
||||||
|
buildList {
|
||||||
|
// Primary Key
|
||||||
|
add(
|
||||||
|
PGPSecretKey(
|
||||||
|
primaryKey.privateKey,
|
||||||
|
primaryKey.publicKey,
|
||||||
|
ImplementationFactory.getInstance().v4FingerprintCalculator,
|
||||||
|
true,
|
||||||
|
protector.getEncryptor(primaryKey.keyID)))
|
||||||
|
|
||||||
|
// Subkeys
|
||||||
|
subkeys.forEach {
|
||||||
|
add(
|
||||||
|
PGPSecretKey(
|
||||||
|
it.privateKey,
|
||||||
|
it.publicKey,
|
||||||
|
ImplementationFactory.getInstance().v4FingerprintCalculator,
|
||||||
|
false,
|
||||||
|
protector.getEncryptor(it.keyID)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opinionated builder for adding subkeys to an OpenPGP key.
|
* Implementation of an [OpinionatedDefinePrimaryKey] for OpenPGP v4 keys.
|
||||||
*
|
*
|
||||||
* @param policy policy to sanitize algorithms with
|
* @param policy policy for algorithm compliance and fallbacks
|
||||||
* @param creationTime creation time of the OpenPGP key
|
* @param creationTime creation time of the primary key
|
||||||
*/
|
*/
|
||||||
abstract class OpinionatedDefineSubkeys internal constructor(policy: Policy, creationTime: Date) :
|
class OpinionatedDefinePrimaryKeyV4
|
||||||
DefineSubkeys<OpinionatedDefineSubkeys>(policy, creationTime) {
|
internal constructor(policy: Policy, creationTime: Date, preferences: AlgorithmSuite) :
|
||||||
|
DefinePrimaryKeyV4<OpinionatedDefineSubkeysV4>(policy, creationTime, preferences) {
|
||||||
|
|
||||||
// unopinionated builder
|
fun unopinionated() = UnopinionatedDefinePrimaryKeyV4(this)
|
||||||
abstract val unopinionated: UnopinionatedDefineSubkeys
|
|
||||||
|
|
||||||
override fun build(protector: SecretKeyRingProtector): PGPSecretKeyRing =
|
override fun preferencesSubpackets(): SelfSignatureSubpackets.Callback =
|
||||||
unopinionated.build(protector)
|
SelfSignatureSubpackets.applyHashed {
|
||||||
|
setSignatureCreationTime(creationTime)
|
||||||
|
setPreferredHashAlgorithms(preferences.hashAlgorithms)
|
||||||
|
setPreferredSymmetricKeyAlgorithms(preferences.symmetricKeyAlgorithms)
|
||||||
|
setPreferredCompressionAlgorithms(preferences.compressionAlgorithms)
|
||||||
|
setFeatures(preferences.features)
|
||||||
|
keyFlags?.let { setKeyFlags(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setPrimaryKey(
|
||||||
|
type: KeyType,
|
||||||
|
keyFlags: List<KeyFlag>?,
|
||||||
|
creationTime: Date,
|
||||||
|
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)?
|
||||||
|
): OpinionatedDefineSubkeysV4 {
|
||||||
|
// Check algorithm is signing capable
|
||||||
|
require(type.algorithm.isSigningCapable()) { "Primary Key MUST be capable of signing." }
|
||||||
|
|
||||||
|
// Check key strength
|
||||||
|
require(policy.publicKeyAlgorithmPolicy.isAcceptable(type.algorithm, type.bitStrength)) {
|
||||||
|
"Public Key algorithm ${type.algorithm} with ${type.bitStrength} is too weak" +
|
||||||
|
" for the current public key algorithm policy."
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remember flags for DK and UID signatures
|
||||||
|
this.keyFlags = keyFlags
|
||||||
|
|
||||||
|
// Add user-provided signatures
|
||||||
|
var key = applyToPrimaryKey(generatePrimaryKey(type, creationTime), applyToPrimaryKey)
|
||||||
|
|
||||||
|
// If no DK sig has been added by user, add default DK sig
|
||||||
|
if (!skipDefaultDirectKeySignature) {
|
||||||
|
key = applyToPrimaryKey(key) { addDirectKeySignature(preferencesSubpackets()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
return OpinionatedDefineSubkeysV4(key, policy, creationTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of an [UnopinionatedDefinePrimaryKey] for OpenPGP v4 keys.
|
||||||
|
*
|
||||||
|
* @param creationTime creation time of the primary key
|
||||||
|
*/
|
||||||
|
class UnopinionatedDefinePrimaryKeyV4
|
||||||
|
internal constructor(policy: Policy, creationTime: Date, preferences: AlgorithmSuite) :
|
||||||
|
DefinePrimaryKeyV4<UnopinionatedDefineSubkeysV4>(policy, creationTime, preferences) {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
opinionated: OpinionatedDefinePrimaryKeyV4
|
||||||
|
) : this(opinionated.policy, opinionated.creationTime, opinionated.preferences)
|
||||||
|
|
||||||
|
override fun preferencesSubpackets(): SelfSignatureSubpackets.Callback =
|
||||||
|
SelfSignatureSubpackets.nop()
|
||||||
|
|
||||||
|
override fun setPrimaryKey(
|
||||||
|
type: KeyType,
|
||||||
|
keyFlags: List<KeyFlag>?,
|
||||||
|
creationTime: Date,
|
||||||
|
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)?
|
||||||
|
): UnopinionatedDefineSubkeysV4 {
|
||||||
|
|
||||||
|
// Remember flags for DK and UID signatures
|
||||||
|
// this.keyFlags = keyFlags
|
||||||
|
|
||||||
|
// Add user-provided signatures
|
||||||
|
val key = applyToPrimaryKey(generatePrimaryKey(type, creationTime), applyToPrimaryKey)
|
||||||
|
|
||||||
|
// return builder for adding subkeys
|
||||||
|
return UnopinionatedDefineSubkeysV4(key, policy, creationTime)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -348,21 +329,10 @@ abstract class OpinionatedDefineSubkeys internal constructor(policy: Policy, cre
|
||||||
* @param unopinionated unopinionated variant of this builder
|
* @param unopinionated unopinionated variant of this builder
|
||||||
*/
|
*/
|
||||||
class OpinionatedDefineSubkeysV4
|
class OpinionatedDefineSubkeysV4
|
||||||
internal constructor(
|
internal constructor(primaryKey: PGPKeyPair, policy: Policy, creationTime: Date) :
|
||||||
primaryKey: PGPKeyPair,
|
DefineSubkeysV4<OpinionatedDefineSubkeysV4>(primaryKey, policy, creationTime, listOf()) {
|
||||||
policy: Policy,
|
|
||||||
creationTime: Date,
|
|
||||||
override val unopinionated: UnopinionatedDefineSubkeysV4 =
|
|
||||||
UnopinionatedDefineSubkeysV4(primaryKey, policy, creationTime)
|
|
||||||
) : OpinionatedDefineSubkeys(policy, creationTime) {
|
|
||||||
|
|
||||||
override fun addSubkey(
|
fun unopinionated() = UnopinionatedDefineSubkeysV4(this)
|
||||||
type: KeyType,
|
|
||||||
creationTime: Date,
|
|
||||||
applyToSubkey: (ApplyToSubkey.() -> PGPKeyPair)?
|
|
||||||
): OpinionatedDefineSubkeysV4 = apply {
|
|
||||||
unopinionated.addSubkey(type, creationTime, applyToSubkey)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addSigningSubkey(
|
fun addSigningSubkey(
|
||||||
type: KeyType,
|
type: KeyType,
|
||||||
|
@ -389,83 +359,32 @@ internal constructor(
|
||||||
) = addSubkey(type, creationTime, applyToSubkey)
|
) = addSubkey(type, creationTime, applyToSubkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
class OpinionatedDefineSubkeysV6
|
class UnopinionatedDefineSubkeysV4
|
||||||
internal constructor(
|
internal constructor(
|
||||||
|
primaryKey: PGPKeyPair,
|
||||||
policy: Policy,
|
policy: Policy,
|
||||||
creationTime: Date,
|
creationTime: Date,
|
||||||
override val unopinionated: UnopinionatedDefineSubkeysV6 =
|
subkeys: List<PGPKeyPair> = mutableListOf()
|
||||||
UnopinionatedDefineSubkeysV6(policy, creationTime)
|
) : DefineSubkeysV4<UnopinionatedDefineSubkeysV4>(primaryKey, policy, creationTime, subkeys) {
|
||||||
) : OpinionatedDefineSubkeys(policy, creationTime) {
|
|
||||||
|
|
||||||
override fun addSubkey(
|
constructor(
|
||||||
type: KeyType,
|
opinionated: OpinionatedDefineSubkeysV4
|
||||||
creationTime: Date,
|
) : this(
|
||||||
|
opinionated.primaryKey, opinionated.policy, opinionated.creationTime, opinionated.subkeys)
|
||||||
|
|
||||||
|
override fun applyToSubkey(
|
||||||
|
subkey: PGPKeyPair,
|
||||||
applyToSubkey: (ApplyToSubkey.() -> PGPKeyPair)?
|
applyToSubkey: (ApplyToSubkey.() -> PGPKeyPair)?
|
||||||
): OpinionatedDefineSubkeysV6 = apply {
|
): PGPKeyPair {
|
||||||
unopinionated.addSubkey(type, creationTime, applyToSubkey)
|
return if (applyToSubkey == null) {
|
||||||
}
|
subkey
|
||||||
}
|
} else {
|
||||||
|
ApplyToSubkeyV4(primaryKey, subkey, this).applyToSubkey()
|
||||||
abstract class UnopinionatedDefineSubkeys internal constructor(policy: Policy, creationTime: Date) :
|
}
|
||||||
DefineSubkeys<UnopinionatedDefineSubkeys>(policy, creationTime)
|
|
||||||
|
|
||||||
class UnopinionatedDefineSubkeysV4
|
|
||||||
internal constructor(val primaryKey: PGPKeyPair, policy: Policy, creationTime: Date) :
|
|
||||||
UnopinionatedDefineSubkeys(policy, creationTime) {
|
|
||||||
|
|
||||||
private val subkeys: MutableList<PGPKeyPair> = mutableListOf()
|
|
||||||
|
|
||||||
override fun addSubkey(
|
|
||||||
type: KeyType,
|
|
||||||
creationTime: Date,
|
|
||||||
applyToSubkey: (ApplyToSubkey.() -> PGPKeyPair)?
|
|
||||||
): UnopinionatedDefineSubkeysV4 = apply {
|
|
||||||
val subkey = OpenPgpKeyPairGenerator.V4().generateSubkey(type, creationTime)
|
|
||||||
subkeys.add(
|
|
||||||
if (applyToSubkey == null) {
|
|
||||||
subkey
|
|
||||||
} else {
|
|
||||||
ApplyToSubkeyV4(primaryKey, subkey, this).applyToSubkey()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun build(protector: SecretKeyRingProtector): PGPSecretKeyRing {
|
override fun generateSubkey(type: KeyType, creationTime: Date): PGPKeyPair {
|
||||||
val primary =
|
return OpenPgpKeyPairGenerator.V4().generateSubkey(type, creationTime)
|
||||||
PGPSecretKey(
|
|
||||||
primaryKey.privateKey,
|
|
||||||
primaryKey.publicKey,
|
|
||||||
ImplementationFactory.getInstance().v4FingerprintCalculator,
|
|
||||||
true,
|
|
||||||
protector.getEncryptor(primaryKey.keyID))
|
|
||||||
return PGPSecretKeyRing(
|
|
||||||
buildList {
|
|
||||||
add(primary)
|
|
||||||
subkeys.forEach {
|
|
||||||
add(
|
|
||||||
PGPSecretKey(
|
|
||||||
it.privateKey,
|
|
||||||
it.publicKey,
|
|
||||||
ImplementationFactory.getInstance().v4FingerprintCalculator,
|
|
||||||
false,
|
|
||||||
protector.getEncryptor(it.keyID)))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class UnopinionatedDefineSubkeysV6 internal constructor(policy: Policy, creationTime: Date) :
|
|
||||||
UnopinionatedDefineSubkeys(policy, creationTime) {
|
|
||||||
|
|
||||||
override fun addSubkey(
|
|
||||||
type: KeyType,
|
|
||||||
creationTime: Date,
|
|
||||||
applyToSubkey: (ApplyToSubkey.() -> PGPKeyPair)?
|
|
||||||
): UnopinionatedDefineSubkeysV6 {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun build(protector: SecretKeyRingProtector): PGPSecretKeyRing {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,7 +410,7 @@ internal constructor(var keyPair: PGPKeyPair, val builder: DefinePrimaryKey<*>)
|
||||||
*/
|
*/
|
||||||
abstract fun addUserId(
|
abstract fun addUserId(
|
||||||
userId: CharSequence,
|
userId: CharSequence,
|
||||||
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop(),
|
subpacketsCallback: SelfSignatureSubpackets.Callback = builder.preferencesSubpackets(),
|
||||||
certificationType: CertificationType = CertificationType.POSITIVE,
|
certificationType: CertificationType = CertificationType.POSITIVE,
|
||||||
hashAlgorithm: HashAlgorithm =
|
hashAlgorithm: HashAlgorithm =
|
||||||
builder.policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
|
builder.policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
|
||||||
|
@ -551,13 +470,27 @@ internal constructor(var keyPair: PGPKeyPair, val builder: DefinePrimaryKey<*>)
|
||||||
* Add a DirectKeySignature to the primary key. Such a signature usually carries information
|
* Add a DirectKeySignature to the primary key. Such a signature usually carries information
|
||||||
* that applies to the whole OpenPGP key, such as algorithm preferences etc.
|
* that applies to the whole OpenPGP key, such as algorithm preferences etc.
|
||||||
*/
|
*/
|
||||||
abstract fun addDirectKeySignature(
|
fun addDirectKeySignature(
|
||||||
subpacketsCallback: SelfSignatureSubpackets.Callback = builder.preferencesSubpackets(),
|
subpacketsCallback: SelfSignatureSubpackets.Callback = builder.preferencesSubpackets(),
|
||||||
hashAlgorithm: HashAlgorithm =
|
hashAlgorithm: HashAlgorithm =
|
||||||
builder.policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
|
builder.policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
|
||||||
bindingTime: Date = builder.creationTime
|
bindingTime: Date = builder.creationTime
|
||||||
|
): PGPKeyPair {
|
||||||
|
skipDefaultSignature()
|
||||||
|
return doAddDirectKeySignature(subpacketsCallback, hashAlgorithm, bindingTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun doAddDirectKeySignature(
|
||||||
|
subpacketsCallback: SelfSignatureSubpackets.Callback,
|
||||||
|
hashAlgorithm: HashAlgorithm,
|
||||||
|
bindingTime: Date
|
||||||
): PGPKeyPair
|
): PGPKeyPair
|
||||||
|
|
||||||
|
fun skipDefaultSignature(): PGPKeyPair {
|
||||||
|
builder.skipDefaultDirectKeySignature = true
|
||||||
|
return keyPair
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedule the execution of another [ApplyToPrimaryKey] function instance right after this one
|
* Schedule the execution of another [ApplyToPrimaryKey] function instance right after this one
|
||||||
* has been executed.
|
* has been executed.
|
||||||
|
@ -578,14 +511,34 @@ class ApplyToPrimaryKeyV4 internal constructor(keyPair: PGPKeyPair, builder: Def
|
||||||
hashAlgorithm: HashAlgorithm,
|
hashAlgorithm: HashAlgorithm,
|
||||||
bindingTime: Date
|
bindingTime: Date
|
||||||
): PGPKeyPair {
|
): PGPKeyPair {
|
||||||
|
val callback = markAsPrimaryIfNecessary(subpacketsCallback)
|
||||||
|
|
||||||
val sig =
|
val sig =
|
||||||
buildCertificationFor(
|
buildCertificationFor(
|
||||||
keyPair, userId, certificationType, bindingTime, hashAlgorithm, subpacketsCallback)
|
keyPair, userId, certificationType, bindingTime, hashAlgorithm, callback)
|
||||||
|
|
||||||
keyPair = keyPair.plusCertification(userId, sig)
|
keyPair = keyPair.plusCertification(userId, sig)
|
||||||
return keyPair
|
return keyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun markAsPrimaryIfNecessary(
|
||||||
|
subpacketsCallback: SelfSignatureSubpackets.Callback
|
||||||
|
): SelfSignatureSubpackets.Callback {
|
||||||
|
val callback =
|
||||||
|
// if key has primary User-IDs already, do nothing
|
||||||
|
if (keyPair.publicKey.userIDs.asSequence().any { uid ->
|
||||||
|
keyPair.publicKey.getSignaturesForID(uid).asSequence().any { sig ->
|
||||||
|
sig.hashedSubPackets.isPrimaryUserID
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
subpacketsCallback
|
||||||
|
} else {
|
||||||
|
// else set this user-id as primary
|
||||||
|
SelfSignatureSubpackets.applyHashed { setPrimaryUserId() }.then(subpacketsCallback)
|
||||||
|
}
|
||||||
|
return callback
|
||||||
|
}
|
||||||
|
|
||||||
override fun addUserAttribute(
|
override fun addUserAttribute(
|
||||||
userAttribute: PGPUserAttributeSubpacketVector,
|
userAttribute: PGPUserAttributeSubpacketVector,
|
||||||
subpacketsCallback: SelfSignatureSubpackets.Callback,
|
subpacketsCallback: SelfSignatureSubpackets.Callback,
|
||||||
|
@ -606,7 +559,7 @@ class ApplyToPrimaryKeyV4 internal constructor(keyPair: PGPKeyPair, builder: Def
|
||||||
return keyPair
|
return keyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addDirectKeySignature(
|
override fun doAddDirectKeySignature(
|
||||||
subpacketsCallback: SelfSignatureSubpackets.Callback,
|
subpacketsCallback: SelfSignatureSubpackets.Callback,
|
||||||
hashAlgorithm: HashAlgorithm,
|
hashAlgorithm: HashAlgorithm,
|
||||||
bindingTime: Date
|
bindingTime: Date
|
||||||
|
|
|
@ -45,7 +45,6 @@ import org.pgpainless.implementation.ImplementationFactory;
|
||||||
import org.pgpainless.key.TestKeys;
|
import org.pgpainless.key.TestKeys;
|
||||||
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
import org.pgpainless.key.protection.SecretKeyRingProtector;
|
||||||
import org.pgpainless.key.protection.UnlockSecretKey;
|
import org.pgpainless.key.protection.UnlockSecretKey;
|
||||||
import org.pgpainless.policy.Policy;
|
|
||||||
import org.pgpainless.signature.consumer.SignaturePicker;
|
import org.pgpainless.signature.consumer.SignaturePicker;
|
||||||
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
import org.pgpainless.signature.subpackets.SignatureSubpacketsUtil;
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,24 @@
|
||||||
|
// 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 org.bouncycastle.bcpg.sig.PrimaryUserID
|
||||||
import org.bouncycastle.extensions.toAsciiArmor
|
import org.bouncycastle.extensions.toAsciiArmor
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
import org.junit.jupiter.api.Assertions.assertFalse
|
import org.junit.jupiter.api.Assertions.assertFalse
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
import org.pgpainless.PGPainless
|
||||||
|
import org.pgpainless.algorithm.KeyFlag
|
||||||
import org.pgpainless.algorithm.PublicKeyAlgorithm
|
import org.pgpainless.algorithm.PublicKeyAlgorithm
|
||||||
import org.pgpainless.key.generation.type.KeyType
|
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.policy.Policy
|
import org.pgpainless.policy.Policy
|
||||||
|
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets
|
||||||
import org.pgpainless.util.DateUtil
|
import org.pgpainless.util.DateUtil
|
||||||
|
|
||||||
class OpenPgpKeyGeneratorTest {
|
class OpenPgpKeyGeneratorTest {
|
||||||
|
@ -57,6 +65,39 @@ class OpenPgpKeyGeneratorTest {
|
||||||
println(key.toAsciiArmor())
|
println(key.toAsciiArmor())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `adding two user-ids will mark the first one as primary`() {
|
||||||
|
val key =
|
||||||
|
OpenPgpKeyGenerator.buildV4()
|
||||||
|
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
|
||||||
|
addUserId("Primary <primary@example.com>")
|
||||||
|
addUserId("Non Primary <non-primary@example.com>")
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val info = PGPainless.inspectKeyRing(key)
|
||||||
|
assertEquals("Primary <primary@example.com>", info.primaryUserId)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `adding two user-ids but mark the first as non-primary will mark the second one as primary`() {
|
||||||
|
val key =
|
||||||
|
OpenPgpKeyGenerator.buildV4()
|
||||||
|
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
|
||||||
|
addUserId(
|
||||||
|
"Non Primary <non-primary@example.com>",
|
||||||
|
SelfSignatureSubpackets.applyHashed {
|
||||||
|
// Not primary
|
||||||
|
setPrimaryUserId(PrimaryUserID(false, false))
|
||||||
|
})
|
||||||
|
addUserId("Primary <primary@example.com>")
|
||||||
|
}
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val info = PGPainless.inspectKeyRing(key)
|
||||||
|
assertEquals("Primary <primary@example.com>", info.primaryUserId)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testUnopinionatedV4() {
|
fun testUnopinionatedV4() {
|
||||||
// Unopinionated
|
// Unopinionated
|
||||||
|
@ -76,7 +117,7 @@ class OpenPgpKeyGeneratorTest {
|
||||||
// Opinionated
|
// Opinionated
|
||||||
val time = DateUtil.parseUTCDate("2024-01-01 00:00:00 UTC")
|
val time = DateUtil.parseUTCDate("2024-01-01 00:00:00 UTC")
|
||||||
OpenPgpKeyGenerator.buildV4(creationTime = time)
|
OpenPgpKeyGenerator.buildV4(creationTime = time)
|
||||||
.setCertificationKey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
|
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519), listOf(KeyFlag.CERTIFY_OTHER)) {
|
||||||
addUserId("Alice <alice@pgpainless.org>")
|
addUserId("Alice <alice@pgpainless.org>")
|
||||||
}
|
}
|
||||||
.addSigningSubkey(KeyType.EDDSA(EdDSACurve._Ed25519))
|
.addSigningSubkey(KeyType.EDDSA(EdDSACurve._Ed25519))
|
||||||
|
@ -109,7 +150,7 @@ class OpenPgpKeyGeneratorTest {
|
||||||
@Test
|
@Test
|
||||||
fun test() {
|
fun test() {
|
||||||
OpenPgpKeyGenerator.buildV4()
|
OpenPgpKeyGenerator.buildV4()
|
||||||
.setCertificationKey(KeyType.RSA(RsaLength._3072))
|
.setPrimaryKey(KeyType.RSA(RsaLength._3072), keyFlags = listOf(KeyFlag.CERTIFY_OTHER))
|
||||||
.build()
|
.build()
|
||||||
.toAsciiArmor()
|
.toAsciiArmor()
|
||||||
.let { println(it) }
|
.let { println(it) }
|
||||||
|
@ -138,4 +179,19 @@ class OpenPgpKeyGeneratorTest {
|
||||||
.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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `skip default DirectKey signature will not add one`() {
|
||||||
|
val key =
|
||||||
|
OpenPgpKeyGenerator.buildV4()
|
||||||
|
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)) { skipDefaultSignature() }
|
||||||
|
.build()
|
||||||
|
|
||||||
|
assertFalse(key.publicKey.keySignatures.hasNext())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testModernKeyGeneration() {
|
||||||
|
println(KeyRingTemplates().modernKeyRing("null").toAsciiArmor())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue