blob: ab104ed8c80b186580c9160a1fa7512d23e70bad [file] [log] [blame]
package org.bouncycastle.jce.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 org.bouncycastle.asn1.DERObjectIdentifier;
// BEGIN android-removed
// import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
// END android-removed
import org.bouncycastle.asn1.nist.NISTNamedCurves;
import org.bouncycastle.asn1.sec.SECNamedCurves;
// BEGIN android-removed
// import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
// END android-removed
import org.bouncycastle.asn1.x9.X962NamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
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.jce.provider.JCEECPrivateKey;
import org.bouncycastle.jce.provider.JCEECPublicKey;
import org.bouncycastle.jce.provider.JDKKeyPairGenerator;
import org.bouncycastle.jce.provider.ProviderUtil;
import org.bouncycastle.jce.spec.ECNamedCurveSpec;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
public abstract class KeyPairGenerator
extends JDKKeyPairGenerator
{
public KeyPairGenerator(String algorithmName)
{
super(algorithmName);
}
public static class EC
extends KeyPairGenerator
{
ECKeyGenerationParameters param;
ECKeyPairGenerator engine = new ECKeyPairGenerator();
Object ecParams = null;
int strength = 239;
int certainty = 50;
SecureRandom random = new SecureRandom();
boolean initialised = false;
String algorithm;
static private Hashtable ecParameters;
static {
ecParameters = new Hashtable();
// BEGIN android-changed
ecParameters.put(Integer.valueOf(192), new ECGenParameterSpec("prime192v1")); // a.k.a P-192
ecParameters.put(Integer.valueOf(239), new ECGenParameterSpec("prime239v1"));
ecParameters.put(Integer.valueOf(256), new ECGenParameterSpec("prime256v1")); // a.k.a P-256
ecParameters.put(Integer.valueOf(224), new ECGenParameterSpec("P-224"));
ecParameters.put(Integer.valueOf(384), new ECGenParameterSpec("P-384"));
ecParameters.put(Integer.valueOf(521), new ECGenParameterSpec("P-521"));
// END android-changed
}
public EC()
{
super("EC");
this.algorithm = "EC";
}
public EC(
String algorithm)
{
super(algorithm);
this.algorithm = algorithm;
}
public void initialize(
int strength,
SecureRandom random)
{
this.strength = strength;
// BEGIN android-added
if (random != null) {
// END android-added
this.random = random;
// BEGIN android-added
}
// END android-added
// BEGIN android-changed
this.ecParams = ecParameters.get(Integer.valueOf(strength));
// END android-changed
if (ecParams != null)
{
try
{
initialize((ECGenParameterSpec)ecParams, random);
}
catch (InvalidAlgorithmParameterException e)
{
throw new InvalidParameterException("key size not configurable.");
}
}
else
{
throw new InvalidParameterException("unknown key size.");
}
}
public void initialize(
AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidAlgorithmParameterException
{
// BEGIN android-added
if (random == null) {
random = this.random;
}
// END android-added
if (params instanceof ECParameterSpec)
{
ECParameterSpec p = (ECParameterSpec)params;
this.ecParams = params;
param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random);
engine.init(param);
initialised = true;
}
else if (params instanceof java.security.spec.ECParameterSpec)
{
java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)params;
this.ecParams = params;
ECCurve curve = EC5Util.convertCurve(p.getCurve());
ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false);
param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random);
engine.init(param);
initialised = true;
}
else if (params instanceof ECGenParameterSpec)
{
final String curveName = ((ECGenParameterSpec)params).getName();
// BEGIN android-removed
// if (this.algorithm.equals("ECGOST3410"))
// {
// ECDomainParameters ecP = ECGOST3410NamedCurves.getByName(curveName);
// if (ecP == null)
// {
// throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
// }
//
// this.ecParams = new ECNamedCurveSpec(
// curveName,
// ecP.getCurve(),
// ecP.getG(),
// ecP.getN(),
// ecP.getH(),
// ecP.getSeed());
// }
// else
// END android-removed
{
X9ECParameters ecP = X962NamedCurves.getByName(curveName);
if (ecP == null)
{
ecP = SECNamedCurves.getByName(curveName);
if (ecP == null)
{
ecP = NISTNamedCurves.getByName(curveName);
}
// BEGIN android-removed
// if (ecP == null)
// {
// ecP = TeleTrusTNamedCurves.getByName(curveName);
// }
// END android-removed
if (ecP == null)
{
// See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug)
try
{
DERObjectIdentifier oid = new DERObjectIdentifier(curveName);
ecP = X962NamedCurves.getByOID(oid);
if (ecP == null)
{
ecP = SECNamedCurves.getByOID(oid);
}
if (ecP == null)
{
ecP = NISTNamedCurves.getByOID(oid);
}
// BEGIN android-removed
// if (ecP == null)
// {
// ecP = TeleTrusTNamedCurves.getByOID(oid);
// }
// END android-removed
if (ecP == null)
{
throw new InvalidAlgorithmParameterException("unknown curve OID: " + curveName);
}
}
catch (IllegalArgumentException ex)
{
throw new InvalidAlgorithmParameterException("unknown curve name: " + curveName);
}
}
}
this.ecParams = new ECNamedCurveSpec(
curveName,
ecP.getCurve(),
ecP.getG(),
ecP.getN(),
ecP.getH(),
null); // ecP.getSeed()); Work-around JDK bug -- it won't look up named curves properly if seed is present
}
java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams;
ECCurve curve = EC5Util.convertCurve(p.getCurve());
ECPoint g = EC5Util.convertPoint(curve, p.getGenerator(), false);
param = new ECKeyGenerationParameters(new ECDomainParameters(curve, g, p.getOrder(), BigInteger.valueOf(p.getCofactor())), random);
engine.init(param);
initialised = true;
}
else if (params == null && ProviderUtil.getEcImplicitlyCa() != null)
{
ECParameterSpec p = ProviderUtil.getEcImplicitlyCa();
this.ecParams = params;
param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random);
engine.init(param);
initialised = true;
}
else if (params == null && ProviderUtil.getEcImplicitlyCa() == null)
{
throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set");
}
else
{
throw new InvalidAlgorithmParameterException("parameter object not a ECParameterSpec");
}
}
public KeyPair generateKeyPair()
{
if (!initialised)
{
// BEGIN android-removed
// throw new IllegalStateException("EC Key Pair Generator not initialised");
// END android-removed
// BEGIN android-added
/*
* KeyPairGenerator documentation says that a default initialization must be provided
*/
initialize(192, random);
// END android-added
}
AsymmetricCipherKeyPair pair = engine.generateKeyPair();
ECPublicKeyParameters pub = (ECPublicKeyParameters)pair.getPublic();
ECPrivateKeyParameters priv = (ECPrivateKeyParameters)pair.getPrivate();
if (ecParams instanceof ECParameterSpec)
{
ECParameterSpec p = (ECParameterSpec)ecParams;
JCEECPublicKey pubKey = new JCEECPublicKey(algorithm, pub, p);
return new KeyPair(pubKey,
new JCEECPrivateKey(algorithm, priv, pubKey, p));
}
else if (ecParams == null)
{
return new KeyPair(new JCEECPublicKey(algorithm, pub),
new JCEECPrivateKey(algorithm, priv));
}
else
{
java.security.spec.ECParameterSpec p = (java.security.spec.ECParameterSpec)ecParams;
JCEECPublicKey pubKey = new JCEECPublicKey(algorithm, pub, p);
return new KeyPair(pubKey, new JCEECPrivateKey(algorithm, priv, pubKey, p));
}
}
}
public static class ECDSA
extends EC
{
public ECDSA()
{
super("ECDSA");
}
}
// BEGIN android-removed
// public static class ECGOST3410
// extends EC
// {
// public ECGOST3410()
// {
// super("ECGOST3410");
// }
// }
// END android-removed
public static class ECDH
extends EC
{
public ECDH()
{
super("ECDH");
}
}
public static class ECDHC
extends EC
{
public ECDHC()
{
super("ECDHC");
}
}
public static class ECMQV
extends EC
{
public ECMQV()
{
super("ECMQV");
}
}
}