package org.bouncycastle.jce.provider.test; import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves; import org.bouncycastle.asn1.nist.NISTNamedCurves; import org.bouncycastle.asn1.sec.SECNamedCurves; import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves; import org.bouncycastle.asn1.x9.X962NamedCurves; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.spec.ECNamedCurveSpec; import org.bouncycastle.util.test.SimpleTest; import javax.crypto.KeyAgreement; import java.math.BigInteger; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Security; import java.security.Signature; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.ECGenParameterSpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Enumeration; import java.util.Hashtable; import java.util.Set; import java.util.HashSet; public class NamedCurveTest extends SimpleTest { private static Hashtable CURVE_NAMES = new Hashtable(); private static Hashtable CURVE_ALIASES = new Hashtable(); static { CURVE_NAMES.put("prime192v1", "prime192v1"); // X9.62 CURVE_NAMES.put("sect571r1", "sect571r1"); // sec CURVE_NAMES.put("secp224r1", "secp224r1"); CURVE_NAMES.put("B-409", SECNamedCurves.getName(NISTNamedCurves.getOID("B-409"))); // nist CURVE_NAMES.put("P-521", SECNamedCurves.getName(NISTNamedCurves.getOID("P-521"))); CURVE_NAMES.put("brainpoolp160r1", "brainpoolp160r1"); // TeleTrusT CURVE_ALIASES.put("secp192r1", "prime192v1"); CURVE_ALIASES.put("secp256r1", "prime256v1"); } public void testCurve( String name) throws Exception { ECGenParameterSpec ecSpec = new ECGenParameterSpec(name); KeyPairGenerator g = KeyPairGenerator.getInstance("ECDH", "BC"); g.initialize(ecSpec, new SecureRandom()); // // a side // KeyPair aKeyPair = g.generateKeyPair(); KeyAgreement aKeyAgree = KeyAgreement.getInstance("ECDHC", "BC"); aKeyAgree.init(aKeyPair.getPrivate()); // // b side // KeyPair bKeyPair = g.generateKeyPair(); KeyAgreement bKeyAgree = KeyAgreement.getInstance("ECDHC", "BC"); bKeyAgree.init(bKeyPair.getPrivate()); // // agreement // aKeyAgree.doPhase(bKeyPair.getPublic(), true); bKeyAgree.doPhase(aKeyPair.getPublic(), true); BigInteger k1 = new BigInteger(aKeyAgree.generateSecret()); BigInteger k2 = new BigInteger(bKeyAgree.generateSecret()); if (!k1.equals(k2)) { fail("2-way test failed"); } // // public key encoding test // byte[] pubEnc = aKeyPair.getPublic().getEncoded(); KeyFactory keyFac = KeyFactory.getInstance("ECDH", "BC"); X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc); ECPublicKey pubKey = (ECPublicKey)keyFac.generatePublic(pubX509); if (!pubKey.getW().equals(((ECPublicKey)aKeyPair.getPublic()).getW())) { fail("public key encoding (Q test) failed"); } if (!(pubKey.getParams() instanceof ECNamedCurveSpec)) { fail("public key encoding not named curve"); } // // private key encoding test // byte[] privEnc = aKeyPair.getPrivate().getEncoded(); PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc); ECPrivateKey privKey = (ECPrivateKey)keyFac.generatePrivate(privPKCS8); if (!privKey.getS().equals(((ECPrivateKey)aKeyPair.getPrivate()).getS())) { fail("private key encoding (S test) failed"); } if (!(privKey.getParams() instanceof ECNamedCurveSpec)) { fail("private key encoding not named curve"); } ECNamedCurveSpec privSpec = (ECNamedCurveSpec)privKey.getParams(); if (!(privSpec.getName().equals(name) || privSpec.getName().equals(CURVE_NAMES.get(name)))) { fail("private key encoding wrong named curve. Expected: " + CURVE_NAMES.get(name) + " got " + privSpec.getName()); } } public void testECDSA( String name) throws Exception { ECGenParameterSpec ecSpec = new ECGenParameterSpec(name); KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC"); g.initialize(ecSpec, new SecureRandom()); Signature sgr = Signature.getInstance("ECDSA", "BC"); KeyPair pair = g.generateKeyPair(); PrivateKey sKey = pair.getPrivate(); PublicKey vKey = pair.getPublic(); sgr.initSign(sKey); byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; sgr.update(message); byte[] sigBytes = sgr.sign(); sgr.initVerify(vKey); sgr.update(message); if (!sgr.verify(sigBytes)) { fail(name + " verification failed"); } // // public key encoding test // byte[] pubEnc = vKey.getEncoded(); KeyFactory keyFac = KeyFactory.getInstance("ECDH", "BC"); X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc); ECPublicKey pubKey = (ECPublicKey)keyFac.generatePublic(pubX509); if (!pubKey.getW().equals(((ECPublicKey)vKey).getW())) { fail("public key encoding (Q test) failed"); } if (!(pubKey.getParams() instanceof ECNamedCurveSpec)) { fail("public key encoding not named curve"); } // // private key encoding test // byte[] privEnc = sKey.getEncoded(); PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc); ECPrivateKey privKey = (ECPrivateKey)keyFac.generatePrivate(privPKCS8); if (!privKey.getS().equals(((ECPrivateKey)sKey).getS())) { fail("private key encoding (S test) failed"); } if (!(privKey.getParams() instanceof ECNamedCurveSpec)) { fail("private key encoding not named curve"); } ECNamedCurveSpec privSpec = (ECNamedCurveSpec)privKey.getParams(); if (!privSpec.getName().equalsIgnoreCase(name) && !privSpec.getName().equalsIgnoreCase((String)CURVE_ALIASES.get(name))) { fail("private key encoding wrong named curve. Expected: " + name + " got " + privSpec.getName()); } } public void testECGOST( String name) throws Exception { ECGenParameterSpec ecSpec = new ECGenParameterSpec(name); KeyPairGenerator g = KeyPairGenerator.getInstance("ECGOST3410", "BC"); g.initialize(ecSpec, new SecureRandom()); Signature sgr = Signature.getInstance("ECGOST3410", "BC"); KeyPair pair = g.generateKeyPair(); PrivateKey sKey = pair.getPrivate(); PublicKey vKey = pair.getPublic(); sgr.initSign(sKey); byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; sgr.update(message); byte[] sigBytes = sgr.sign(); sgr.initVerify(vKey); sgr.update(message); if (!sgr.verify(sigBytes)) { fail(name + " verification failed"); } // // public key encoding test // byte[] pubEnc = vKey.getEncoded(); KeyFactory keyFac = KeyFactory.getInstance("ECGOST3410", "BC"); X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc); ECPublicKey pubKey = (ECPublicKey)keyFac.generatePublic(pubX509); if (!pubKey.getW().equals(((ECPublicKey)vKey).getW())) { fail("public key encoding (Q test) failed"); } if (!(pubKey.getParams() instanceof ECNamedCurveSpec)) { fail("public key encoding not named curve"); } // // private key encoding test // byte[] privEnc = sKey.getEncoded(); PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc); ECPrivateKey privKey = (ECPrivateKey)keyFac.generatePrivate(privPKCS8); if (!privKey.getS().equals(((ECPrivateKey)sKey).getS())) { fail("GOST private key encoding (S test) failed"); } if (!(privKey.getParams() instanceof ECNamedCurveSpec)) { fail("GOST private key encoding not named curve"); } ECNamedCurveSpec privSpec = (ECNamedCurveSpec)privKey.getParams(); if (!privSpec.getName().equalsIgnoreCase(name) && !privSpec.getName().equalsIgnoreCase((String)CURVE_ALIASES.get(name))) { fail("GOST private key encoding wrong named curve. Expected: " + name + " got " + privSpec.getName()); } } public String getName() { return "NamedCurve"; } public void performTest() throws Exception { testCurve("prime192v1"); // X9.62 testCurve("sect571r1"); // sec testCurve("secp224r1"); testCurve("B-409"); // nist testCurve("P-521"); testCurve("brainpoolp160r1"); // TeleTrusT for (Enumeration en = X962NamedCurves.getNames(); en.hasMoreElements();) { testECDSA((String)en.nextElement()); } // these curves can't be used under JDK 1.5 Set problemCurves = new HashSet(); problemCurves.add("secp256k1"); problemCurves.add("secp160k1"); problemCurves.add("secp224k1"); problemCurves.add("secp192k1"); for (Enumeration en = SECNamedCurves.getNames(); en.hasMoreElements();) { String curveName = (String)en.nextElement(); if (!problemCurves.contains(curveName)) { testECDSA(curveName); } } for (Enumeration en = TeleTrusTNamedCurves.getNames(); en.hasMoreElements();) { testECDSA((String)en.nextElement()); } for (Enumeration en = ECGOST3410NamedCurves.getNames(); en.hasMoreElements();) { testECGOST((String)en.nextElement()); } } public static void main( String[] args) { Security.addProvider(new BouncyCastleProvider()); runTest(new NamedCurveTest()); } }