mirror of
https://github.com/pgpainless/pgpainless.git
synced 2024-12-25 12:27:58 +01:00
Rename KeyGenerator and add MalformedKeyGenerationTest
This commit is contained in:
parent
6df4211985
commit
44a3096467
3 changed files with 75 additions and 22 deletions
|
@ -24,31 +24,51 @@ import org.pgpainless.signature.subpackets.SelfSignatureSubpackets
|
||||||
* @param referenceTime reference time for key generation
|
* @param referenceTime reference time for key generation
|
||||||
* @param preferences set of preferred algorithms and enabled features
|
* @param preferences set of preferred algorithms and enabled features
|
||||||
*/
|
*/
|
||||||
open class OpenPgpKeyBuilder(
|
open class GenerateOpenPgpKey(
|
||||||
protected val policy: Policy,
|
private val policy: Policy,
|
||||||
protected val referenceTime: Date = Date(),
|
private val referenceTime: Date = Date(),
|
||||||
protected val preferences: AlgorithmSuite = policy.keyGenerationAlgorithmSuite
|
private val preferences: AlgorithmSuite = policy.keyGenerationAlgorithmSuite
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
abstract class OpenPgpKeyBuilder(
|
||||||
|
protected val policy: Policy,
|
||||||
|
protected val referenceTime: Date,
|
||||||
|
protected val preferences: AlgorithmSuite
|
||||||
|
) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure, that the chosen [KeyType] is allowed.
|
||||||
|
*/
|
||||||
|
open fun sanitizePublicKeyAlgorithms(keyType: KeyType, policy: Policy) {
|
||||||
|
verifyAlgorithmComplianceWithPolicy(keyType, policy)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure, that the chosen [KeyType] complies to the given [Policy] by comparing it to the
|
||||||
|
* [Policy.PublicKeyAlgorithmPolicy].
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if [keyType] fails to be accepted by [policy]
|
||||||
|
*/
|
||||||
|
private fun verifyAlgorithmComplianceWithPolicy(keyType: KeyType, policy: Policy) {
|
||||||
|
val algorithm = keyType.algorithm
|
||||||
|
val bitStrength = keyType.bitStrength
|
||||||
|
require(policy.publicKeyAlgorithmPolicy.isAcceptable(algorithm, bitStrength)) {
|
||||||
|
"Public key algorithm policy violation: $algorithm with bit strength $bitStrength is not acceptable."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build an OpenPGP v4 key. The result will be a key compliant to RFC4880, RFC6637.
|
* Build an OpenPGP v4 key. The result will be a key compliant to RFC4880, RFC6637.
|
||||||
*
|
*
|
||||||
* @param keyType type of the primary key
|
* @param keyType type of the primary key
|
||||||
* @param flags key flags for the primary key. Defaults to [KeyFlag.CERTIFY_OTHER].
|
* @param flags key flags for the primary key. Defaults to [KeyFlag.CERTIFY_OTHER].
|
||||||
* @return [V4OpenPgpKeyBuilder] which can be further modified, e.g. add subkeys, user-ids etc.
|
* @return [V4GenerateOpenPgpKey] which can be further modified, e.g. add subkeys, user-ids etc.
|
||||||
*/
|
*/
|
||||||
fun buildV4Key(
|
fun buildV4Key(
|
||||||
keyType: KeyType,
|
keyType: KeyType,
|
||||||
flags: List<KeyFlag>? = listOf(KeyFlag.CERTIFY_OTHER)
|
flags: List<KeyFlag>? = listOf(KeyFlag.CERTIFY_OTHER)
|
||||||
): V4OpenPgpKeyBuilder = V4OpenPgpKeyBuilder(keyType, flags, policy, referenceTime, preferences)
|
): V4GenerateOpenPgpKey = V4GenerateOpenPgpKey(keyType, flags, policy, referenceTime, preferences)
|
||||||
|
|
||||||
internal fun verifyAlgorithmComplianceWithPolicy(keyType: KeyType, policy: Policy) {
|
|
||||||
val algorithm = keyType.algorithm
|
|
||||||
val bitStrength = keyType.bitStrength
|
|
||||||
require(policy.publicKeyAlgorithmPolicy.isAcceptable(algorithm, bitStrength)) {
|
|
||||||
"Public key algorithm policy violation: $algorithm with bit strength $bitStrength is not acceptable."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder for version 4 OpenPGP keys.
|
* Builder for version 4 OpenPGP keys.
|
||||||
|
@ -59,7 +79,7 @@ open class OpenPgpKeyBuilder(
|
||||||
* @param referenceTime reference time for key generation
|
* @param referenceTime reference time for key generation
|
||||||
* @param preferences set of algorithm preferences and enabled features for the key
|
* @param preferences set of algorithm preferences and enabled features for the key
|
||||||
*/
|
*/
|
||||||
class V4OpenPgpKeyBuilder
|
class V4GenerateOpenPgpKey
|
||||||
internal constructor(
|
internal constructor(
|
||||||
primaryKeyType: KeyType,
|
primaryKeyType: KeyType,
|
||||||
primaryFlags: List<KeyFlag>?,
|
primaryFlags: List<KeyFlag>?,
|
||||||
|
@ -69,7 +89,7 @@ open class OpenPgpKeyBuilder(
|
||||||
) : OpenPgpKeyBuilder(policy, referenceTime, preferences) {
|
) : OpenPgpKeyBuilder(policy, referenceTime, preferences) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
verifyAlgorithmComplianceWithPolicy(primaryKeyType, policy)
|
sanitizePublicKeyAlgorithms(primaryKeyType, policy)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val primaryKey =
|
private val primaryKey =
|
||||||
|
@ -152,7 +172,7 @@ open class OpenPgpKeyBuilder(
|
||||||
subkeyBuilder: BaseOpenPgpKeyBuilder.BaseV4SubkeyBuilder,
|
subkeyBuilder: BaseOpenPgpKeyBuilder.BaseV4SubkeyBuilder,
|
||||||
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
|
subpacketsCallback: SelfSignatureSubpackets.Callback = SelfSignatureSubpackets.nop()
|
||||||
) = apply {
|
) = apply {
|
||||||
verifyAlgorithmComplianceWithPolicy(subkeyBuilder.type, policy)
|
sanitizePublicKeyAlgorithms(subkeyBuilder.type, policy)
|
||||||
subkeys.add(subkeyBuilder.bindingSignature(subpacketsCallback = subpacketsCallback))
|
subkeys.add(subkeyBuilder.bindingSignature(subpacketsCallback = subpacketsCallback))
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,13 @@ import org.pgpainless.key.protection.SecretKeyRingProtector
|
||||||
import org.pgpainless.policy.Policy
|
import org.pgpainless.policy.Policy
|
||||||
import org.pgpainless.util.DateUtil
|
import org.pgpainless.util.DateUtil
|
||||||
|
|
||||||
class OpenPgpKeyBuilderTest {
|
class GenerateOpenPgpKeyTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test() {
|
fun test() {
|
||||||
val date = DateUtil.parseUTCDate("2020-04-01 10:00:00 UTC")
|
val date = DateUtil.parseUTCDate("2020-04-01 10:00:00 UTC")
|
||||||
val key =
|
val key =
|
||||||
OpenPgpKeyBuilder(Policy.getInstance(), date)
|
GenerateOpenPgpKey(Policy.getInstance(), date)
|
||||||
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519), listOf(KeyFlag.CERTIFY_OTHER))
|
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519), listOf(KeyFlag.CERTIFY_OTHER))
|
||||||
.addUserId("Alice")
|
.addUserId("Alice")
|
||||||
.addUserAttribute(
|
.addUserAttribute(
|
||||||
|
@ -37,7 +37,7 @@ class OpenPgpKeyBuilderTest {
|
||||||
@Test
|
@Test
|
||||||
fun minimal() {
|
fun minimal() {
|
||||||
val key =
|
val key =
|
||||||
OpenPgpKeyBuilder(Policy.getInstance())
|
GenerateOpenPgpKey(Policy.getInstance())
|
||||||
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519), listOf(KeyFlag.CERTIFY_OTHER))
|
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519), listOf(KeyFlag.CERTIFY_OTHER))
|
||||||
.build()
|
.build()
|
||||||
println(PGPainless.asciiArmor(key))
|
println(PGPainless.asciiArmor(key))
|
||||||
|
@ -46,7 +46,7 @@ class OpenPgpKeyBuilderTest {
|
||||||
@Test
|
@Test
|
||||||
fun minimalWithUserId() {
|
fun minimalWithUserId() {
|
||||||
val key =
|
val key =
|
||||||
OpenPgpKeyBuilder(Policy.getInstance())
|
GenerateOpenPgpKey(Policy.getInstance())
|
||||||
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519), listOf(KeyFlag.CERTIFY_OTHER))
|
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519), listOf(KeyFlag.CERTIFY_OTHER))
|
||||||
.addUserId("Alice <alice@pgpainless.org>")
|
.addUserId("Alice <alice@pgpainless.org>")
|
||||||
.build()
|
.build()
|
||||||
|
@ -60,7 +60,7 @@ class OpenPgpKeyBuilderTest {
|
||||||
Policy(
|
Policy(
|
||||||
publicKeyAlgorithmPolicy =
|
publicKeyAlgorithmPolicy =
|
||||||
Policy.PublicKeyAlgorithmPolicy(mapOf(PublicKeyAlgorithm.RSA_GENERAL to 4096)))
|
Policy.PublicKeyAlgorithmPolicy(mapOf(PublicKeyAlgorithm.RSA_GENERAL to 4096)))
|
||||||
val builder = OpenPgpKeyBuilder(policy)
|
val builder = GenerateOpenPgpKey(policy)
|
||||||
|
|
||||||
assertThrows<IllegalArgumentException> {
|
assertThrows<IllegalArgumentException> {
|
||||||
builder.buildV4Key(KeyType.RSA(RsaLength._3072)) // too weak
|
builder.buildV4Key(KeyType.RSA(RsaLength._3072)) // too weak
|
|
@ -0,0 +1,33 @@
|
||||||
|
// SPDX-FileCopyrightText: 2024 Paul Schaub <vanitasvitae@fsfe.org>
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package org.pgpainless.key.generation
|
||||||
|
|
||||||
|
import org.bouncycastle.bcpg.sig.PrimaryUserID
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.pgpainless.PGPainless
|
||||||
|
import org.pgpainless.key.generation.type.KeyType
|
||||||
|
import org.pgpainless.key.generation.type.eddsa.EdDSACurve
|
||||||
|
import org.pgpainless.policy.Policy
|
||||||
|
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets
|
||||||
|
|
||||||
|
class MalformedKeyGenerationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun malformedPrimaryUserIdSubpacket() {
|
||||||
|
val userId = "Alice <alice@pgpainless.org>"
|
||||||
|
val key = GenerateOpenPgpKey(Policy.getInstance())
|
||||||
|
.buildV4Key(KeyType.EDDSA(EdDSACurve._Ed25519))
|
||||||
|
.addUserId(userId,
|
||||||
|
SelfSignatureSubpackets.applyHashed {
|
||||||
|
setPrimaryUserId(PrimaryUserID(false, false, byteArrayOf(0x02)))
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
|
||||||
|
println(PGPainless.asciiArmor(key))
|
||||||
|
|
||||||
|
PGPainless.readKeyRing().secretKeyRing(key.encoded)!!
|
||||||
|
// TODO: Check interpretation of faulty PrimaryUserID packet
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue