1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2024-12-24 11:57:59 +01:00

WIP: Work on new key generation API

This commit is contained in:
Paul Schaub 2024-01-06 01:31:12 +01:00
parent 831e2497ed
commit 0e25ada166
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
3 changed files with 242 additions and 0 deletions

View file

@ -0,0 +1,99 @@
package org.pgpainless.key.generation
import org.bouncycastle.openpgp.PGPKeyPair
import org.bouncycastle.openpgp.PGPSecretKeyRing
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
import java.security.KeyPairGenerator
import java.util.Date
class OpenPgpKeyBuilder {
fun buildV4Key(
type: KeyType,
creationTime: Date = Date()
): V4PrimaryKeyBuilder = V4PrimaryKeyBuilder(type, creationTime)
abstract class V4KeyBuilder<T: V4KeyBuilder<T>>(
protected val type: KeyType,
protected val creationTime: Date,
val certificateCreationTime: Date = Date()
) {
internal val keyPair = generateKeyPair()
fun subkey(
type: KeyType,
creationTime: Date = certificateCreationTime
): V4SubkeyBuilder = V4SubkeyBuilder(type, creationTime, this)
fun generate(): PGPSecretKeyRing {
val keys = collectKeysForGeneration()
assert(keys.first() is V4PrimaryKeyBuilder)
assert(keys.drop(1).all { it is V4SubkeyBuilder })
val primaryKey: V4PrimaryKeyBuilder = keys.first() as V4PrimaryKeyBuilder
}
private fun collectKeysForGeneration(): List<V4KeyBuilder<*>> =
if (this is V4SubkeyBuilder) {
predecessor.collectKeysForGeneration().plus(this)
} else {
listOf(this)
}
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)
}
}
class V4PrimaryKeyBuilder(
type: KeyType,
creationTime: Date
): V4KeyBuilder<V4PrimaryKeyBuilder>(type, creationTime) {
fun userId(userId: CharSequence) = userId(userId, OpenPgpV4KeyGenerator.Preferences())
fun userId(userId: CharSequence, preferences: OpenPgpV4KeyGenerator.Preferences) = apply {
keyPair.publicKey.
}
fun selfSignature(preferences: OpenPgpV4KeyGenerator.Preferences) = apply {
}
}
class V4SubkeyBuilder(
type: KeyType,
creationTime: Date,
internal val predecessor: V4KeyBuilder<*>,
): V4KeyBuilder<V4SubkeyBuilder>(type, creationTime, predecessor.certificateCreationTime) {
fun bindingSignature(preferences: OpenPgpV4KeyGenerator.Preferences) = apply {
}
}
}
fun test() {
OpenPgpKeyBuilder()
.buildV4Key(KeyType.RSA(RsaLength._4096))
.selfSignature(OpenPgpV4KeyGenerator.Preferences())
.userId("Alice", OpenPgpV4KeyGenerator.Preferences())
.subkey(KeyType.EDDSA(EdDSACurve._Ed25519))
.bindingSignature(OpenPgpV4KeyGenerator.Preferences())
.subkey(KeyType.XDH(XDHSpec._X25519))
.bindingSignature(OpenPgpV4KeyGenerator.Preferences())
}

View file

@ -0,0 +1,117 @@
package org.pgpainless.key.generation
import org.bouncycastle.openpgp.PGPSecretKeyRing
import org.pgpainless.algorithm.KeyFlag
import org.pgpainless.key.generation.type.KeyType
import org.pgpainless.policy.Policy
import java.util.*
class OpenPgpV4KeyGenerator(
private val policy: Policy,
private val referenceTime: Date = Date()
) {
fun primaryKey(
type: KeyType,
vararg flag: KeyFlag = arrayOf(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
) = primaryKey(type, referenceTime, *flag)
fun primaryKey(
type: KeyType,
creationTime: Date,
vararg flag: KeyFlag = arrayOf(KeyFlag.CERTIFY_OTHER, KeyFlag.SIGN_DATA)
) = WithSubkeys(
KeyDescription(type, creationTime, flag.toList()),
policy,
referenceTime
)
class WithSubkeys(
private val primaryKey: KeyDescription,
private val policy: Policy,
private val referenceTime: Date
) {
val builder = OpenPgpKeyBuilder()
.buildV4Key(primaryKey.type)
.
init {
}
fun encryptionSubkey(
type: KeyType,
vararg flag: KeyFlag = arrayOf(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
) = encryptionSubkey(type, referenceTime, *flag)
fun encryptionSubkey(
type: KeyType,
creationTime: Date,
vararg flag: KeyFlag = arrayOf(KeyFlag.ENCRYPT_COMMS, KeyFlag.ENCRYPT_STORAGE)
) = subkey(type, creationTime, *flag)
fun signingSubkey(
type: KeyType
) = signingSubkey(type, referenceTime)
fun signingSubkey(
type: KeyType,
creationTime: Date
) = subkey(type, creationTime, KeyFlag.SIGN_DATA)
fun subkey(
type: KeyType,
vararg flag: KeyFlag
) = subkey(type, referenceTime, *flag)
fun subkey(
type: KeyType,
creationTime: Date = referenceTime,
vararg flag: KeyFlag
) = apply {
}
fun noUserId(
preferences: Preferences
): PGPSecretKeyRing {
}
fun userId(
userId: CharSequence,
preferences: Preferences
): WithUserIds = WithUserIds().apply {
userId(userId, preferences)
}
}
class WithUserIds {
fun userId(
userId: CharSequence,
preferences: Preferences
): WithUserIds {
}
fun done(): PGPSecretKeyRing {
}
fun directKeySignature(
preferences: Preferences
): PGPSecretKeyRing {
}
}
data class KeyDescription(
val type: KeyType,
val creationTime: Date,
val flags: List<KeyFlag>
)
data class Preferences()
}

View file

@ -0,0 +1,26 @@
package org.pgpainless.key.generation
import org.junit.jupiter.api.Test
import org.pgpainless.algorithm.KeyFlag
import org.pgpainless.key.generation.type.KeyType
import org.pgpainless.key.generation.type.rsa.RsaLength
import org.pgpainless.policy.Policy
class OpenPgpV4KeyGeneratorTest {
@Test
fun test() {
OpenPgpV4KeyGenerator(Policy.getInstance())
OpenPgpV4KeyGenerator(Policy.getInstance())
.primaryKey(
KeyType.RSA(RsaLength._4096),
KeyFlag.CERTIFY_OTHER
).signingSubkey(
KeyType.RSA(RsaLength._4096)
).encryptionSubkey(
KeyType.RSA(RsaLength._4096)
)
}
}