1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-06-25 04:54:49 +02:00
pgpainless/pgpainless-core/src/main/kotlin/org/pgpainless/key/generation/OpenPgpKeyBuilder.kt

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

237 lines
9.5 KiB
Kotlin
Raw Normal View History

2024-01-06 01:31:12 +01:00
package org.pgpainless.key.generation
2024-01-11 16:44:21 +01:00
import java.security.KeyPairGenerator
import java.util.*
2024-01-08 13:51:16 +01:00
import org.bouncycastle.bcpg.PublicSubkeyPacket
2024-01-06 01:31:12 +01:00
import org.bouncycastle.openpgp.PGPKeyPair
2024-01-08 13:51:16 +01:00
import org.bouncycastle.openpgp.PGPPrivateKey
import org.bouncycastle.openpgp.PGPPublicKey
2024-01-11 16:44:21 +01:00
import org.bouncycastle.openpgp.PGPSignature
import org.bouncycastle.openpgp.PGPUserAttributeSubpacketVector
import org.pgpainless.algorithm.CertificationType
2024-01-08 13:51:16 +01:00
import org.pgpainless.algorithm.HashAlgorithm
2024-01-11 16:44:21 +01:00
import org.pgpainless.algorithm.KeyFlag
2024-01-06 01:31:12 +01:00
import org.pgpainless.implementation.ImplementationFactory
import org.pgpainless.key.generation.type.KeyType
2024-01-11 16:44:21 +01:00
import org.pgpainless.policy.Policy
2024-01-06 01:31:12 +01:00
import org.pgpainless.provider.ProviderFactory
2024-01-11 16:44:21 +01:00
import org.pgpainless.signature.builder.DirectKeySelfSignatureBuilder
import org.pgpainless.signature.builder.PrimaryKeyBindingSignatureBuilder
2024-01-08 13:51:16 +01:00
import org.pgpainless.signature.builder.SelfSignatureBuilder
import org.pgpainless.signature.builder.SubkeyBindingSignatureBuilder
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets
2024-01-06 01:31:12 +01:00
class OpenPgpKeyBuilder {
fun buildV4Key(
type: KeyType,
2024-01-11 16:44:21 +01:00
creationTime: Date = Date(),
policy: Policy
): V4PrimaryKeyBuilder = V4PrimaryKeyBuilder(type, creationTime, policy)
2024-01-06 01:31:12 +01:00
2024-01-11 16:44:21 +01:00
abstract class V4KeyBuilder<T : V4KeyBuilder<T>>(
2024-01-08 13:51:16 +01:00
val type: KeyType,
val creationTime: Date,
2024-01-11 16:44:21 +01:00
val certificateCreationTime: Date = Date(),
val policy: Policy
2024-01-06 01:31:12 +01:00
) {
2024-01-08 13:51:16 +01:00
internal var key = generateKeyPair()
2024-01-06 01:31:12 +01:00
2024-01-11 16:44:21 +01:00
fun subkey(type: KeyType, creationTime: Date = certificateCreationTime): V4SubkeyBuilder =
V4SubkeyBuilder(type, creationTime, policy, primaryKey())
2024-01-06 01:31:12 +01:00
2024-01-08 13:51:16 +01:00
internal abstract fun primaryKey(): V4PrimaryKeyBuilder
2024-01-06 01:31:12 +01:00
private fun generateKeyPair(): PGPKeyPair {
// Create raw Key Pair
2024-01-11 16:44:21 +01:00
val keyPair =
KeyPairGenerator.getInstance(type.name, ProviderFactory.provider)
.also { it.initialize(type.algorithmSpec) }
.generateKeyPair()
2024-01-06 01:31:12 +01:00
// Form PGP Key Pair
return ImplementationFactory.getInstance()
.getPGPV4KeyPair(type.algorithm, keyPair, creationTime)
2024-01-11 16:44:21 +01:00
.let { adjustKeyPacket(it) }
2024-01-06 01:31:12 +01:00
}
2024-01-08 13:51:16 +01:00
2024-01-11 16:44:21 +01:00
/**
* Make sure, the PGP key packet is a subkey packet for subkeys, and a primary key packet
* for primary keys.
*/
2024-01-08 13:51:16 +01:00
protected abstract fun adjustKeyPacket(keyPair: PGPKeyPair): PGPKeyPair
2024-01-06 01:31:12 +01:00
}
2024-01-11 16:44:21 +01:00
class V4PrimaryKeyBuilder(type: KeyType, creationTime: Date, policy: Policy) :
V4KeyBuilder<V4PrimaryKeyBuilder>(type, creationTime, policy = policy) {
2024-01-06 01:31:12 +01:00
2024-01-08 13:51:16 +01:00
fun userId(
userId: CharSequence,
2024-01-11 16:44:21 +01:00
certificationType: CertificationType = CertificationType.POSITIVE,
2024-01-08 13:51:16 +01:00
bindingTime: Date = creationTime,
2024-01-11 16:44:21 +01:00
hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
2024-01-08 13:51:16 +01:00
subpacketsCallback: SelfSignatureSubpackets.Callback =
2024-01-11 16:44:21 +01:00
SelfSignatureSubpackets.defaultCallback()
) = apply {
val sig =
buildCertificationFor(
userId, certificationType, bindingTime, hashAlgorithm, subpacketsCallback)
key =
PGPKeyPair(
PGPPublicKey.addCertification(key.publicKey, userId.toString(), sig),
key.privateKey)
}
2024-01-08 13:51:16 +01:00
2024-01-11 16:44:21 +01:00
fun buildCertificationFor(
userId: CharSequence,
certificationType: CertificationType,
bindingTime: Date,
hashAlgorithm: HashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback
): PGPSignature {
val builder =
SelfSignatureBuilder(
key.privateKey, key.publicKey, certificationType.signatureType, hashAlgorithm)
builder.hashedSubpackets.setSignatureCreationTime(bindingTime)
builder.applyCallback(subpacketsCallback)
return builder.build(userId)
}
fun userAttribute(
userAttribute: PGPUserAttributeSubpacketVector,
certificationType: CertificationType = CertificationType.POSITIVE,
bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback =
SelfSignatureSubpackets.defaultCallback()
) = apply {
val sig =
buildCertificationFor(
userAttribute,
certificationType,
bindingTime,
hashAlgorithm,
subpacketsCallback)
key =
PGPKeyPair(
PGPPublicKey.addCertification(key.publicKey, userAttribute, sig),
key.privateKey)
}
fun buildCertificationFor(
userAttribute: PGPUserAttributeSubpacketVector,
certificationType: CertificationType,
bindingTime: Date,
hashAlgorithm: HashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback
): PGPSignature {
val builder =
SelfSignatureBuilder(
key.privateKey, key.publicKey, certificationType.signatureType, hashAlgorithm)
builder.hashedSubpackets.setSignatureCreationTime(bindingTime)
builder.applyCallback(subpacketsCallback)
return builder.build(userAttribute)
}
fun directKeySignature(
bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm(),
subpacketsCallback: SelfSignatureSubpackets.Callback =
SelfSignatureSubpackets.defaultCallback()
2024-01-08 13:51:16 +01:00
) = apply {
2024-01-11 16:44:21 +01:00
val sig = buildDirectKeySignature(bindingTime, hashAlgorithm, subpacketsCallback)
key = PGPKeyPair(PGPPublicKey.addCertification(key.publicKey, sig), key.privateKey)
}
fun buildDirectKeySignature(
bindingTime: Date,
hashAlgorithm: HashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback
): PGPSignature {
val builder =
DirectKeySelfSignatureBuilder(key.privateKey, key.publicKey, hashAlgorithm)
builder.hashedSubpackets.setSignatureCreationTime(bindingTime)
builder.applyCallback(subpacketsCallback)
return builder.build()
2024-01-06 01:31:12 +01:00
}
2024-01-08 13:51:16 +01:00
override fun adjustKeyPacket(keyPair: PGPKeyPair): PGPKeyPair {
return keyPair // is already a secret key packet
2024-01-06 01:31:12 +01:00
}
2024-01-08 13:51:16 +01:00
override fun primaryKey() = this
2024-01-06 01:31:12 +01:00
}
class V4SubkeyBuilder(
type: KeyType,
creationTime: Date,
2024-01-11 16:44:21 +01:00
policy: Policy,
2024-01-08 13:51:16 +01:00
private val primaryKeyBuilder: V4PrimaryKeyBuilder
2024-01-11 16:44:21 +01:00
) : V4KeyBuilder<V4SubkeyBuilder>(type, creationTime, policy = policy) {
fun bindingSignature(
bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback =
SelfSignatureSubpackets.defaultCallback()
) = apply {
val sig = buildBindingSignature(bindingTime, hashAlgorithm, subpacketsCallback)
key = PGPKeyPair(PGPPublicKey.addCertification(key.publicKey, sig), key.privateKey)
}
fun buildBindingSignature(
bindingTime: Date = creationTime,
hashAlgorithm: HashAlgorithm =
policy.certificationSignatureHashAlgorithmPolicy.defaultHashAlgorithm,
subpacketsCallback: SelfSignatureSubpackets.Callback =
SelfSignatureSubpackets.defaultCallback()
): PGPSignature {
val builder =
SubkeyBindingSignatureBuilder(
primaryKeyBuilder.key.privateKey,
primaryKeyBuilder.key.publicKey,
hashAlgorithm)
builder.hashedSubpackets.setSignatureCreationTime(bindingTime)
builder.applyCallback(subpacketsCallback)
if (builder.hashedSubpackets.getKeyFlags().orEmpty().contains(KeyFlag.SIGN_DATA) &&
builder.hashedSubpackets.getEmbeddedSignaturePackets().isEmpty()) {
// Create back-sig
val backSigBuilder =
PrimaryKeyBindingSignatureBuilder(key.privateKey, key.publicKey, hashAlgorithm)
backSigBuilder.hashedSubpackets.setSignatureCreationTime(bindingTime)
val backSig = backSigBuilder.build(primaryKey().key.publicKey)
builder.hashedSubpackets.addEmbeddedSignature(backSig)
}
return builder.build(key.publicKey)
2024-01-08 13:51:16 +01:00
}
2024-01-06 01:31:12 +01:00
2024-01-08 13:51:16 +01:00
override fun adjustKeyPacket(keyPair: PGPKeyPair): PGPKeyPair {
val fpCalc = ImplementationFactory.getInstance().keyFingerprintCalculator
val pubkey = keyPair.publicKey
val privkey = keyPair.privateKey
// form subkey packet
2024-01-11 16:44:21 +01:00
val subkey =
PublicSubkeyPacket(
pubkey.algorithm, pubkey.creationTime, pubkey.publicKeyPacket.key)
2024-01-08 13:51:16 +01:00
return PGPKeyPair(
PGPPublicKey(subkey, fpCalc),
2024-01-11 16:44:21 +01:00
PGPPrivateKey(pubkey.keyID, subkey, privkey.privateKeyDataPacket))
2024-01-06 01:31:12 +01:00
}
2024-01-08 13:51:16 +01:00
override fun primaryKey() = primaryKeyBuilder.primaryKey()
}
2024-01-06 01:31:12 +01:00
}