Skip to content

Commit

Permalink
PGPKeyPairGenerator: Implement generation of NIST ECDH and ECDSA keys
Browse files Browse the repository at this point in the history
  • Loading branch information
vanitasvitae committed Jan 28, 2025
1 parent 965def5 commit 3c6cf05
Show file tree
Hide file tree
Showing 4 changed files with 421 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.bouncycastle.openpgp.operator;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.sec.SECObjectIdentifiers;
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPKeyPair;
Expand Down Expand Up @@ -178,4 +180,114 @@ public abstract PGPKeyPair generateLegacyEd25519KeyPair()
*/
public abstract PGPKeyPair generateLegacyX25519KeyPair()
throws PGPException;

/**
* Generate an ECDH elliptic curve encryption key over the NIST p-256 curve.
*
* @return NIST p-256 ECDSA encryption key pair
* @throws PGPException if the key pair cannot be generated
*
* @see <a href="https://www.rfc-editor.org/rfc/rfc6637.html">
* RFC6637 - Elliptic Curve Cryptography in OpenPGP</a>
*/
public PGPKeyPair generateNistP256ECDHKeyPair()
throws PGPException
{
return generateECDHKeyPair(SECObjectIdentifiers.secp256r1);
}

/**
* Generate an ECDH elliptic curve encryption key over the NIST p-384 curve.
*
* @return NIST p-384 ECDSA encryption key pair
* @throws PGPException if the key pair cannot be generated
*
* @see <a href="https://www.rfc-editor.org/rfc/rfc6637.html">
* RFC6637 - Elliptic Curve Cryptography in OpenPGP</a>
*/
public PGPKeyPair generateNistP384ECDHKeyPair()
throws PGPException
{
return generateECDHKeyPair(SECObjectIdentifiers.secp384r1);
}

/**
* Generate an ECDH elliptic curve encryption key over the NIST p-521 curve.
*
* @return NIST p-521 ECDSA encryption key pair
* @throws PGPException if the key pair cannot be generated
*
* @see <a href="https://www.rfc-editor.org/rfc/rfc6637.html">
* RFC6637 - Elliptic Curve Cryptography in OpenPGP</a>
*/
public PGPKeyPair generateNistP521ECDHKeyPair()
throws PGPException
{
return generateECDHKeyPair(SECObjectIdentifiers.secp521r1);
}

/**
* Generate an ECDSA elliptic curve signing key over the NIST p-256 curve.
*
* @return NIST p-256 ECDSA signing key pair
* @throws PGPException if the key pair cannot be generated
*
* @see <a href="https://www.rfc-editor.org/rfc/rfc6637.html">
* RFC6637 - Elliptic Curve Cryptography in OpenPGP</a>
*/
public PGPKeyPair generateNistP256ECDSAKeyPair()
throws PGPException
{
return generateECDSAKeyPair(SECObjectIdentifiers.secp256r1);
}

/**
* Generate an ECDSA elliptic curve signing key over the NIST p-384 curve.
*
* @return NIST p-384 ECDSA signing key pair
* @throws PGPException if the key pair cannot be generated
*
* @see <a href="https://www.rfc-editor.org/rfc/rfc6637.html">
* RFC6637 - Elliptic Curve Cryptography in OpenPGP</a>
*/
public PGPKeyPair generateNistP384ECDSAKeyPair()
throws PGPException
{
return generateECDSAKeyPair(SECObjectIdentifiers.secp384r1);
}

/**
* Generate an ECDSA elliptic curve signing key over the NIST p-521 curve.
*
* @return NIST p-521 ECDSA signing key pair
* @throws PGPException if the key pair cannot be generated
*
* @see <a href="https://www.rfc-editor.org/rfc/rfc6637.html">
* RFC6637 - Elliptic Curve Cryptography in OpenPGP</a>
*/
public PGPKeyPair generateNistP521ECDSAKeyPair()
throws PGPException
{
return generateECDSAKeyPair(SECObjectIdentifiers.secp521r1);
}

/**
* Generate an elliptic curve Diffie-Hellman encryption key pair over the curve identified by the given OID.
*
* @param curveOID OID of the elliptic curve
* @return PGP key pair
* @throws PGPException if the key pair cannot be generated
*/
public abstract PGPKeyPair generateECDHKeyPair(ASN1ObjectIdentifier curveOID)
throws PGPException;

/**
* Generate an elliptic curve signing key over the curve identified by the given OID.
*
* @param curveOID OID of the elliptic curve
* @return PGP key pair
* @throws PGPException if the key pair cannot be generated
*/
public abstract PGPKeyPair generateECDSAKeyPair(ASN1ObjectIdentifier curveOID)
throws PGPException;
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
package org.bouncycastle.openpgp.operator.bc;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
import org.bouncycastle.bcpg.PublicKeyPacket;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.generators.Ed25519KeyPairGenerator;
import org.bouncycastle.crypto.generators.Ed448KeyPairGenerator;
import org.bouncycastle.crypto.generators.RSAKeyPairGenerator;
import org.bouncycastle.crypto.generators.X25519KeyPairGenerator;
import org.bouncycastle.crypto.generators.X448KeyPairGenerator;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECNamedDomainParameters;
import org.bouncycastle.crypto.params.Ed25519KeyGenerationParameters;
import org.bouncycastle.crypto.params.Ed448KeyGenerationParameters;
import org.bouncycastle.crypto.params.RSAKeyGenerationParameters;
import org.bouncycastle.crypto.params.X25519KeyGenerationParameters;
import org.bouncycastle.crypto.params.X448KeyGenerationParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.operator.PGPKeyPairGenerator;
Expand All @@ -24,7 +29,7 @@
import java.util.Date;

public class BcPGPKeyPairGeneratorProvider
extends PGPKeyPairGeneratorProvider
extends PGPKeyPairGeneratorProvider
{
private SecureRandom random = CryptoServicesRegistrar.getSecureRandom();

Expand Down Expand Up @@ -128,5 +133,31 @@ public PGPKeyPair generateLegacyX25519KeyPair()
AsymmetricCipherKeyPair keyPair = gen.generateKeyPair();
return new BcPGPKeyPair(version, PublicKeyAlgorithmTags.ECDH, keyPair, creationTime);
}

@Override
public PGPKeyPair generateECDHKeyPair(ASN1ObjectIdentifier curveOID)
throws PGPException
{
ECKeyPairGenerator gen = new ECKeyPairGenerator();
gen.init(new ECKeyGenerationParameters(
new ECNamedDomainParameters(curveOID, ECUtil.getNamedCurveByOid(curveOID)),
CryptoServicesRegistrar.getSecureRandom()));

AsymmetricCipherKeyPair keyPair = gen.generateKeyPair();
return new BcPGPKeyPair(version, PublicKeyAlgorithmTags.ECDH, keyPair, creationTime);
}

@Override
public PGPKeyPair generateECDSAKeyPair(ASN1ObjectIdentifier curveOID)
throws PGPException
{
ECKeyPairGenerator gen = new ECKeyPairGenerator();
gen.init(new ECKeyGenerationParameters(
new ECNamedDomainParameters(curveOID, ECUtil.getNamedCurveByOid(curveOID)),
CryptoServicesRegistrar.getSecureRandom()));

AsymmetricCipherKeyPair keyPair = gen.generateKeyPair();
return new BcPGPKeyPair(version, PublicKeyAlgorithmTags.ECDSA, keyPair, creationTime);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package org.bouncycastle.openpgp.operator.jcajce;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.bcpg.PublicKeyAlgorithmTags;
import org.bouncycastle.bcpg.PublicKeyPacket;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jcajce.spec.EdDSAParameterSpec;
import org.bouncycastle.jcajce.spec.XDHParameterSpec;
import org.bouncycastle.jcajce.util.DefaultJcaJceHelper;
import org.bouncycastle.jcajce.util.NamedJcaJceHelper;
import org.bouncycastle.jcajce.util.ProviderJcaJceHelper;
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.operator.PGPKeyPairGenerator;
Expand Down Expand Up @@ -212,5 +215,41 @@ public PGPKeyPair generateLegacyX25519KeyPair()
throw new PGPException("Cannot generate LegacyX25519 key pair.", e);
}
}

@Override
public PGPKeyPair generateECDHKeyPair(ASN1ObjectIdentifier curveOID)
throws PGPException
{
try
{
KeyPairGenerator gen = helper.createKeyPairGenerator("ECDH");
String curveName = ECUtil.getCurveName(curveOID);
gen.initialize(new ECNamedCurveGenParameterSpec(curveName));
KeyPair keyPair = gen.generateKeyPair();
return new JcaPGPKeyPair(version, PublicKeyAlgorithmTags.ECDH, keyPair, creationTime);
}
catch (GeneralSecurityException e)
{
throw new PGPException("Cannot generate ECDH key pair.", e);
}
}

@Override
public PGPKeyPair generateECDSAKeyPair(ASN1ObjectIdentifier curveOID)
throws PGPException
{
try
{
KeyPairGenerator gen = helper.createKeyPairGenerator("ECDSA");
String curveName = ECUtil.getCurveName(curveOID);
gen.initialize(new ECNamedCurveGenParameterSpec(curveName));
KeyPair keyPair = gen.generateKeyPair();
return new JcaPGPKeyPair(version, PublicKeyAlgorithmTags.ECDSA, keyPair, creationTime);
}
catch (GeneralSecurityException e)
{
throw new PGPException("Cannot generate ECDSA key pair.", e);
}
}
}
}
Loading

0 comments on commit 3c6cf05

Please sign in to comment.