mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 12:27:58 +01:00
WIP: Work on new key generation API
This commit is contained in:
parent
831e2497ed
commit
0e25ada166
3 changed files with 242 additions and 0 deletions
|
@ -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())
|
||||||
|
}
|
|
@ -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()
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue