1
0
Fork 0
mirror of https://github.com/pgpainless/pgpainless.git synced 2025-09-09 10:19:39 +02:00

SOP generate-key: Implement additional profiles

This commit is contained in:
Paul Schaub 2025-05-30 14:21:43 +02:00
parent e280aa34a0
commit 330e7eaee8
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
3 changed files with 90 additions and 12 deletions

View file

@ -21,6 +21,8 @@ import org.pgpainless.key.generation.KeySpec;
import org.pgpainless.key.generation.type.KeyType;
import org.pgpainless.key.generation.type.eddsa_legacy.EdDSALegacyCurve;
import org.pgpainless.key.generation.type.xdh_legacy.XDHLegacySpec;
import org.pgpainless.sop.EncryptImpl;
import org.pgpainless.sop.GenerateKeyImpl;
import org.slf4j.LoggerFactory;
import sop.exception.SOPGPException;
@ -647,7 +649,7 @@ public class RoundTripEncryptDecryptCmdTest extends CLITest {
// Generate key
File passwordFile = writeFile("password", "sw0rdf1sh");
File keyFile = pipeStdoutToFile("key.asc");
assertSuccess(executeCommand("generate-key", "--profile=rfc4880", "--with-key-password", passwordFile.getAbsolutePath(), "Alice <alice@example.org>"));
assertSuccess(executeCommand("generate-key", "--profile=" + GenerateKeyImpl.RFC4880_RSA4096_PROFILE.getName(), "--with-key-password", passwordFile.getAbsolutePath(), "Alice <alice@example.org>"));
File certFile = pipeStdoutToFile("cert.asc");
pipeFileToStdin(keyFile);
@ -659,7 +661,7 @@ public class RoundTripEncryptDecryptCmdTest extends CLITest {
// Encrypt
File ciphertextFile = pipeStdoutToFile("msg.asc");
pipeFileToStdin(plaintextFile);
assertSuccess(executeCommand("encrypt", "--profile=rfc4880", certFile.getAbsolutePath()));
assertSuccess(executeCommand("encrypt", "--profile=" + EncryptImpl.RFC4880_PROFILE.getName(), certFile.getAbsolutePath()));
ByteArrayOutputStream decrypted = pipeStdoutToStream();
pipeFileToStdin(ciphertextFile);

View file

@ -19,6 +19,7 @@ import org.pgpainless.bouncycastle.extensions.encode
import org.pgpainless.key.generation.KeyRingBuilder
import org.pgpainless.key.generation.KeySpec
import org.pgpainless.key.generation.type.KeyType
import org.pgpainless.key.generation.type.ecc.EllipticCurve
import org.pgpainless.key.generation.type.eddsa_legacy.EdDSALegacyCurve
import org.pgpainless.key.generation.type.rsa.RsaLength
import org.pgpainless.key.generation.type.xdh_legacy.XDHLegacySpec
@ -34,17 +35,24 @@ class GenerateKeyImpl(private val api: PGPainless) : GenerateKey {
companion object {
@JvmField
val CURVE25519_PROFILE =
Profile(
"draft-koch-eddsa-for-openpgp-00", "Generate EdDSA / ECDH keys using Curve25519")
@JvmField val RSA4096_PROFILE = Profile("rfc4880", "Generate 4096-bit RSA keys")
@JvmField val RFC9580_PROFILE = Profile("rfc9580", "Generate OpenPGP v6 keys")
Profile("draft-koch-eddsa-for-openpgp-00", "OpenPGP v4 keys over Curve25519")
@JvmField
val RFC4880_RSA4096_PROFILE = Profile("rfc4880-rsa4096", "OpenPGP v4 keys with RSA 4096")
@JvmField val RFC6637_NIST_P256_PROFILE = Profile("rfc6637-nist-p256")
@JvmField val RFC6637_NIST_P384_PROFILE = Profile("rfc6637-nist-p384")
@JvmField val RFC6637_NIST_P521_PROFILE = Profile("rfc6637-nist-p521")
@JvmField
val RFC9580_CURVE25519_PROFILE =
Profile("rfc9580-curve25519", "OpenPGP v6 keys over Curve25519")
@JvmField
val RFC9580_CURVE448_PROFILE = Profile("rfc9580-curve448", "OpenPGP v6 keys over Curve448")
@JvmField
val SUPPORTED_PROFILES =
listOf(
CURVE25519_PROFILE.withAliases("default", "compatibility"),
RSA4096_PROFILE,
RFC9580_PROFILE.withAliases("performance", "security"))
RFC4880_RSA4096_PROFILE,
RFC9580_CURVE25519_PROFILE.withAliases("performance", "security"))
}
private val userIds = mutableSetOf<String>()
@ -116,7 +124,7 @@ class GenerateKeyImpl(private val api: PGPainless) : GenerateKey {
KeyFlag.ENCRYPT_STORAGE))
}
}
RSA4096_PROFILE.name -> {
RFC4880_RSA4096_PROFILE.name -> {
api.buildKey(OpenPGPKeyVersion.v4)
.setPrimaryKey(
KeySpec.getBuilder(KeyType.RSA(RsaLength._4096), KeyFlag.CERTIFY_OTHER))
@ -132,7 +140,61 @@ class GenerateKeyImpl(private val api: PGPainless) : GenerateKey {
}
}
}
RFC9580_PROFILE.name -> {
RFC6637_NIST_P256_PROFILE.name -> {
api.buildKey(OpenPGPKeyVersion.v4)
.setPrimaryKey(
KeySpec.getBuilder(
KeyType.ECDSA(EllipticCurve._P256), KeyFlag.CERTIFY_OTHER))
.addSubkey(
KeySpec.getBuilder(
KeyType.ECDSA(EllipticCurve._P256), KeyFlag.SIGN_DATA))
.apply {
if (!signingOnly) {
addSubkey(
KeySpec.getBuilder(
KeyType.ECDH(EllipticCurve._P256),
KeyFlag.ENCRYPT_COMMS,
KeyFlag.ENCRYPT_STORAGE))
}
}
}
RFC6637_NIST_P384_PROFILE.name -> {
api.buildKey(OpenPGPKeyVersion.v4)
.setPrimaryKey(
KeySpec.getBuilder(
KeyType.ECDSA(EllipticCurve._P384), KeyFlag.CERTIFY_OTHER))
.addSubkey(
KeySpec.getBuilder(
KeyType.ECDSA(EllipticCurve._P384), KeyFlag.SIGN_DATA))
.apply {
if (!signingOnly) {
addSubkey(
KeySpec.getBuilder(
KeyType.ECDH(EllipticCurve._P384),
KeyFlag.ENCRYPT_COMMS,
KeyFlag.ENCRYPT_STORAGE))
}
}
}
RFC6637_NIST_P521_PROFILE.name -> {
api.buildKey(OpenPGPKeyVersion.v4)
.setPrimaryKey(
KeySpec.getBuilder(
KeyType.ECDSA(EllipticCurve._P521), KeyFlag.CERTIFY_OTHER))
.addSubkey(
KeySpec.getBuilder(
KeyType.ECDSA(EllipticCurve._P521), KeyFlag.SIGN_DATA))
.apply {
if (!signingOnly) {
addSubkey(
KeySpec.getBuilder(
KeyType.ECDH(EllipticCurve._P521),
KeyFlag.ENCRYPT_COMMS,
KeyFlag.ENCRYPT_STORAGE))
}
}
}
RFC9580_CURVE25519_PROFILE.name -> {
api.buildKey(OpenPGPKeyVersion.v6)
.setPrimaryKey(KeySpec.getBuilder(KeyType.Ed25519(), KeyFlag.CERTIFY_OTHER))
.addSubkey(KeySpec.getBuilder(KeyType.Ed25519(), KeyFlag.SIGN_DATA))
@ -146,6 +208,20 @@ class GenerateKeyImpl(private val api: PGPainless) : GenerateKey {
}
}
}
RFC9580_CURVE448_PROFILE.name -> {
api.buildKey(OpenPGPKeyVersion.v6)
.setPrimaryKey(KeySpec.getBuilder(KeyType.Ed448(), KeyFlag.CERTIFY_OTHER))
.addSubkey(KeySpec.getBuilder(KeyType.Ed448(), KeyFlag.SIGN_DATA))
.apply {
if (!signingOnly) {
addSubkey(
KeySpec.getBuilder(
KeyType.X448(),
KeyFlag.ENCRYPT_COMMS,
KeyFlag.ENCRYPT_STORAGE))
}
}
}
else -> throw SOPGPException.UnsupportedProfile("generate-key", profile)
}

View file

@ -568,7 +568,7 @@ public class EncryptDecryptRoundTripTest {
public void encryptWithSupportedProfileTest() throws IOException {
byte[] key = sop.generateKey()
.profile("rfc4880")
.profile(GenerateKeyImpl.RFC4880_RSA4096_PROFILE.getName())
.userId("Alice <alice@pgpainless.org>")
.generate()
.getBytes();
@ -578,7 +578,7 @@ public class EncryptDecryptRoundTripTest {
.getBytes();
byte[] encrypted = sop.encrypt()
.profile("rfc4880")
.profile(EncryptImpl.RFC4880_PROFILE.getName())
.withCert(cert)
.plaintext(message)
.toByteArrayAndResult()