blob: 72fcca93e06f06c722f78a36d7f434d21d825676 [file] [log] [blame]
package org.bouncycastle.jcajce.provider.asymmetric.ec;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidParameterException;
import java.security.KeyPair;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.util.Hashtable;
import java.util.Map;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.spec.ECNamedCurveGenParameterSpec;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.Integers;
public abstract class KeyPairGeneratorSpi
extends java.security.KeyPairGenerator
{
public KeyPairGeneratorSpi(String algorithmName)
{
super(algorithmName);
}
public static class EC
extends KeyPairGeneratorSpi
{
ECKeyGenerationParameters param;
ECKeyPairGenerator engine = new ECKeyPairGenerator();
Object ecParams = null;
int strength = 239;
SecureRandom random = CryptoServicesRegistrar.getSecureRandom();
boolean initialised = false;
String algorithm;
ProviderConfiguration configuration;
static private Hashtable ecParameters;
static {
ecParameters = new Hashtable();
ecParameters.put(Integers.valueOf(192), new ECGenParameterSpec("prime192v1")); // a.k.a P-192
ecParameters.put(Integers.valueOf(239), new ECGenParameterSpec("prime239v1"));
ecParameters.put(Integers.valueOf(256), new ECGenParameterSpec("prime256v1")); // a.k.a P-256
ecParameters.put(Integers.valueOf(224), new ECGenParameterSpec("P-224"));
ecParameters.put(Integers.valueOf(384), new ECGenParameterSpec("P-384"));
ecParameters.put(Integers.valueOf(521), new ECGenParameterSpec("P-521"));
}
public EC()
{
super("EC");
this.algorithm = "EC";
this.configuration = BouncyCastleProvider.CONFIGURATION;
}
public EC(
String algorithm,
ProviderConfiguration configuration)
{
super(algorithm);
this.algorithm = algorithm;
this.configuration = configuration;
}
public void initialize(
int strength,
SecureRandom random)
{
this.strength = strength;
this.random = random;
ECGenParameterSpec ecParams = (ECGenParameterSpec)ecParameters.get(Integers.valueOf(strength));
if (ecParams == null)
{
throw new InvalidParameterException("unknown key size.");
}
try
{
initialize(ecParams, random);
}
catch (InvalidAlgorithmParameterException e)
{
throw new InvalidParameterException("key size not configurable.");
}
}
public void initialize(
AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidAlgorithmParameterException
{
if (params == null)
{
ECParameterSpec implicitCA = configuration.getEcImplicitlyCa();
if (implicitCA == null)
{
throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set");
}
this.ecParams = null;
this.param = createKeyGenParamsBC(implicitCA, random);
}
else if (params instanceof ECParameterSpec)
{
this.ecParams = params;
this.param = createKeyGenParamsBC((ECParameterSpec)params, random);
}
else if (params instanceof java.security.spec.ECParameterSpec)
{
this.ecParams = params;
this.param = createKeyGenParamsJCE((java.security.spec.ECParameterSpec)params, random);
}
else if (params instanceof ECGenParameterSpec)
{
initializeNamedCurve(((ECGenParameterSpec)params).getName(), random);
}
else if (params instanceof ECNamedCurveGenParameterSpec)
{
initializeNamedCurve(((ECNamedCurveGenParameterSpec)params).getName(), random);
}
else
{
throw new InvalidAlgorithmParameterException("parameter object not a ECParameterSpec");
}
engine.init(param);
initialised = true;
}
public KeyPair generateKeyPair()
{
if (!initialised)
{
initialize(strength, new SecureRandom());
}
AsymmetricCipherKeyPair pair = engine.generateKeyPair();
ECPublicKeyParameters pub = (ECPublicKeyParameters)pair.getPublic();
ECPrivateKeyParameters priv = (ECPrivateKeyParameters)pair.getPrivate();
if (ecParams instanceof ECParameterSpec)
{
ECParameterSpec p = (ECParameterSpec)ecParams;
BCECPublicKey pubKey = new BCECPublicKey(algorithm, pub, p, configuration);
return new KeyPair(pubKey,
new BCECPrivateKey(algorithm, priv, pubKey, p, configuration));
}
else if (ecParams == null)
{
return new KeyPair(new BCECPublicKey(algorithm, pub, configuration),
new BCECPrivateKey(algorithm, priv, configuration));
}
else
{
java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams;
BCECPublicKey pubKey = new BCECPublicKey(algorithm, pub, p, configuration);
return new KeyPair(pubKey, new BCECPrivateKey(algorithm, priv, pubKey, p, configuration));
}
}
protected ECKeyGenerationParameters createKeyGenParamsBC(ECParameterSpec p, SecureRandom r)
{
return new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN(), p.getH()), r);
}
protected ECKeyGenerationParameters createKeyGenParamsJCE(java.security.spec.ECParameterSpec p, SecureRandom r)
{
ECCurve curve = EC5Util.convertCurve(p.getCurve());
ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false);
BigInteger n = p.getOrder();
BigInteger h = BigInteger.valueOf(p.getCofactor());
ECDomainParameters dp = new ECDomainParameters(curve, g, n, h);
return new ECKeyGenerationParameters(dp, r);
}
protected ECNamedCurveSpec createNamedCurveSpec(String curveName)
throws InvalidAlgorithmParameterException
{
// NOTE: Don't bother with custom curves here as the curve will be converted to JCE type shortly
X9ECParameters p = ECUtils.getDomainParametersFromName(curveName);
if (p == null)
{
try
{
// Check whether it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug)
p = ECNamedCurveTable.getByOID(new ASN1ObjectIdentifier(curveName));
if (p == null)
{
Map extraCurves = configuration.getAdditionalECParameters();
p = (X9ECParameters)extraCurves.get(new ASN1ObjectIdentifier(curveName));
if (p == null)
{
throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName);
}
}
}
catch (IllegalArgumentException ex)
{
throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
}
}
// Work-around for JDK bug -- it won't look up named curves properly if seed is present
byte[] seed = null; //p.getSeed();
return new ECNamedCurveSpec(curveName, p.getCurve(), p.getG(), p.getN(), p.getH(), seed);
}
protected void initializeNamedCurve(String curveName, SecureRandom random)
throws InvalidAlgorithmParameterException
{
ECNamedCurveSpec namedCurve = createNamedCurveSpec(curveName);
this.ecParams = namedCurve;
this.param = createKeyGenParamsJCE(namedCurve, random);
}
}
public static class ECDSA
extends EC
{
public ECDSA()
{
super("ECDSA", BouncyCastleProvider.CONFIGURATION);
}
}
public static class ECDH
extends EC
{
public ECDH()
{
super("ECDH", BouncyCastleProvider.CONFIGURATION);
}
}
public static class ECDHC
extends EC
{
public ECDHC()
{
super("ECDHC", BouncyCastleProvider.CONFIGURATION);
}
}
public static class ECMQV
extends EC
{
public ECMQV()
{
super("ECMQV", BouncyCastleProvider.CONFIGURATION);
}
}
}