mirror of
https://github.com/pgpainless/pgpainless.git
synced 2025-09-09 18:29:39 +02:00
SOP generate-key: Implement additional profiles
This commit is contained in:
parent
e45b551ab3
commit
0027a3ed24
3 changed files with 90 additions and 12 deletions
|
@ -21,6 +21,8 @@ import org.pgpainless.key.generation.KeySpec;
|
||||||
import org.pgpainless.key.generation.type.KeyType;
|
import org.pgpainless.key.generation.type.KeyType;
|
||||||
import org.pgpainless.key.generation.type.eddsa_legacy.EdDSALegacyCurve;
|
import org.pgpainless.key.generation.type.eddsa_legacy.EdDSALegacyCurve;
|
||||||
import org.pgpainless.key.generation.type.xdh_legacy.XDHLegacySpec;
|
import org.pgpainless.key.generation.type.xdh_legacy.XDHLegacySpec;
|
||||||
|
import org.pgpainless.sop.EncryptImpl;
|
||||||
|
import org.pgpainless.sop.GenerateKeyImpl;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import sop.exception.SOPGPException;
|
import sop.exception.SOPGPException;
|
||||||
|
|
||||||
|
@ -647,7 +649,7 @@ public class RoundTripEncryptDecryptCmdTest extends CLITest {
|
||||||
// Generate key
|
// Generate key
|
||||||
File passwordFile = writeFile("password", "sw0rdf1sh");
|
File passwordFile = writeFile("password", "sw0rdf1sh");
|
||||||
File keyFile = pipeStdoutToFile("key.asc");
|
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");
|
File certFile = pipeStdoutToFile("cert.asc");
|
||||||
pipeFileToStdin(keyFile);
|
pipeFileToStdin(keyFile);
|
||||||
|
@ -659,7 +661,7 @@ public class RoundTripEncryptDecryptCmdTest extends CLITest {
|
||||||
// Encrypt
|
// Encrypt
|
||||||
File ciphertextFile = pipeStdoutToFile("msg.asc");
|
File ciphertextFile = pipeStdoutToFile("msg.asc");
|
||||||
pipeFileToStdin(plaintextFile);
|
pipeFileToStdin(plaintextFile);
|
||||||
assertSuccess(executeCommand("encrypt", "--profile=rfc4880", certFile.getAbsolutePath()));
|
assertSuccess(executeCommand("encrypt", "--profile=" + EncryptImpl.RFC4880_PROFILE.getName(), certFile.getAbsolutePath()));
|
||||||
|
|
||||||
ByteArrayOutputStream decrypted = pipeStdoutToStream();
|
ByteArrayOutputStream decrypted = pipeStdoutToStream();
|
||||||
pipeFileToStdin(ciphertextFile);
|
pipeFileToStdin(ciphertextFile);
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.pgpainless.bouncycastle.extensions.encode
|
||||||
import org.pgpainless.key.generation.KeyRingBuilder
|
import org.pgpainless.key.generation.KeyRingBuilder
|
||||||
import org.pgpainless.key.generation.KeySpec
|
import org.pgpainless.key.generation.KeySpec
|
||||||
import org.pgpainless.key.generation.type.KeyType
|
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.eddsa_legacy.EdDSALegacyCurve
|
||||||
import org.pgpainless.key.generation.type.rsa.RsaLength
|
import org.pgpainless.key.generation.type.rsa.RsaLength
|
||||||
import org.pgpainless.key.generation.type.xdh_legacy.XDHLegacySpec
|
import org.pgpainless.key.generation.type.xdh_legacy.XDHLegacySpec
|
||||||
|
@ -34,17 +35,24 @@ class GenerateKeyImpl(private val api: PGPainless) : GenerateKey {
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField
|
||||||
val CURVE25519_PROFILE =
|
val CURVE25519_PROFILE =
|
||||||
Profile(
|
Profile("draft-koch-eddsa-for-openpgp-00", "OpenPGP v4 keys over Curve25519")
|
||||||
"draft-koch-eddsa-for-openpgp-00", "Generate EdDSA / ECDH keys using Curve25519")
|
@JvmField
|
||||||
@JvmField val RSA4096_PROFILE = Profile("rfc4880", "Generate 4096-bit RSA keys")
|
val RFC4880_RSA4096_PROFILE = Profile("rfc4880-rsa4096", "OpenPGP v4 keys with RSA 4096")
|
||||||
@JvmField val RFC9580_PROFILE = Profile("rfc9580", "Generate OpenPGP v6 keys")
|
@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
|
@JvmField
|
||||||
val SUPPORTED_PROFILES =
|
val SUPPORTED_PROFILES =
|
||||||
listOf(
|
listOf(
|
||||||
CURVE25519_PROFILE.withAliases("default", "compatibility"),
|
CURVE25519_PROFILE.withAliases("default", "compatibility"),
|
||||||
RSA4096_PROFILE,
|
RFC4880_RSA4096_PROFILE,
|
||||||
RFC9580_PROFILE.withAliases("performance", "security"))
|
RFC9580_CURVE25519_PROFILE.withAliases("performance", "security"))
|
||||||
}
|
}
|
||||||
|
|
||||||
private val userIds = mutableSetOf<String>()
|
private val userIds = mutableSetOf<String>()
|
||||||
|
@ -116,7 +124,7 @@ class GenerateKeyImpl(private val api: PGPainless) : GenerateKey {
|
||||||
KeyFlag.ENCRYPT_STORAGE))
|
KeyFlag.ENCRYPT_STORAGE))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RSA4096_PROFILE.name -> {
|
RFC4880_RSA4096_PROFILE.name -> {
|
||||||
api.buildKey(OpenPGPKeyVersion.v4)
|
api.buildKey(OpenPGPKeyVersion.v4)
|
||||||
.setPrimaryKey(
|
.setPrimaryKey(
|
||||||
KeySpec.getBuilder(KeyType.RSA(RsaLength._4096), KeyFlag.CERTIFY_OTHER))
|
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)
|
api.buildKey(OpenPGPKeyVersion.v6)
|
||||||
.setPrimaryKey(KeySpec.getBuilder(KeyType.Ed25519(), KeyFlag.CERTIFY_OTHER))
|
.setPrimaryKey(KeySpec.getBuilder(KeyType.Ed25519(), KeyFlag.CERTIFY_OTHER))
|
||||||
.addSubkey(KeySpec.getBuilder(KeyType.Ed25519(), KeyFlag.SIGN_DATA))
|
.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)
|
else -> throw SOPGPException.UnsupportedProfile("generate-key", profile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -568,7 +568,7 @@ public class EncryptDecryptRoundTripTest {
|
||||||
public void encryptWithSupportedProfileTest() throws IOException {
|
public void encryptWithSupportedProfileTest() throws IOException {
|
||||||
|
|
||||||
byte[] key = sop.generateKey()
|
byte[] key = sop.generateKey()
|
||||||
.profile("rfc4880")
|
.profile(GenerateKeyImpl.RFC4880_RSA4096_PROFILE.getName())
|
||||||
.userId("Alice <alice@pgpainless.org>")
|
.userId("Alice <alice@pgpainless.org>")
|
||||||
.generate()
|
.generate()
|
||||||
.getBytes();
|
.getBytes();
|
||||||
|
@ -578,7 +578,7 @@ public class EncryptDecryptRoundTripTest {
|
||||||
.getBytes();
|
.getBytes();
|
||||||
|
|
||||||
byte[] encrypted = sop.encrypt()
|
byte[] encrypted = sop.encrypt()
|
||||||
.profile("rfc4880")
|
.profile(EncryptImpl.RFC4880_PROFILE.getName())
|
||||||
.withCert(cert)
|
.withCert(cert)
|
||||||
.plaintext(message)
|
.plaintext(message)
|
||||||
.toByteArrayAndResult()
|
.toByteArrayAndResult()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue