mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 12:27:58 +01:00
Documentation and primary userIDs
This commit is contained in:
parent
d7ce9764c3
commit
4a0eef0924
2 changed files with 239 additions and 13 deletions
|
@ -1,5 +1,6 @@
|
||||||
package org.pgpainless.key.generation
|
package org.pgpainless.key.generation
|
||||||
|
|
||||||
|
import org.bouncycastle.bcpg.attr.ImageAttribute
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.KeyPairGenerator
|
import java.security.KeyPairGenerator
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
@ -9,6 +10,8 @@ import org.bouncycastle.openpgp.PGPSecretKey
|
||||||
import org.bouncycastle.openpgp.PGPSecretKeyRing
|
import org.bouncycastle.openpgp.PGPSecretKeyRing
|
||||||
import org.bouncycastle.openpgp.PGPSignature
|
import org.bouncycastle.openpgp.PGPSignature
|
||||||
import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVector
|
import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVector
|
||||||
|
import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVectorGenerator
|
||||||
|
import org.bouncycastle.util.io.Streams
|
||||||
import org.pgpainless.PGPainless
|
import org.pgpainless.PGPainless
|
||||||
import org.pgpainless.algorithm.AlgorithmSuite
|
import org.pgpainless.algorithm.AlgorithmSuite
|
||||||
import org.pgpainless.algorithm.CertificationType
|
import org.pgpainless.algorithm.CertificationType
|
||||||
|
@ -25,6 +28,7 @@ import org.pgpainless.signature.builder.DirectKeySelfSignatureBuilder
|
||||||
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 java.io.InputStream
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a version 4 OpenPGP secret key.
|
* Build a version 4 OpenPGP secret key.
|
||||||
|
@ -158,6 +162,11 @@ abstract class OpinionatedDefinePrimaryKey<
|
||||||
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)?
|
applyToPrimaryKey: (ApplyToPrimaryKey.() -> PGPKeyPair)?
|
||||||
): OpinionatedDefineSubkeys.V4 {
|
): OpinionatedDefineSubkeys.V4 {
|
||||||
|
|
||||||
|
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."
|
||||||
|
}
|
||||||
|
|
||||||
val applier = applyToPrimaryKey ?: { addDirectKeySignature(preferencesSubpackets()) }
|
val applier = applyToPrimaryKey ?: { addDirectKeySignature(preferencesSubpackets()) }
|
||||||
|
|
||||||
val unopinionatedSubkeys = unopinionated().setPrimaryKey(type, creationTime, applier)
|
val unopinionatedSubkeys = unopinionated().setPrimaryKey(type, creationTime, applier)
|
||||||
|
@ -400,7 +409,12 @@ abstract class UnopinionatedDefineSubkeys(policy: Policy, creationTime: Date) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Function that can be applied to the primary key. */
|
/**
|
||||||
|
* Function that can be applied to the primary key.
|
||||||
|
*
|
||||||
|
* @param keyPair primary key pair
|
||||||
|
* @param builder builder instance that generated the primary key
|
||||||
|
*/
|
||||||
abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePrimaryKey<*>) {
|
abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePrimaryKey<*>) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -408,6 +422,11 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
|
||||||
*
|
*
|
||||||
* @param userId UserID to be bound to the primary key
|
* @param userId UserID to be bound to the primary key
|
||||||
* @param subpacketsCallback callback to modify the binding signatures subpackets
|
* @param subpacketsCallback callback to modify the binding signatures subpackets
|
||||||
|
* @param certificationType type of the certification signature. Defaults to [CertificationType.POSITIVE]
|
||||||
|
* @param hashAlgorithm hash algorithm to be used during signature calculation
|
||||||
|
* @param bindingTime creation time of the binding signature
|
||||||
|
*
|
||||||
|
* @return modified key pair
|
||||||
*/
|
*/
|
||||||
abstract fun addUserId(
|
abstract fun addUserId(
|
||||||
userId: CharSequence,
|
userId: CharSequence,
|
||||||
|
@ -418,6 +437,52 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
|
||||||
bindingTime: Date = builder.creationTime
|
bindingTime: Date = builder.creationTime
|
||||||
): PGPKeyPair
|
): PGPKeyPair
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a UserAttribute to the primary key.
|
||||||
|
*
|
||||||
|
* @param userAttribute UserAttribute to be bound to the primary key
|
||||||
|
* @param subpacketsCallback callback to modify the binding signature subpackets
|
||||||
|
* @param certificationType type of the binding signature. Default to [CertificationType.POSITIVE]
|
||||||
|
* @param hashAlgorithm hash algorithm to be used during signature calculation
|
||||||
|
* @param bindingTime creation time of the binding signature
|
||||||
|
*
|
||||||
|
* @return modified key pair
|
||||||
|
*/
|
||||||
|
abstract fun addUserAttribute(
|
||||||
|
userAttribute: PGPUserAttributeSubpacketVector,
|
||||||
|
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop(),
|
||||||
|
certificationType: CertificationType = CertificationType.POSITIVE,
|
||||||
|
hashAlgorithm: HashAlgorithm = builder.policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
|
||||||
|
bindingTime: Date = builder.creationTime
|
||||||
|
): PGPKeyPair
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a JPEG image as UserAttribute to the primary key.
|
||||||
|
* This may for example be a profile picture of the key owner.
|
||||||
|
*
|
||||||
|
* @param jpegInputStream input stream containing the JPEG encoded image
|
||||||
|
* @param subpacketsCallback callback to modify the subpackets of the binding signature
|
||||||
|
* @param certificationType type of the binding signature. Defaults to [CertificationType.POSITIVE]
|
||||||
|
* @param hashAlgorithm hash algorithm to be used during signature calculation
|
||||||
|
* @param bindingTime creation time of the binding signature
|
||||||
|
*
|
||||||
|
* @return modified key pair
|
||||||
|
*/
|
||||||
|
fun addImageAttribute(
|
||||||
|
jpegInputStream: InputStream,
|
||||||
|
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop(),
|
||||||
|
certificationType: CertificationType = CertificationType.POSITIVE,
|
||||||
|
hashAlgorithm: HashAlgorithm = builder.policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
|
||||||
|
bindingTime: Date = builder.creationTime
|
||||||
|
): PGPKeyPair = addUserAttribute(
|
||||||
|
PGPUserAttributeSubpacketVectorGenerator().apply {
|
||||||
|
setImageAttribute(ImageAttribute.JPEG, Streams.readAll(jpegInputStream))
|
||||||
|
}.generate(),
|
||||||
|
subpacketsCallback,
|
||||||
|
certificationType,
|
||||||
|
hashAlgorithm,
|
||||||
|
bindingTime)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
@ -429,6 +494,13 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
|
||||||
bindingTime: Date = builder.creationTime
|
bindingTime: Date = builder.creationTime
|
||||||
): PGPKeyPair
|
): PGPKeyPair
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule the execution of another [ApplyToPrimaryKey] function instance right after
|
||||||
|
* this one has been executed.
|
||||||
|
*
|
||||||
|
* @param other second instance
|
||||||
|
* @return modified key pair after this and [other] have been executed
|
||||||
|
*/
|
||||||
abstract fun then(other: (ApplyToPrimaryKey.() -> PGPKeyPair)?): PGPKeyPair
|
abstract fun then(other: (ApplyToPrimaryKey.() -> PGPKeyPair)?): PGPKeyPair
|
||||||
|
|
||||||
class V4(keyPair: PGPKeyPair, builder: DefinePrimaryKey<*>) :
|
class V4(keyPair: PGPKeyPair, builder: DefinePrimaryKey<*>) :
|
||||||
|
@ -457,6 +529,28 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
|
||||||
return keyPair
|
return keyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun addUserAttribute(
|
||||||
|
userAttribute: PGPUserAttributeSubpacketVector,
|
||||||
|
subpacketsCallback: SelfSignatureSubpackets.Callback,
|
||||||
|
certificationType: CertificationType,
|
||||||
|
hashAlgorithm: HashAlgorithm,
|
||||||
|
bindingTime: Date
|
||||||
|
): PGPKeyPair {
|
||||||
|
val sig = buildCertificationFor(
|
||||||
|
keyPair,
|
||||||
|
userAttribute,
|
||||||
|
certificationType,
|
||||||
|
bindingTime,
|
||||||
|
hashAlgorithm,
|
||||||
|
subpacketsCallback)
|
||||||
|
|
||||||
|
keyPair = PGPKeyPair(
|
||||||
|
PGPPublicKey.addCertification(keyPair.publicKey, userAttribute, sig),
|
||||||
|
keyPair.privateKey)
|
||||||
|
|
||||||
|
return keyPair
|
||||||
|
}
|
||||||
|
|
||||||
override fun addDirectKeySignature(
|
override fun addDirectKeySignature(
|
||||||
subpacketsCallback: SelfSignatureSubpackets.Callback,
|
subpacketsCallback: SelfSignatureSubpackets.Callback,
|
||||||
hashAlgorithm: HashAlgorithm,
|
hashAlgorithm: HashAlgorithm,
|
||||||
|
@ -483,6 +577,19 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
|
||||||
return keyPair
|
return keyPair
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a certification signature that binds the given [userId] to the given
|
||||||
|
* primary key [pair].
|
||||||
|
*
|
||||||
|
* @param pair primary key pair
|
||||||
|
* @param userId UserID to be bound
|
||||||
|
* @param certificationType type of the binding signature
|
||||||
|
* @param bindingTime creation time of the binding signature
|
||||||
|
* @param hashAlgorithm hash algorithm to be used during signature calculation
|
||||||
|
* @param subpacketsCallback callback to modify the binding signatures subpackets
|
||||||
|
*
|
||||||
|
* @return binding signature
|
||||||
|
*/
|
||||||
fun buildCertificationFor(
|
fun buildCertificationFor(
|
||||||
pair: PGPKeyPair,
|
pair: PGPKeyPair,
|
||||||
userId: CharSequence,
|
userId: CharSequence,
|
||||||
|
@ -499,6 +606,20 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
|
||||||
return builder.build(userId)
|
return builder.build(userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a certification signature that binds the given [userAttribute] to the given
|
||||||
|
* primary key [pair].
|
||||||
|
*
|
||||||
|
* @param pair primary key pair
|
||||||
|
* @param userAttribute UserAttribute to be bound
|
||||||
|
* @param certificationType type of the binding signature
|
||||||
|
* @param bindingTime creation time of the binding signature
|
||||||
|
* @param hashAlgorithm hash algorithm to be used during signature calculation
|
||||||
|
* @param subpacketsCallback callback to modify the binding signatures subpackets
|
||||||
|
*
|
||||||
|
* @return binding signature
|
||||||
|
*/
|
||||||
fun buildCertificationFor(
|
fun buildCertificationFor(
|
||||||
pair: PGPKeyPair,
|
pair: PGPKeyPair,
|
||||||
userAttribute: PGPUserAttributeSubpacketVector,
|
userAttribute: PGPUserAttributeSubpacketVector,
|
||||||
|
@ -515,6 +636,15 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
|
||||||
return builder.build(userAttribute)
|
return builder.build(userAttribute)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a DirectKey self signature over the primary key [pair].
|
||||||
|
*
|
||||||
|
* @param pair primary key pair
|
||||||
|
* @param hashAlgorithm hash algorithm to be used during signature calculation
|
||||||
|
* @param subpacketsCallback callback to modify the subpackets of the direct-key signature
|
||||||
|
*
|
||||||
|
* @return direct-key self signature
|
||||||
|
*/
|
||||||
fun buildDirectKeySignature(
|
fun buildDirectKeySignature(
|
||||||
pair: PGPKeyPair,
|
pair: PGPKeyPair,
|
||||||
hashAlgorithm: HashAlgorithm,
|
hashAlgorithm: HashAlgorithm,
|
||||||
|
@ -530,7 +660,13 @@ abstract class ApplyToPrimaryKey(var keyPair: PGPKeyPair, val builder: DefinePri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Function that can be applied to subkeys. */
|
/**
|
||||||
|
* Function that can be applied to subkeys.
|
||||||
|
*
|
||||||
|
* @param primaryKey primary key pair
|
||||||
|
* @param subkey subkey pair
|
||||||
|
* @param builder builder instance that generated the subkey
|
||||||
|
*/
|
||||||
abstract class ApplyToSubkey(
|
abstract class ApplyToSubkey(
|
||||||
val primaryKey: PGPKeyPair,
|
val primaryKey: PGPKeyPair,
|
||||||
val subkey: PGPKeyPair,
|
val subkey: PGPKeyPair,
|
||||||
|
@ -541,6 +677,10 @@ abstract class ApplyToSubkey(
|
||||||
* Add a binding signature to the subkey.
|
* Add a binding signature to the subkey.
|
||||||
*
|
*
|
||||||
* @param subpacketsCallback callback to modify the binding signatures subpackets
|
* @param subpacketsCallback callback to modify the binding signatures subpackets
|
||||||
|
* @param hashAlgorithm hash algorithm to be used during signature calculation
|
||||||
|
* @param bindingTime creation time of the binding signature
|
||||||
|
*
|
||||||
|
* @return modified subkey pair
|
||||||
*/
|
*/
|
||||||
abstract fun addBindingSignature(
|
abstract fun addBindingSignature(
|
||||||
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop(),
|
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop(),
|
||||||
|
@ -549,6 +689,13 @@ abstract class ApplyToSubkey(
|
||||||
bindingTime: Date = subkey.publicKey.creationTime
|
bindingTime: Date = subkey.publicKey.creationTime
|
||||||
): PGPKeyPair
|
): PGPKeyPair
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the [ApplyToSubkey] function tailored to OpenPGP v4 keys.
|
||||||
|
*
|
||||||
|
* @param primaryKey primary key pair
|
||||||
|
* @param subkey subkey pair
|
||||||
|
* @param builder builder instance that generated the subkey
|
||||||
|
*/
|
||||||
class V4(primaryKey: PGPKeyPair, subkey: PGPKeyPair, builder: DefineSubkeys<*>) :
|
class V4(primaryKey: PGPKeyPair, subkey: PGPKeyPair, builder: DefineSubkeys<*>) :
|
||||||
ApplyToSubkey(primaryKey, subkey, builder) {
|
ApplyToSubkey(primaryKey, subkey, builder) {
|
||||||
|
|
||||||
|
@ -565,6 +712,17 @@ abstract class ApplyToSubkey(
|
||||||
PGPPublicKey.addCertification(subkey.publicKey, sig), subkey.privateKey)
|
PGPPublicKey.addCertification(subkey.publicKey, sig), subkey.privateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a version 4 binding signature that binds the [subkey] to the [primaryKey].
|
||||||
|
*
|
||||||
|
* @param primaryKey primary key pair
|
||||||
|
* @param subkey subkey pair
|
||||||
|
* @param hashAlgorithm hash algorithm to be used during signature calculation
|
||||||
|
* @param bindingTime creation time of the subkey
|
||||||
|
* @param subpacketsCallback callback to modify the subpackets of the binding signature
|
||||||
|
*
|
||||||
|
* @return subkey binding signature
|
||||||
|
*/
|
||||||
fun buildBindingSignature(
|
fun buildBindingSignature(
|
||||||
primaryKey: PGPKeyPair,
|
primaryKey: PGPKeyPair,
|
||||||
subkey: PGPKeyPair,
|
subkey: PGPKeyPair,
|
||||||
|
@ -584,35 +742,60 @@ abstract class ApplyToSubkey(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun generateKeyPair(type: KeyType): KeyPair =
|
/**
|
||||||
KeyPairGenerator.getInstance(type.name, ProviderFactory.provider)
|
* Templates for OpenPGP key generation.
|
||||||
.also { it.initialize(type.algorithmSpec) }
|
*/
|
||||||
.generateKeyPair()
|
|
||||||
|
|
||||||
class OpenPgpKeyTemplates {
|
class OpenPgpKeyTemplates {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Templates for version 4 OpenPGP keys.
|
||||||
|
*
|
||||||
|
* @return templates
|
||||||
|
*/
|
||||||
@JvmStatic fun v4() = V4()
|
@JvmStatic fun v4() = V4()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Templates for version 4 OpenPGP keys.
|
||||||
|
* Version 4 keys are compliant to RFC4880.
|
||||||
|
*/
|
||||||
class V4 {
|
class V4 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate an OpenPGP key that consists of an Ed25519 primary key used for certification
|
||||||
|
* of third-party keys, a dedicated Ed25519 subkey for message signing, and an X25519
|
||||||
|
* subkey used for message encryption.
|
||||||
|
*
|
||||||
|
* @param userId an arbitrary number of user-ids. The first UserID will be marked as primary
|
||||||
|
* @param creationTime creation time for the OpenPGP key
|
||||||
|
*/
|
||||||
fun ed25519Curve25519(
|
fun ed25519Curve25519(
|
||||||
vararg userId: CharSequence,
|
vararg userId: CharSequence,
|
||||||
creationTime: Date = Date()
|
creationTime: Date = Date()
|
||||||
): PGPSecretKeyRing =
|
): PGPSecretKeyRing =
|
||||||
buildV4(creationTime = creationTime)
|
buildV4(creationTime = creationTime)
|
||||||
// .setCertificationKey(KeyType.EDDSA(EdDSACurve._Ed25519))
|
|
||||||
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
|
.setPrimaryKey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
|
||||||
userId.forEach { addUserId(it) }
|
// Add UserIDs
|
||||||
|
userId.forEachIndexed { index, uid ->
|
||||||
|
if (index == 0) {
|
||||||
|
// Mark first UserID as primary
|
||||||
|
addUserId(uid, SelfSignatureSubpackets.applyHashed { setPrimaryUserId() })
|
||||||
|
} else {
|
||||||
|
addUserId(uid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add Direct-Key signature with preferences and keyFlags
|
||||||
addDirectKeySignature(
|
addDirectKeySignature(
|
||||||
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.CERTIFY_OTHER) })
|
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.CERTIFY_OTHER) })
|
||||||
keyPair
|
|
||||||
}
|
}
|
||||||
|
// singing key
|
||||||
.addSubkey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
|
.addSubkey(KeyType.EDDSA(EdDSACurve._Ed25519)) {
|
||||||
addBindingSignature(
|
addBindingSignature(
|
||||||
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.SIGN_DATA) })
|
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.SIGN_DATA) })
|
||||||
}
|
}
|
||||||
|
// encryption key
|
||||||
.addSubkey(KeyType.XDH(XDHSpec._X25519)) {
|
.addSubkey(KeyType.XDH(XDHSpec._X25519)) {
|
||||||
addBindingSignature(
|
addBindingSignature(
|
||||||
SelfSignatureSubpackets.applyHashed {
|
SelfSignatureSubpackets.applyHashed {
|
||||||
|
@ -621,6 +804,15 @@ class OpenPgpKeyTemplates {
|
||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate an OpenPGP key that consists of an RSA primary key used for certification
|
||||||
|
* of third-party keys, a dedicated RSA subkey for message signing, and an RSA
|
||||||
|
* subkey used for message encryption.
|
||||||
|
*
|
||||||
|
* @param userId an arbitrary number of user-ids. The first UserID will be marked as primary
|
||||||
|
* @param creationTime creation time for the OpenPGP key
|
||||||
|
* @param length RSA bit strength
|
||||||
|
*/
|
||||||
fun composedRsa(
|
fun composedRsa(
|
||||||
vararg userId: CharSequence,
|
vararg userId: CharSequence,
|
||||||
creationTime: Date = Date(),
|
creationTime: Date = Date(),
|
||||||
|
@ -628,15 +820,25 @@ class OpenPgpKeyTemplates {
|
||||||
): PGPSecretKeyRing =
|
): PGPSecretKeyRing =
|
||||||
buildV4(creationTime = creationTime)
|
buildV4(creationTime = creationTime)
|
||||||
.setPrimaryKey(KeyType.RSA(length)) {
|
.setPrimaryKey(KeyType.RSA(length)) {
|
||||||
userId.forEach { addUserId(it) }
|
// Add UserIDs
|
||||||
|
userId.forEachIndexed { index, uid ->
|
||||||
|
if (index == 0) {
|
||||||
|
// Mark first UserID as primary
|
||||||
|
addUserId(uid, SelfSignatureSubpackets.applyHashed { setPrimaryUserId() })
|
||||||
|
} else {
|
||||||
|
addUserId(uid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add Direct-Key signature with preferences and keyFlags
|
||||||
addDirectKeySignature(
|
addDirectKeySignature(
|
||||||
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.CERTIFY_OTHER) })
|
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.CERTIFY_OTHER) })
|
||||||
keyPair
|
|
||||||
}
|
}
|
||||||
|
// signing key
|
||||||
.addSubkey(KeyType.RSA(length)) {
|
.addSubkey(KeyType.RSA(length)) {
|
||||||
addBindingSignature(
|
addBindingSignature(
|
||||||
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.SIGN_DATA) })
|
SelfSignatureSubpackets.applyHashed { setKeyFlags(KeyFlag.SIGN_DATA) })
|
||||||
}
|
}
|
||||||
|
// encryption key
|
||||||
.addSubkey(KeyType.RSA(length)) {
|
.addSubkey(KeyType.RSA(length)) {
|
||||||
addBindingSignature(
|
addBindingSignature(
|
||||||
SelfSignatureSubpackets.applyHashed {
|
SelfSignatureSubpackets.applyHashed {
|
||||||
|
@ -645,6 +847,14 @@ class OpenPgpKeyTemplates {
|
||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate an OpenPGP key consisting of a single RSA key that is used for certification of
|
||||||
|
* third-party keys, signing and encryption of messages.
|
||||||
|
*
|
||||||
|
* @param userId an arbitrary number of UserIDs. The first one will be marked as primary.
|
||||||
|
* @param creationTime creation time of the OpenPGP key
|
||||||
|
* @param length bit-strength of the RSA key
|
||||||
|
*/
|
||||||
fun singleRsa(
|
fun singleRsa(
|
||||||
vararg userId: CharSequence,
|
vararg userId: CharSequence,
|
||||||
creationTime: Date = Date(),
|
creationTime: Date = Date(),
|
||||||
|
|
|
@ -4,10 +4,14 @@ 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.pgpainless.PGPainless
|
||||||
|
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.util.DateUtil
|
import org.pgpainless.util.DateUtil
|
||||||
|
|
||||||
class OpenPgpKeyGeneratorTest {
|
class OpenPgpKeyGeneratorTest {
|
||||||
|
@ -105,4 +109,16 @@ class OpenPgpKeyGeneratorTest {
|
||||||
println(it)
|
println(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `key generation with too weak PK algorithms fails`() {
|
||||||
|
val policy = Policy.getInstance()
|
||||||
|
policy.publicKeyAlgorithmPolicy = Policy.PublicKeyAlgorithmPolicy(
|
||||||
|
buildMap { put(PublicKeyAlgorithm.RSA_GENERAL, 3072) }
|
||||||
|
)
|
||||||
|
|
||||||
|
assertThrows<IllegalArgumentException> {
|
||||||
|
buildV4(policy).setPrimaryKey(KeyType.RSA(RsaLength._2048))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue