diff options
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec')
4 files changed, 212 insertions, 170 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java index 0eaae1d..ac0ddf5 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/BCECPublicKey.java @@ -34,6 +34,8 @@ import org.bouncycastle.jce.interfaces.ECPointEncoder; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.math.ec.ECCurve; +import org.bouncycastle.math.ec.custom.sec.SecP256K1Point; +import org.bouncycastle.math.ec.custom.sec.SecP256R1Point; public class BCECPublicKey implements ECPublicKey, org.bouncycastle.jce.interfaces.ECPublicKey, ECPointEncoder @@ -82,6 +84,8 @@ public class BCECPublicKey ECCurve curve = spec.getParams().getCurve(); EllipticCurve ellipticCurve = EC5Util.convertCurve(curve, spec.getParams().getSeed()); + // this may seem a little long-winded but it's how we pick up the custom curve. + this.q = EC5Util.convertCurve(ellipticCurve).createPoint(spec.getQ().getAffineXCoord().toBigInteger(), spec.getQ().getAffineYCoord().toBigInteger()); this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec.getParams()); } else @@ -132,7 +136,6 @@ public class BCECPublicKey ECDomainParameters dp = params.getParameters(); this.algorithm = algorithm; - this.q = params.getQ(); if (spec == null) { @@ -147,6 +150,8 @@ public class BCECPublicKey this.ecSpec = EC5Util.convertSpec(ellipticCurve, spec); } + this.q = EC5Util.convertCurve(ecSpec.getCurve()).createPoint(params.getQ().getAffineXCoord().toBigInteger(), params.getQ().getAffineYCoord().toBigInteger()); + this.configuration = configuration; } @@ -369,14 +374,7 @@ public class BCECPublicKey { if (ecSpec == null) { - if (q instanceof org.bouncycastle.math.ec.ECPoint.Fp) - { - return new org.bouncycastle.math.ec.ECPoint.Fp(null, q.getAffineXCoord(), q.getAffineYCoord()); - } - else - { - return new org.bouncycastle.math.ec.ECPoint.F2m(null, q.getAffineXCoord(), q.getAffineYCoord()); - } + return q.getDetachedPoint(); } return q; diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java index ea36dfd..3dbe004 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyAgreementSpi.java @@ -17,6 +17,7 @@ import javax.crypto.spec.SecretKeySpec; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; +import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x9.X9IntegerConverter; import org.bouncycastle.crypto.BasicAgreement; @@ -30,6 +31,7 @@ import org.bouncycastle.crypto.agreement.ECDHBasicAgreement; // import org.bouncycastle.crypto.agreement.kdf.ECDHKEKGenerator; // END android-removed import org.bouncycastle.crypto.digests.SHA1Digest; +import org.bouncycastle.crypto.params.DESParameters; import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; @@ -45,6 +47,7 @@ import org.bouncycastle.jce.interfaces.ECPublicKey; // import org.bouncycastle.jce.interfaces.MQVPublicKey; // END android-removed import org.bouncycastle.util.Integers; +import org.bouncycastle.util.Strings; /** * Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363 @@ -57,9 +60,12 @@ public class KeyAgreementSpi { private static final X9IntegerConverter converter = new X9IntegerConverter(); private static final Hashtable algorithms = new Hashtable(); + private static final Hashtable oids = new Hashtable(); + private static final Hashtable des = new Hashtable(); static { + Integer i64 = Integers.valueOf(64); Integer i128 = Integers.valueOf(128); Integer i192 = Integers.valueOf(192); Integer i256 = Integers.valueOf(256); @@ -71,6 +77,18 @@ public class KeyAgreementSpi algorithms.put(NISTObjectIdentifiers.id_aes192_wrap.getId(), i192); algorithms.put(NISTObjectIdentifiers.id_aes256_wrap.getId(), i256); algorithms.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), i192); + algorithms.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), i192); + algorithms.put(OIWObjectIdentifiers.desCBC.getId(), i64); + + oids.put("DESEDE", PKCSObjectIdentifiers.des_EDE3_CBC); + oids.put("AES", NISTObjectIdentifiers.id_aes256_CBC); + oids.put("DES", OIWObjectIdentifiers.desCBC); + + des.put("DES", "DES"); + des.put("DESEDE", "DES"); + des.put(OIWObjectIdentifiers.desCBC.getId(), "DES"); + des.put(PKCSObjectIdentifiers.des_EDE3_CBC.getId(), "DES"); + des.put(PKCSObjectIdentifiers.id_alg_CMS3DESwrap.getId(), "DES"); } private String kaAlgorithm; @@ -84,7 +102,7 @@ public class KeyAgreementSpi private byte[] bigIntToBytes( BigInteger r) { - return converter.integerToBytes(r, converter.getByteLength(parameters.getG().getAffineXCoord())); + return converter.integerToBytes(r, converter.getByteLength(parameters.getCurve())); } protected KeyAgreementSpi( @@ -189,18 +207,25 @@ public class KeyAgreementSpi throws NoSuchAlgorithmException { byte[] secret = bigIntToBytes(result); + String algKey = Strings.toUpperCase(algorithm); + String oidAlgorithm = algorithm; + + if (oids.containsKey(algKey)) + { + oidAlgorithm = ((ASN1ObjectIdentifier)oids.get(algKey)).getId(); + } // BEGIN android-removed // if (kdf != null) // { - // if (!algorithms.containsKey(algorithm)) + // if (!algorithms.containsKey(oidAlgorithm)) // { // throw new NoSuchAlgorithmException("unknown algorithm encountered: " + algorithm); // } // - // int keySize = ((Integer)algorithms.get(algorithm)).intValue(); + // int keySize = ((Integer)algorithms.get(oidAlgorithm)).intValue(); // - // DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(algorithm), keySize, secret); + // DHKDFParameters params = new DHKDFParameters(new ASN1ObjectIdentifier(oidAlgorithm), keySize, secret); // // byte[] keyBytes = new byte[keySize / 8]; // kdf.init(params); @@ -210,7 +235,21 @@ public class KeyAgreementSpi // else // END android-removed { - // TODO Should we be ensuring the key is the right length? + if (algorithms.containsKey(oidAlgorithm)) + { + Integer length = (Integer)algorithms.get(oidAlgorithm); + + byte[] key = new byte[length.intValue() / 8]; + + System.arraycopy(secret, 0, key, 0, key.length); + + secret = key; + } + } + + if (des.containsKey(oidAlgorithm)) + { + DESParameters.setOddParity(secret); } return new SecretKeySpec(secret, algorithm); @@ -222,12 +261,11 @@ public class KeyAgreementSpi SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { - // BEGIN android-added if (params != null) { throw new InvalidAlgorithmParameterException("No algorithm parameters supported"); } - // END android-added + initFromKey(key); } diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java index 42bb895..1239609 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/KeyPairGeneratorSpi.java @@ -91,22 +91,20 @@ public abstract class KeyPairGeneratorSpi // BEGIN android-added } // END android-added + ECGenParameterSpec ecParams = (ECGenParameterSpec)ecParameters.get(Integers.valueOf(strength)); + if (ecParams == null) + { + throw new InvalidParameterException("unknown key size."); + } - if (ecParams != null) + try { - try - { - initialize(ecParams, random); - } - catch (InvalidAlgorithmParameterException e) - { - throw new InvalidParameterException("key size not configurable."); - } + initialize(ecParams, random); } - else + catch (InvalidAlgorithmParameterException e) { - throw new InvalidParameterException("unknown key size."); + throw new InvalidParameterException("key size not configurable."); } } @@ -120,97 +118,42 @@ public abstract class KeyPairGeneratorSpi random = this.random; } // END android-added - if (params instanceof ECParameterSpec) + if (params == null) { - ECParameterSpec p = (ECParameterSpec)params; - this.ecParams = params; - - param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random); + ECParameterSpec implicitCA = configuration.getEcImplicitlyCa(); + if (implicitCA == null) + { + throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set"); + } - engine.init(param); - initialised = true; + this.ecParams = null; + this.param = createKeyGenParamsBC(implicitCA, random); } - else if (params instanceof java.security.spec.ECParameterSpec) + else if (params instanceof 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; + this.param = createKeyGenParamsBC((ECParameterSpec)params, random); } - else if (params instanceof ECGenParameterSpec || params instanceof ECNamedCurveGenParameterSpec) + else if (params instanceof java.security.spec.ECParameterSpec) { - String curveName; - - if (params instanceof ECGenParameterSpec) - { - curveName = ((ECGenParameterSpec)params).getName(); - } - else - { - curveName = ((ECNamedCurveGenParameterSpec)params).getName(); - } - - X9ECParameters ecP = ECNamedCurveTable.getByName(curveName); - if (ecP == null) - { - // See if it's actually an OID string (SunJSSE ServerHandshaker setupEphemeralECDHKeys bug) - try - { - ASN1ObjectIdentifier oid = new ASN1ObjectIdentifier(curveName); - ecP = ECNamedCurveTable.getByOID(oid); - 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; + this.ecParams = params; + this.param = createKeyGenParamsJCE((java.security.spec.ECParameterSpec)params, random); } - else if (params == null && configuration.getEcImplicitlyCa() != null) + else if (params instanceof ECGenParameterSpec) { - ECParameterSpec p = configuration.getEcImplicitlyCa(); - this.ecParams = params; - - param = new ECKeyGenerationParameters(new ECDomainParameters(p.getCurve(), p.getG(), p.getN()), random); - - engine.init(param); - initialised = true; + initializeNamedCurve(((ECGenParameterSpec)params).getName(), random); } - else if (params == null && configuration.getEcImplicitlyCa() == null) + else if (params instanceof ECNamedCurveGenParameterSpec) { - throw new InvalidAlgorithmParameterException("null parameter passed but no implicitCA set"); + initializeNamedCurve(((ECNamedCurveGenParameterSpec)params).getName(), random); } else { throw new InvalidAlgorithmParameterException("parameter object not a ECParameterSpec"); } + + engine.init(param); + initialised = true; } public KeyPair generateKeyPair() @@ -246,6 +189,58 @@ public abstract class KeyPairGeneratorSpi 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 @@ -283,4 +278,4 @@ public abstract class KeyPairGeneratorSpi super("ECMQV", BouncyCastleProvider.CONFIGURATION); } } -}
\ No newline at end of file +} diff --git a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java index 3757229..26811d1 100644 --- a/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java +++ b/bcprov/src/main/java/org/bouncycastle/jcajce/provider/asymmetric/ec/SignatureSpi.java @@ -249,7 +249,7 @@ public class SignatureSpi // { // public ecCVCDSA() // { - // super(new SHA1Digest(), new ECDSASigner(), new CVCDSAEncoder()); + // super(new SHA1Digest(), new ECDSASigner(), new PlainDSAEncoder()); // } // } // @@ -258,7 +258,7 @@ public class SignatureSpi // { // public ecCVCDSA224() // { - // super(new SHA224Digest(), new ECDSASigner(), new CVCDSAEncoder()); + // super(new SHA224Digest(), new ECDSASigner(), new PlainDSAEncoder()); // } // } // @@ -267,7 +267,7 @@ public class SignatureSpi // { // public ecCVCDSA256() // { - // super(new SHA256Digest(), new ECDSASigner(), new CVCDSAEncoder()); + // super(new SHA256Digest(), new ECDSASigner(), new PlainDSAEncoder()); // } // } // @@ -276,7 +276,7 @@ public class SignatureSpi // { // public ecCVCDSA384() // { - // super(new SHA384Digest(), new ECDSASigner(), new CVCDSAEncoder()); + // super(new SHA384Digest(), new ECDSASigner(), new PlainDSAEncoder()); // } // } // @@ -285,7 +285,16 @@ public class SignatureSpi // { // public ecCVCDSA512() // { - // super(new SHA512Digest(), new ECDSASigner(), new CVCDSAEncoder()); + // super(new SHA512Digest(), new ECDSASigner(), new PlainDSAEncoder()); + // } + // } + // + // static public class ecPlainDSARP160 + // extends SignatureSpi + // { + // public ecPlainDSARP160() + // { + // super(new RIPEMD160Digest(), new ECDSASigner(), new PlainDSAEncoder()); // } // } // END android-removed @@ -320,66 +329,68 @@ public class SignatureSpi } } - private static class CVCDSAEncoder - implements DSAEncoder - { - public byte[] encode( - BigInteger r, - BigInteger s) - throws IOException - { - byte[] first = makeUnsigned(r); - byte[] second = makeUnsigned(s); - byte[] res; - - if (first.length > second.length) - { - res = new byte[first.length * 2]; - } - else - { - res = new byte[second.length * 2]; - } - - System.arraycopy(first, 0, res, res.length / 2 - first.length, first.length); - System.arraycopy(second, 0, res, res.length - second.length, second.length); - - return res; - } - - - private byte[] makeUnsigned(BigInteger val) - { - byte[] res = val.toByteArray(); - - if (res[0] == 0) - { - byte[] tmp = new byte[res.length - 1]; - - System.arraycopy(res, 1, tmp, 0, tmp.length); - - return tmp; - } - - return res; - } - - public BigInteger[] decode( - byte[] encoding) - throws IOException - { - BigInteger[] sig = new BigInteger[2]; - - byte[] first = new byte[encoding.length / 2]; - byte[] second = new byte[encoding.length / 2]; - - System.arraycopy(encoding, 0, first, 0, first.length); - System.arraycopy(encoding, first.length, second, 0, second.length); - - sig[0] = new BigInteger(1, first); - sig[1] = new BigInteger(1, second); - - return sig; - } - } + // BEGIN android-removed + // private static class PlainDSAEncoder + // implements DSAEncoder + // { + // public byte[] encode( + // BigInteger r, + // BigInteger s) + // throws IOException + // { + // byte[] first = makeUnsigned(r); + // byte[] second = makeUnsigned(s); + // byte[] res; + // + // if (first.length > second.length) + // { + // res = new byte[first.length * 2]; + // } + // else + // { + // res = new byte[second.length * 2]; + // } + // + // System.arraycopy(first, 0, res, res.length / 2 - first.length, first.length); + // System.arraycopy(second, 0, res, res.length - second.length, second.length); + // + // return res; + // } + // + // + // private byte[] makeUnsigned(BigInteger val) + // { + // byte[] res = val.toByteArray(); + // + // if (res[0] == 0) + // { + // byte[] tmp = new byte[res.length - 1]; + // + // System.arraycopy(res, 1, tmp, 0, tmp.length); + // + // return tmp; + // } + // + // return res; + // } + // + // public BigInteger[] decode( + // byte[] encoding) + // throws IOException + // { + // BigInteger[] sig = new BigInteger[2]; + // + // byte[] first = new byte[encoding.length / 2]; + // byte[] second = new byte[encoding.length / 2]; + // + // System.arraycopy(encoding, 0, first, 0, first.length); + // System.arraycopy(encoding, first.length, second, 0, second.length); + // + // sig[0] = new BigInteger(1, first); + // sig[1] = new BigInteger(1, second); + // + // return sig; + // } + // } + // END android-removed } |