1
0
Fork 0
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:
Paul Schaub 2024-01-27 18:45:55 +01:00
parent 6df4211985
commit 44a3096467
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
3 changed files with 75 additions and 22 deletions

View file

@ -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(
private val policy: Policy,
private val referenceTime: Date = Date(),
private val preferences: AlgorithmSuite = policy.keyGenerationAlgorithmSuite
) {
abstract class OpenPgpKeyBuilder(
protected val policy: Policy, protected val policy: Policy,
protected val referenceTime: Date = Date(), protected val referenceTime: Date,
protected val preferences: AlgorithmSuite = policy.keyGenerationAlgorithmSuite protected val preferences: AlgorithmSuite
) { ) {
/** /**
* Build an OpenPGP v4 key. The result will be a key compliant to RFC4880, RFC6637. * Make sure, that the chosen [KeyType] is allowed.
*
* @param keyType type of the primary key
* @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.
*/ */
fun buildV4Key( open fun sanitizePublicKeyAlgorithms(keyType: KeyType, policy: Policy) {
keyType: KeyType, verifyAlgorithmComplianceWithPolicy(keyType, policy)
flags: List<KeyFlag>? = listOf(KeyFlag.CERTIFY_OTHER) }
): V4OpenPgpKeyBuilder = V4OpenPgpKeyBuilder(keyType, flags, policy, referenceTime, preferences)
internal fun verifyAlgorithmComplianceWithPolicy(keyType: KeyType, policy: 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 algorithm = keyType.algorithm
val bitStrength = keyType.bitStrength val bitStrength = keyType.bitStrength
require(policy.publicKeyAlgorithmPolicy.isAcceptable(algorithm, bitStrength)) { require(policy.publicKeyAlgorithmPolicy.isAcceptable(algorithm, bitStrength)) {
"Public key algorithm policy violation: $algorithm with bit strength $bitStrength is not acceptable." "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.
*
* @param keyType type of the primary key
* @param flags key flags for the primary key. Defaults to [KeyFlag.CERTIFY_OTHER].
* @return [V4GenerateOpenPgpKey] which can be further modified, e.g. add subkeys, user-ids etc.
*/
fun buildV4Key(
keyType: KeyType,
flags: List<KeyFlag>? = listOf(KeyFlag.CERTIFY_OTHER)
): V4GenerateOpenPgpKey = V4GenerateOpenPgpKey(keyType, flags, policy, referenceTime, preferences)
/** /**
* 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))
} }

View file

@ -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

View file

@ -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
}
}