diff options
Diffstat (limited to 'prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java')
-rw-r--r-- | prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java new file mode 100644 index 00000000..bd24d1aa --- /dev/null +++ b/prov/src/main/java/org/spongycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java @@ -0,0 +1,270 @@ +package org.spongycastle.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 org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.x9.ECNamedCurveTable; +import org.spongycastle.asn1.x9.X9ECParameters; +import org.spongycastle.crypto.AsymmetricCipherKeyPair; +import org.spongycastle.crypto.generators.ECKeyPairGenerator; +import org.spongycastle.crypto.params.ECDomainParameters; +import org.spongycastle.crypto.params.ECKeyGenerationParameters; +import org.spongycastle.crypto.params.ECPrivateKeyParameters; +import org.spongycastle.crypto.params.ECPublicKeyParameters; +import org.spongycastle.jcajce.provider.asymmetric.util.EC5Util; +import org.spongycastle.jcajce.provider.config.ProviderConfiguration; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.jce.spec.ECNamedCurveGenParameterSpec; +import org.spongycastle.jce.spec.ECNamedCurveSpec; +import org.spongycastle.jce.spec.ECParameterSpec; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECPoint; +import org.spongycastle.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; + 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; + 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()), 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 = ECNamedCurveTable.getByName(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) + { + 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); + } + } +}
\ No newline at end of file |