| 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.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; |
| // BEGIN android-changed |
| int strength = 256; |
| // BEGIN android-changed |
| int certainty = 50; |
| SecureRandom random = new SecureRandom(); |
| 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; |
| // BEGIN android-added |
| if (random != null) { |
| // END android-added |
| this.random = random; |
| // BEGIN android-added |
| } |
| // END android-added |
| |
| 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 |
| { |
| // BEGIN android-added |
| if (random == null) { |
| random = this.random; |
| } |
| // END android-added |
| 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); |
| } |
| } |
| } |