2024-01-06 01:31:12 +01:00
|
|
|
package org.pgpainless.key.generation
|
|
|
|
|
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
|
|
|
|
import org.pgpainless.algorithm.HashAlgorithm
|
|
|
|
import org.pgpainless.algorithm.SignatureType
|
2024-01-06 01:31:12 +01:00
|
|
|
import org.pgpainless.implementation.ImplementationFactory
|
|
|
|
import org.pgpainless.key.generation.type.KeyType
|
|
|
|
import org.pgpainless.key.generation.type.eddsa.EdDSACurve
|
|
|
|
import org.pgpainless.key.generation.type.rsa.RsaLength
|
|
|
|
import org.pgpainless.key.generation.type.xdh.XDHSpec
|
|
|
|
import org.pgpainless.provider.ProviderFactory
|
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
|
|
|
import java.security.KeyPairGenerator
|
2024-01-08 13:51:16 +01:00
|
|
|
import java.util.*
|
2024-01-06 01:31:12 +01:00
|
|
|
|
|
|
|
class OpenPgpKeyBuilder {
|
|
|
|
|
|
|
|
fun buildV4Key(
|
|
|
|
type: KeyType,
|
|
|
|
creationTime: Date = Date()
|
|
|
|
): V4PrimaryKeyBuilder = V4PrimaryKeyBuilder(type, creationTime)
|
|
|
|
|
|
|
|
abstract class V4KeyBuilder<T: V4KeyBuilder<T>>(
|
2024-01-08 13:51:16 +01:00
|
|
|
val type: KeyType,
|
|
|
|
val creationTime: Date,
|
2024-01-06 01:31:12 +01:00
|
|
|
val certificateCreationTime: Date = Date()
|
|
|
|
) {
|
|
|
|
|
2024-01-08 13:51:16 +01:00
|
|
|
internal var key = generateKeyPair()
|
2024-01-06 01:31:12 +01:00
|
|
|
|
|
|
|
fun subkey(
|
|
|
|
type: KeyType,
|
|
|
|
creationTime: Date = certificateCreationTime
|
2024-01-08 13:51:16 +01:00
|
|
|
): V4SubkeyBuilder = V4SubkeyBuilder(type, creationTime, 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
|
|
|
|
val keyPair = KeyPairGenerator.getInstance(type.name, ProviderFactory.provider)
|
|
|
|
.also { it.initialize(type.algorithmSpec) }
|
|
|
|
.generateKeyPair()
|
|
|
|
|
|
|
|
// Form PGP Key Pair
|
|
|
|
return ImplementationFactory.getInstance()
|
|
|
|
.getPGPV4KeyPair(type.algorithm, keyPair, creationTime)
|
2024-01-08 13:51:16 +01:00
|
|
|
.let {
|
|
|
|
adjustKeyPacket(it)
|
|
|
|
}
|
2024-01-06 01:31:12 +01:00
|
|
|
}
|
2024-01-08 13:51:16 +01:00
|
|
|
|
|
|
|
protected abstract fun adjustKeyPacket(keyPair: PGPKeyPair): PGPKeyPair
|
2024-01-06 01:31:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
class V4PrimaryKeyBuilder(
|
|
|
|
type: KeyType,
|
|
|
|
creationTime: Date
|
|
|
|
): V4KeyBuilder<V4PrimaryKeyBuilder>(type, creationTime) {
|
|
|
|
|
2024-01-08 13:51:16 +01:00
|
|
|
fun userId(
|
|
|
|
userId: CharSequence,
|
|
|
|
bindingTime: Date = creationTime,
|
|
|
|
hashAlgorithm: HashAlgorithm = HashAlgorithm.SHA512,
|
|
|
|
subpacketsCallback: SelfSignatureSubpackets.Callback =
|
|
|
|
object : SelfSignatureSubpackets.Callback {
|
|
|
|
|
|
|
|
}
|
|
|
|
) = apply {
|
|
|
|
val sig = SelfSignatureBuilder(
|
|
|
|
key.privateKey,
|
|
|
|
key.publicKey,
|
|
|
|
SignatureType.POSITIVE_CERTIFICATION,
|
|
|
|
hashAlgorithm)
|
|
|
|
.applyCallback(subpacketsCallback)
|
|
|
|
.build(userId)
|
|
|
|
key = PGPKeyPair(
|
|
|
|
PGPPublicKey.addCertification(key.publicKey, userId.toString(), sig),
|
|
|
|
key.privateKey
|
|
|
|
)
|
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-08 13:51:16 +01:00
|
|
|
private val primaryKeyBuilder: V4PrimaryKeyBuilder
|
|
|
|
): V4KeyBuilder<V4SubkeyBuilder>(type, creationTime) {
|
|
|
|
|
|
|
|
fun bindingSignature(subpacketCallback: SelfSignatureSubpackets.Callback) = apply {
|
|
|
|
SubkeyBindingSignatureBuilder(primaryKeyBuilder.key.privateKey, primaryKeyBuilder.key.publicKey)
|
|
|
|
.applyCallback(subpacketCallback)
|
|
|
|
.build(key.publicKey)
|
|
|
|
.let {
|
|
|
|
key = PGPKeyPair(
|
|
|
|
PGPPublicKey.addCertification(key.publicKey, it),
|
|
|
|
key.privateKey)
|
|
|
|
}
|
|
|
|
}
|
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
|
|
|
|
val subkey = PublicSubkeyPacket(pubkey.algorithm,
|
|
|
|
pubkey.creationTime, pubkey.publicKeyPacket.key)
|
|
|
|
return PGPKeyPair(
|
|
|
|
PGPPublicKey(subkey, fpCalc),
|
|
|
|
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()
|
|
|
|
|
|
|
|
fun bindingSignature(
|
|
|
|
bindingTime: Date = creationTime
|
|
|
|
): V4SubkeyBuilder = bindingSignature(object : SelfSignatureSubpackets.Callback {
|
|
|
|
override fun modifyHashedSubpackets(hashedSubpackets: SelfSignatureSubpackets) {
|
|
|
|
hashedSubpackets.setSignatureCreationTime(bindingTime)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2024-01-06 01:31:12 +01:00
|
|
|
}
|