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

Adapt PGPKeyPairGenerator and remove support for generating ElGamal keys

This commit is contained in:
Paul Schaub 2025-01-28 21:20:56 +01:00
parent 87f3d28567
commit 1acda0e970
Signed by: vanitasvitae
GPG key ID: 62BEE9264BF17311
10 changed files with 43 additions and 124 deletions

View file

@ -5,9 +5,10 @@
package org.pgpainless.key.generation
import java.io.IOException
import java.security.KeyPairGenerator
import java.util.*
import org.bouncycastle.bcpg.PublicKeyPacket
import org.bouncycastle.openpgp.*
import org.bouncycastle.openpgp.api.OpenPGPImplementation
import org.bouncycastle.openpgp.operator.PBESecretKeyDecryptor
import org.bouncycastle.openpgp.operator.PBESecretKeyEncryptor
import org.bouncycastle.openpgp.operator.PGPContentSignerBuilder
@ -19,7 +20,6 @@ import org.pgpainless.algorithm.SignatureType
import org.pgpainless.bouncycastle.extensions.unlock
import org.pgpainless.implementation.ImplementationFactory
import org.pgpainless.policy.Policy
import org.pgpainless.provider.ProviderFactory
import org.pgpainless.signature.subpackets.SelfSignatureSubpackets
import org.pgpainless.signature.subpackets.SignatureSubpackets
import org.pgpainless.signature.subpackets.SignatureSubpacketsHelper
@ -252,17 +252,12 @@ class KeyRingBuilder : KeyRingBuilderInterface<KeyRingBuilder> {
spec: KeySpec,
creationTime: Date = spec.keyCreationDate ?: Date()
): PGPKeyPair {
spec.keyType.let { type ->
// Create raw Key Pair
val keyPair =
KeyPairGenerator.getInstance(type.name, ProviderFactory.provider)
.also { it.initialize(type.algorithmSpec) }
.generateKeyPair()
val gen =
OpenPGPImplementation.getInstance()
.pgpKeyPairGeneratorProvider()
.get(PublicKeyPacket.VERSION_4, creationTime)
// Form PGP Key Pair
return ImplementationFactory.getInstance()
.getPGPKeyPair(type.algorithm, keyPair, creationTime)
}
return spec.keyType.generateKeyPair(gen)
}
}
}

View file

@ -5,6 +5,8 @@
package org.pgpainless.key.generation.type
import java.security.spec.AlgorithmParameterSpec
import org.bouncycastle.openpgp.PGPKeyPair
import org.bouncycastle.openpgp.operator.PGPKeyPairGenerator
import org.pgpainless.algorithm.PublicKeyAlgorithm
import org.pgpainless.key.generation.type.ecc.EllipticCurve
import org.pgpainless.key.generation.type.ecc.ecdh.ECDH
@ -92,6 +94,8 @@ interface KeyType {
val canEncryptStorage: Boolean
@JvmName("canEncryptStorage") get() = algorithm.encryptionCapable
fun generateKeyPair(generator: PGPKeyPairGenerator): PGPKeyPair
companion object {
@JvmStatic fun RSA(length: RsaLength): RSA = RSA.withLength(length)

View file

@ -4,7 +4,10 @@
package org.pgpainless.key.generation.type.ecc.ecdh
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec
import org.bouncycastle.openpgp.PGPKeyPair
import org.bouncycastle.openpgp.operator.PGPKeyPairGenerator
import org.pgpainless.algorithm.PublicKeyAlgorithm
import org.pgpainless.key.generation.type.KeyType
import org.pgpainless.key.generation.type.ecc.EllipticCurve
@ -15,6 +18,10 @@ class ECDH private constructor(val curve: EllipticCurve) : KeyType {
override val bitStrength = curve.bitStrength
override val algorithmSpec = ECNamedCurveGenParameterSpec(curve.curveName)
override fun generateKeyPair(generator: PGPKeyPairGenerator): PGPKeyPair {
return ECUtil.getNamedCurveOid(curve.curveName).let { generator.generateECDHKeyPair(it) }
}
companion object {
@JvmStatic fun fromCurve(curve: EllipticCurve) = ECDH(curve)
}

View file

@ -4,7 +4,10 @@
package org.pgpainless.key.generation.type.ecc.ecdsa
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec
import org.bouncycastle.openpgp.PGPKeyPair
import org.bouncycastle.openpgp.operator.PGPKeyPairGenerator
import org.pgpainless.algorithm.PublicKeyAlgorithm
import org.pgpainless.key.generation.type.KeyType
import org.pgpainless.key.generation.type.ecc.EllipticCurve
@ -15,6 +18,10 @@ class ECDSA private constructor(val curve: EllipticCurve) : KeyType {
override val bitStrength = curve.bitStrength
override val algorithmSpec = ECNamedCurveGenParameterSpec(curve.curveName)
override fun generateKeyPair(generator: PGPKeyPairGenerator): PGPKeyPair {
return ECUtil.getNamedCurveOid(curve.curveName).let { generator.generateECDSAKeyPair(it) }
}
companion object {
@JvmStatic fun fromCurve(curve: EllipticCurve) = ECDSA(curve)
}

View file

@ -5,6 +5,8 @@
package org.pgpainless.key.generation.type.eddsa_legacy
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec
import org.bouncycastle.openpgp.PGPKeyPair
import org.bouncycastle.openpgp.operator.PGPKeyPairGenerator
import org.pgpainless.algorithm.PublicKeyAlgorithm
import org.pgpainless.key.generation.type.KeyType
@ -14,6 +16,10 @@ class EdDSALegacy private constructor(val curve: EdDSALegacyCurve) : KeyType {
override val bitStrength = curve.bitStrength
override val algorithmSpec = ECNamedCurveGenParameterSpec(curve.curveName)
override fun generateKeyPair(generator: PGPKeyPairGenerator): PGPKeyPair {
return generator.generateLegacyEd25519KeyPair()
}
companion object {
@JvmStatic fun fromCurve(curve: EdDSALegacyCurve) = EdDSALegacy(curve)
}

View file

@ -1,27 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.key.generation.type.elgamal
import org.bouncycastle.jce.spec.ElGamalParameterSpec
import org.pgpainless.algorithm.PublicKeyAlgorithm
import org.pgpainless.key.generation.type.KeyType
/**
* ElGamal encryption only key type.
*
* @deprecated the use of ElGamal is not recommended anymore.
*/
@Deprecated("The use of ElGamal is not recommended anymore.")
class ElGamal private constructor(length: ElGamalLength) : KeyType {
override val name = "ElGamal"
override val algorithm = PublicKeyAlgorithm.ELGAMAL_ENCRYPT
override val bitStrength = length.length
override val algorithmSpec = ElGamalParameterSpec(length.p, length.g)
companion object {
@JvmStatic fun withLength(length: ElGamalLength) = ElGamal(length)
}
}

View file

@ -1,63 +0,0 @@
// SPDX-FileCopyrightText: 2023 Paul Schaub <vanitasvitae@fsfe.org>
//
// SPDX-License-Identifier: Apache-2.0
package org.pgpainless.key.generation.type.elgamal
import java.math.BigInteger
import org.pgpainless.key.generation.type.KeyLength
/**
* The following primes are taken from RFC-3526.
*
* @see <a href="https://www.ietf.org/rfc/rfc3526.txt"> RFC-3526: More Modular Exponential (MODP)
* Diffie-Hellman groups for Internet Key Exchange (IKE)</a>
* @deprecated the use of ElGamal keys is no longer recommended.
*/
@Deprecated("The use of ElGamal keys is no longer recommended.")
enum class ElGamalLength(override val length: Int, p: String, g: String) : KeyLength {
/** prime: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }. generator: 2 */
_1536(
1536,
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
"2"),
/** prime: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }. generator: 2 */
_2048(
2048,
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF",
"2"),
/** prime: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 }. generator: 2 */
_3072(
3072,
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",
"2"),
/** prime: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }. generator: 2 */
_4096(
4096,
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF",
"2"),
/** prime: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 }. generator: 2 */
_6144(
6144,
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF",
"2"),
/** prime: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 }. generator: 2 */
_8192(
8192,
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF",
"2");
val p: BigInteger
val g: BigInteger
init {
this.p = BigInteger(p, 16)
this.g = BigInteger(g, 16)
}
}

View file

@ -5,6 +5,8 @@
package org.pgpainless.key.generation.type.rsa
import java.security.spec.RSAKeyGenParameterSpec
import org.bouncycastle.openpgp.PGPKeyPair
import org.bouncycastle.openpgp.operator.PGPKeyPairGenerator
import org.pgpainless.algorithm.PublicKeyAlgorithm
import org.pgpainless.key.generation.type.KeyType
@ -16,6 +18,10 @@ class RSA private constructor(length: RsaLength) : KeyType {
override val bitStrength = length.length
override val algorithmSpec = RSAKeyGenParameterSpec(length.length, RSAKeyGenParameterSpec.F4)
override fun generateKeyPair(generator: PGPKeyPairGenerator): PGPKeyPair {
return generator.generateRsaKeyPair(bitStrength)
}
companion object {
@JvmStatic fun withLength(length: RsaLength) = RSA(length)
}

View file

@ -5,6 +5,8 @@
package org.pgpainless.key.generation.type.xdh_legacy
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec
import org.bouncycastle.openpgp.PGPKeyPair
import org.bouncycastle.openpgp.operator.PGPKeyPairGenerator
import org.pgpainless.algorithm.PublicKeyAlgorithm
import org.pgpainless.key.generation.type.KeyType
@ -14,6 +16,10 @@ class XDHLegacy private constructor(spec: XDHLegacySpec) : KeyType {
override val bitStrength = spec.bitStrength
override val algorithmSpec = ECNamedCurveGenParameterSpec(spec.algorithmName)
override fun generateKeyPair(generator: PGPKeyPairGenerator): PGPKeyPair {
return generator.generateLegacyX25519KeyPair()
}
companion object {
@JvmStatic fun fromSpec(spec: XDHLegacySpec) = XDHLegacy(spec)
}

View file

@ -29,7 +29,6 @@ import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
import org.pgpainless.PGPainless;
import org.pgpainless.algorithm.DocumentSignatureType;
import org.pgpainless.algorithm.KeyFlag;
import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
import org.pgpainless.decryption_verification.ConsumerOptions;
import org.pgpainless.decryption_verification.DecryptionStream;
@ -37,10 +36,6 @@ import org.pgpainless.decryption_verification.MessageMetadata;
import org.pgpainless.exception.KeyException;
import org.pgpainless.key.SubkeyIdentifier;
import org.pgpainless.key.TestKeys;
import org.pgpainless.key.generation.KeySpec;
import org.pgpainless.key.generation.type.KeyType;
import org.pgpainless.key.generation.type.elgamal.ElGamal;
import org.pgpainless.key.generation.type.elgamal.ElGamalLength;
import org.pgpainless.key.generation.type.rsa.RsaLength;
import org.pgpainless.key.protection.SecretKeyRingProtector;
import org.pgpainless.key.protection.UnprotectedKeysProtector;
@ -71,23 +66,6 @@ public class EncryptDecryptTest {
Policy.SymmetricKeyAlgorithmPolicy.symmetricKeyDecryptionPolicy2022());
}
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void freshKeysRsaToElGamalTest()
throws PGPException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, IOException {
PGPSecretKeyRing sender = PGPainless.generateKeyRing().simpleRsaKeyRing("romeo@montague.lit", RsaLength._3072);
PGPSecretKeyRing recipient = PGPainless.buildKeyRing()
.setPrimaryKey(KeySpec.getBuilder(
KeyType.RSA(RsaLength._4096),
KeyFlag.SIGN_DATA, KeyFlag.CERTIFY_OTHER))
.addSubkey(KeySpec.getBuilder(
ElGamal.withLength(ElGamalLength._3072),
KeyFlag.ENCRYPT_STORAGE, KeyFlag.ENCRYPT_COMMS))
.addUserId("juliet@capulet.lit").build();
encryptDecryptForSecretKeyRings(sender, recipient);
}
@TestTemplate
@ExtendWith(TestAllImplementations.class)
public void freshKeysRsaToRsaTest()