diff options
Diffstat (limited to 'libraries/spongycastle/prov/src/test/java/org/spongycastle/jce/provider/test/DSATest.java')
-rw-r--r-- | libraries/spongycastle/prov/src/test/java/org/spongycastle/jce/provider/test/DSATest.java | 1016 |
1 files changed, 1016 insertions, 0 deletions
diff --git a/libraries/spongycastle/prov/src/test/java/org/spongycastle/jce/provider/test/DSATest.java b/libraries/spongycastle/prov/src/test/java/org/spongycastle/jce/provider/test/DSATest.java new file mode 100644 index 000000000..83e2fe99c --- /dev/null +++ b/libraries/spongycastle/prov/src/test/java/org/spongycastle/jce/provider/test/DSATest.java @@ -0,0 +1,1016 @@ +package org.spongycastle.jce.provider.test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.math.BigInteger; +import java.security.AlgorithmParameterGenerator; +import java.security.AlgorithmParameters; +import java.security.InvalidKeyException; +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.SignatureException; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.spec.DSAParameterSpec; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import org.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.ASN1Primitive; +import org.spongycastle.asn1.ASN1Sequence; +import org.spongycastle.asn1.DERInteger; +import org.spongycastle.asn1.DERObjectIdentifier; +import org.spongycastle.asn1.eac.EACObjectIdentifiers; +import org.spongycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; +import org.spongycastle.asn1.x9.X9ObjectIdentifiers; +import org.spongycastle.crypto.params.DSAParameters; +import org.spongycastle.crypto.params.DSAPublicKeyParameters; +import org.spongycastle.crypto.signers.DSASigner; +import org.spongycastle.jce.interfaces.PKCS12BagAttributeCarrier; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.jce.spec.ECNamedCurveGenParameterSpec; +import org.spongycastle.jce.spec.ECParameterSpec; +import org.spongycastle.jce.spec.ECPrivateKeySpec; +import org.spongycastle.jce.spec.ECPublicKeySpec; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.util.Arrays; +import org.spongycastle.util.BigIntegers; +import org.spongycastle.util.encoders.Hex; +import org.spongycastle.util.test.FixedSecureRandom; +import org.spongycastle.util.test.SimpleTest; + +public class DSATest + extends SimpleTest +{ + byte[] k1 = Hex.decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3"); + byte[] k2 = Hex.decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded"); + + SecureRandom random = new FixedSecureRandom(new byte[][] { k1, k2 }); + + private void testCompat() + throws Exception + { + if (Security.getProvider("SUN") == null) + { + return; + } + + Signature s = Signature.getInstance("DSA", "SUN"); + KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "SUN"); + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + g.initialize(512, new SecureRandom()); + + KeyPair p = g.generateKeyPair(); + + PrivateKey sKey = p.getPrivate(); + PublicKey vKey = p.getPublic(); + + // + // sign SUN - verify with BC + // + s.initSign(sKey); + + s.update(data); + + byte[] sigBytes = s.sign(); + + s = Signature.getInstance("DSA", "SC"); + + s.initVerify(vKey); + + s.update(data); + + if (!s.verify(sigBytes)) + { + fail("SUN -> BC verification failed"); + } + + // + // sign BC - verify with SUN + // + + s.initSign(sKey); + + s.update(data); + + sigBytes = s.sign(); + + s = Signature.getInstance("DSA", "SUN"); + + s.initVerify(vKey); + + s.update(data); + + if (!s.verify(sigBytes)) + { + fail("BC -> SUN verification failed"); + } + + // + // key encoding test - BC decoding Sun keys + // + KeyFactory f = KeyFactory.getInstance("DSA", "SC"); + X509EncodedKeySpec x509s = new X509EncodedKeySpec(vKey.getEncoded()); + + DSAPublicKey k1 = (DSAPublicKey)f.generatePublic(x509s); + + checkPublic(k1, vKey); + + PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(sKey.getEncoded()); + + DSAPrivateKey k2 = (DSAPrivateKey)f.generatePrivate(pkcs8); + + checkPrivateKey(k2, sKey); + + // + // key decoding test - SUN decoding BC keys + // + f = KeyFactory.getInstance("DSA", "SUN"); + x509s = new X509EncodedKeySpec(k1.getEncoded()); + + vKey = (DSAPublicKey)f.generatePublic(x509s); + + checkPublic(k1, vKey); + + pkcs8 = new PKCS8EncodedKeySpec(k2.getEncoded()); + sKey = f.generatePrivate(pkcs8); + + checkPrivateKey(k2, sKey); + } + + private void testNONEwithDSA() + throws Exception + { + byte[] dummySha1 = Hex.decode("01020304050607080910111213141516"); + + KeyPairGenerator kpGen = KeyPairGenerator.getInstance("DSA", "SC"); + + kpGen.initialize(512); + + KeyPair kp = kpGen.generateKeyPair(); + + Signature sig = Signature.getInstance("NONEwithDSA", "SC"); + + sig.initSign(kp.getPrivate()); + + sig.update(dummySha1); + + byte[] sigBytes = sig.sign(); + + sig.initVerify(kp.getPublic()); + + sig.update(dummySha1); + + sig.verify(sigBytes); + + // reset test + + sig.update(dummySha1); + + if (!sig.verify(sigBytes)) + { + fail("NONEwithDSA failed to reset"); + } + + // lightweight test + DSAPublicKey key = (DSAPublicKey)kp.getPublic(); + DSAParameters params = new DSAParameters(key.getParams().getP(), key.getParams().getQ(), key.getParams().getG()); + DSAPublicKeyParameters keyParams = new DSAPublicKeyParameters(key.getY(), params); + DSASigner signer = new DSASigner(); + ASN1Sequence derSig = ASN1Sequence.getInstance(ASN1Primitive.fromByteArray(sigBytes)); + + signer.init(false, keyParams); + + if (!signer.verifySignature(dummySha1, DERInteger.getInstance(derSig.getObjectAt(0)).getValue(), DERInteger.getInstance(derSig.getObjectAt(1)).getValue())) + { + fail("NONEwithDSA not really NONE!"); + } + } + + private void checkPublic(DSAPublicKey k1, PublicKey vKey) + { + if (!k1.getY().equals(((DSAPublicKey)vKey).getY())) + { + fail("public number not decoded properly"); + } + + if (!k1.getParams().getG().equals(((DSAPublicKey)vKey).getParams().getG())) + { + fail("public generator not decoded properly"); + } + + if (!k1.getParams().getP().equals(((DSAPublicKey)vKey).getParams().getP())) + { + fail("public p value not decoded properly"); + } + + if (!k1.getParams().getQ().equals(((DSAPublicKey)vKey).getParams().getQ())) + { + fail("public q value not decoded properly"); + } + } + + private void checkPrivateKey(DSAPrivateKey k2, PrivateKey sKey) + { + if (!k2.getX().equals(((DSAPrivateKey)sKey).getX())) + { + fail("private number not decoded properly"); + } + + if (!k2.getParams().getG().equals(((DSAPrivateKey)sKey).getParams().getG())) + { + fail("private generator not decoded properly"); + } + + if (!k2.getParams().getP().equals(((DSAPrivateKey)sKey).getParams().getP())) + { + fail("private p value not decoded properly"); + } + + if (!k2.getParams().getQ().equals(((DSAPrivateKey)sKey).getParams().getQ())) + { + fail("private q value not decoded properly"); + } + } + + private Object serializeDeserialize(Object o) + throws Exception + { + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ObjectOutputStream oOut = new ObjectOutputStream(bOut); + + oOut.writeObject(o); + oOut.close(); + + ObjectInputStream oIn = new ObjectInputStream(new ByteArrayInputStream(bOut.toByteArray())); + + return oIn.readObject(); + } + + /** + * X9.62 - 1998,<br> + * J.3.2, Page 155, ECDSA over the field Fp<br> + * an example with 239 bit prime + */ + private void testECDSA239bitPrime() + throws Exception + { + BigInteger r = new BigInteger("308636143175167811492622547300668018854959378758531778147462058306432176"); + BigInteger s = new BigInteger("323813553209797357708078776831250505931891051755007842781978505179448783"); + + byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655")); + + SecureRandom k = new FixedSecureRandom(kData); + + ECCurve curve = new ECCurve.Fp( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECParameterSpec spec = new ECParameterSpec( + curve, + curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + + ECPrivateKeySpec priKey = new ECPrivateKeySpec( + new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d + spec); + + ECPublicKeySpec pubKey = new ECPublicKeySpec( + curve.decodePoint(Hex.decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q + spec); + + Signature sgr = Signature.getInstance("ECDSA", "SC"); + KeyFactory f = KeyFactory.getInstance("ECDSA", "SC"); + PrivateKey sKey = f.generatePrivate(priKey); + PublicKey vKey = f.generatePublic(pubKey); + + sgr.initSign(sKey, k); + + 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("239 Bit EC verification failed"); + } + + BigInteger[] sig = derDecode(sigBytes); + + if (!r.equals(sig[0])) + { + fail("r component wrong." + System.getProperty("line.separator") + + " expecting: " + r + System.getProperty("line.separator") + + " got : " + sig[0]); + } + + if (!s.equals(sig[1])) + { + fail("s component wrong." + System.getProperty("line.separator") + + " expecting: " + s + System.getProperty("line.separator") + + " got : " + sig[1]); + } + } + + private void testNONEwithECDSA239bitPrime() + throws Exception + { + ECCurve curve = new ECCurve.Fp( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECParameterSpec spec = new ECParameterSpec( + curve, + curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + + ECPrivateKeySpec priKey = new ECPrivateKeySpec( + new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d + spec); + + ECPublicKeySpec pubKey = new ECPublicKeySpec( + curve.decodePoint(Hex.decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q + spec); + + Signature sgr = Signature.getInstance("NONEwithECDSA", "SC"); + KeyFactory f = KeyFactory.getInstance("ECDSA", "SC"); + PrivateKey sKey = f.generatePrivate(priKey); + PublicKey vKey = f.generatePublic(pubKey); + + byte[] message = "abc".getBytes(); + byte[] sig = Hex.decode("3040021e2cb7f36803ebb9c427c58d8265f11fc5084747133078fc279de874fbecb0021e64cb19604be06c57e761b3de5518f71de0f6e0cd2df677cec8a6ffcb690d"); + + checkMessage(sgr, sKey, vKey, message, sig); + + message = "abcdefghijklmnopqrstuvwxyz".getBytes(); + sig = Hex.decode("3040021e2cb7f36803ebb9c427c58d8265f11fc5084747133078fc279de874fbecb0021e43fd65b3363d76aabef8630572257dbb67c82818ad9fad31256539b1b02c"); + + checkMessage(sgr, sKey, vKey, message, sig); + + message = "a very very long message gauranteed to cause an overflow".getBytes(); + sig = Hex.decode("3040021e2cb7f36803ebb9c427c58d8265f11fc5084747133078fc279de874fbecb0021e7d5be84b22937a1691859a3c6fe45ed30b108574431d01b34025825ec17a"); + + checkMessage(sgr, sKey, vKey, message, sig); + } + + private void checkMessage(Signature sgr, PrivateKey sKey, PublicKey vKey, byte[] message, byte[] sig) + throws InvalidKeyException, SignatureException + { + byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655")); + + SecureRandom k = new FixedSecureRandom(kData); + + sgr.initSign(sKey, k); + + sgr.update(message); + + byte[] sigBytes = sgr.sign(); + + if (!Arrays.areEqual(sigBytes, sig)) + { + fail(new String(message) + " signature incorrect"); + } + + sgr.initVerify(vKey); + + sgr.update(message); + + if (!sgr.verify(sigBytes)) + { + fail(new String(message) + " verification failed"); + } + } + + /** + * X9.62 - 1998,<br> + * J.2.1, Page 100, ECDSA over the field F2m<br> + * an example with 191 bit binary field + */ + private void testECDSA239bitBinary() + throws Exception + { + BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552"); + BigInteger s = new BigInteger("197030374000731686738334997654997227052849804072198819102649413465737174"); + + byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363")); + + SecureRandom k = new FixedSecureRandom(kData); + + ECCurve curve = new ECCurve.F2m( + 239, // m + 36, // k + new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a + new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b + + ECParameterSpec params = new ECParameterSpec( + curve, + curve.decodePoint(Hex.decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G + new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n + BigInteger.valueOf(4)); // h + + ECPrivateKeySpec priKeySpec = new ECPrivateKeySpec( + new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d + params); + + ECPublicKeySpec pubKeySpec = new ECPublicKeySpec( + curve.decodePoint(Hex.decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q + params); + + Signature sgr = Signature.getInstance("ECDSA", "SC"); + KeyFactory f = KeyFactory.getInstance("ECDSA", "SC"); + PrivateKey sKey = f.generatePrivate(priKeySpec); + PublicKey vKey = f.generatePublic(pubKeySpec); + byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; + + sgr.initSign(sKey, k); + + sgr.update(message); + + byte[] sigBytes = sgr.sign(); + + sgr.initVerify(vKey); + + sgr.update(message); + + if (!sgr.verify(sigBytes)) + { + fail("239 Bit EC verification failed"); + } + + BigInteger[] sig = derDecode(sigBytes); + + if (!r.equals(sig[0])) + { + fail("r component wrong." + System.getProperty("line.separator") + + " expecting: " + r + System.getProperty("line.separator") + + " got : " + sig[0]); + } + + if (!s.equals(sig[1])) + { + fail("s component wrong." + System.getProperty("line.separator") + + " expecting: " + s + System.getProperty("line.separator") + + " got : " + sig[1]); + } + } + + private void testECDSA239bitBinary(String algorithm, DERObjectIdentifier oid) + throws Exception + { + byte[] kData = BigIntegers.asUnsignedByteArray(new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363")); + + SecureRandom k = new FixedSecureRandom(kData); + + ECCurve curve = new ECCurve.F2m( + 239, // m + 36, // k + new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a + new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b + + ECParameterSpec params = new ECParameterSpec( + curve, + curve.decodePoint(Hex.decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G + new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n + BigInteger.valueOf(4)); // h + + ECPrivateKeySpec priKeySpec = new ECPrivateKeySpec( + new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d + params); + + ECPublicKeySpec pubKeySpec = new ECPublicKeySpec( + curve.decodePoint(Hex.decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q + params); + + Signature sgr = Signature.getInstance(algorithm, "SC"); + KeyFactory f = KeyFactory.getInstance("ECDSA", "SC"); + PrivateKey sKey = f.generatePrivate(priKeySpec); + PublicKey vKey = f.generatePublic(pubKeySpec); + byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' }; + + sgr.initSign(sKey, k); + + sgr.update(message); + + byte[] sigBytes = sgr.sign(); + + sgr = Signature.getInstance(oid.getId(), "SC"); + + sgr.initVerify(vKey); + + sgr.update(message); + + if (!sgr.verify(sigBytes)) + { + fail("239 Bit EC RIPEMD160 verification failed"); + } + } + + private void testGeneration() + throws Exception + { + Signature s = Signature.getInstance("DSA", "SC"); + KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "SC"); + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + + // test exception + // + try + { + g.initialize(513, new SecureRandom()); + + fail("illegal parameter 513 check failed."); + } + catch (IllegalArgumentException e) + { + // expected + } + + try + { + g.initialize(510, new SecureRandom()); + + fail("illegal parameter 510 check failed."); + } + catch (IllegalArgumentException e) + { + // expected + } + + try + { + g.initialize(1025, new SecureRandom()); + + fail("illegal parameter 1025 check failed."); + } + catch (IllegalArgumentException e) + { + // expected + } + + g.initialize(512, new SecureRandom()); + + KeyPair p = g.generateKeyPair(); + + PrivateKey sKey = p.getPrivate(); + PublicKey vKey = p.getPublic(); + + s.initSign(sKey); + + s.update(data); + + byte[] sigBytes = s.sign(); + + s = Signature.getInstance("DSA", "SC"); + + s.initVerify(vKey); + + s.update(data); + + if (!s.verify(sigBytes)) + { + fail("DSA verification failed"); + } + + // + // key decoding test - serialisation test + // + + DSAPublicKey k1 = (DSAPublicKey)serializeDeserialize(vKey); + + checkPublic(k1, vKey); + + checkEquals(k1, vKey); + + DSAPrivateKey k2 = (DSAPrivateKey)serializeDeserialize(sKey); + + checkPrivateKey(k2, sKey); + + checkEquals(k2, sKey); + + if (!(k2 instanceof PKCS12BagAttributeCarrier)) + { + fail("private key not implementing PKCS12 attribute carrier"); + } + + // + // ECDSA Fp generation test + // + s = Signature.getInstance("ECDSA", "SC"); + g = KeyPairGenerator.getInstance("ECDSA", "SC"); + + ECCurve curve = new ECCurve.Fp( + new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q + new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a + new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b + + ECParameterSpec ecSpec = new ECParameterSpec( + curve, + curve.decodePoint(Hex.decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G + new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n + + g.initialize(ecSpec, new SecureRandom()); + + p = g.generateKeyPair(); + + sKey = p.getPrivate(); + vKey = p.getPublic(); + + s.initSign(sKey); + + s.update(data); + + sigBytes = s.sign(); + + s = Signature.getInstance("ECDSA", "SC"); + + s.initVerify(vKey); + + s.update(data); + + if (!s.verify(sigBytes)) + { + fail("ECDSA verification failed"); + } + + // + // key decoding test - serialisation test + // + + PublicKey eck1 = (PublicKey)serializeDeserialize(vKey); + + checkEquals(eck1, vKey); + + PrivateKey eck2 = (PrivateKey)serializeDeserialize(sKey); + + checkEquals(eck2, sKey); + + // Named curve parameter + g.initialize(new ECNamedCurveGenParameterSpec("P-256"), new SecureRandom()); + + p = g.generateKeyPair(); + + sKey = p.getPrivate(); + vKey = p.getPublic(); + + s.initSign(sKey); + + s.update(data); + + sigBytes = s.sign(); + + s = Signature.getInstance("ECDSA", "SC"); + + s.initVerify(vKey); + + s.update(data); + + if (!s.verify(sigBytes)) + { + fail("ECDSA verification failed"); + } + + // + // key decoding test - serialisation test + // + + eck1 = (PublicKey)serializeDeserialize(vKey); + + checkEquals(eck1, vKey); + + eck2 = (PrivateKey)serializeDeserialize(sKey); + + checkEquals(eck2, sKey); + + // + // ECDSA F2m generation test + // + s = Signature.getInstance("ECDSA", "SC"); + g = KeyPairGenerator.getInstance("ECDSA", "SC"); + + curve = new ECCurve.F2m( + 239, // m + 36, // k + new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a + new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b + + ecSpec = new ECParameterSpec( + curve, + curve.decodePoint(Hex.decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G + new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n + BigInteger.valueOf(4)); // h + + g.initialize(ecSpec, new SecureRandom()); + + p = g.generateKeyPair(); + + sKey = p.getPrivate(); + vKey = p.getPublic(); + + s.initSign(sKey); + + s.update(data); + + sigBytes = s.sign(); + + s = Signature.getInstance("ECDSA", "SC"); + + s.initVerify(vKey); + + s.update(data); + + if (!s.verify(sigBytes)) + { + fail("ECDSA verification failed"); + } + + // + // key decoding test - serialisation test + // + + eck1 = (PublicKey)serializeDeserialize(vKey); + + checkEquals(eck1, vKey); + + eck2 = (PrivateKey)serializeDeserialize(sKey); + + checkEquals(eck2, sKey); + + if (!(eck2 instanceof PKCS12BagAttributeCarrier)) + { + fail("private key not implementing PKCS12 attribute carrier"); + } + } + + private void checkEquals(Object o1, Object o2) + { + if (!o1.equals(o2)) + { + fail("comparison test failed"); + } + + if (o1.hashCode() != o2.hashCode()) + { + fail("hashCode test failed"); + } + } + + private void testParameters() + throws Exception + { + AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("DSA", "SC"); + a.init(512, random); + AlgorithmParameters params = a.generateParameters(); + + byte[] encodeParams = params.getEncoded(); + + AlgorithmParameters a2 = AlgorithmParameters.getInstance("DSA", "SC"); + a2.init(encodeParams); + + // a and a2 should be equivalent! + byte[] encodeParams_2 = a2.getEncoded(); + + if (!areEqual(encodeParams, encodeParams_2)) + { + fail("encode/decode parameters failed"); + } + + DSAParameterSpec dsaP = (DSAParameterSpec)params.getParameterSpec(DSAParameterSpec.class); + + KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "SC"); + g.initialize(dsaP, new SecureRandom()); + KeyPair p = g.generateKeyPair(); + + PrivateKey sKey = p.getPrivate(); + PublicKey vKey = p.getPublic(); + + Signature s = Signature.getInstance("DSA", "SC"); + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + s.initSign(sKey); + + s.update(data); + + byte[] sigBytes = s.sign(); + + s = Signature.getInstance("DSA", "SC"); + + s.initVerify(vKey); + + s.update(data); + + if (!s.verify(sigBytes)) + { + fail("DSA verification failed"); + } + } + + private void testDSA2Parameters() + throws Exception + { + byte[] seed = Hex.decode("4783081972865EA95D43318AB2EAF9C61A2FC7BBF1B772A09017BDF5A58F4FF0"); + + AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("DSA", "SC"); + a.init(2048, new DSATestSecureRandom(seed)); + AlgorithmParameters params = a.generateParameters(); + + DSAParameterSpec dsaP = (DSAParameterSpec)params.getParameterSpec(DSAParameterSpec.class); + + if (!dsaP.getQ().equals(new BigInteger("C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467", 16))) + { + fail("Q incorrect"); + } + + if (!dsaP.getP().equals(new BigInteger( + "F56C2A7D366E3EBDEAA1891FD2A0D099" + + "436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91" + + "D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C" + + "69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2" + + "5909132627F51A0C866877E672E555342BDF9355347DBD43" + + "B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431" + + "31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A" + + "EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD" + + "F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF" + + "1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D" + + "531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75", 16))) + { + fail("P incorrect"); + } + + if (!dsaP.getG().equals(new BigInteger( + "8DC6CC814CAE4A1C05A3E186A6FE27EA" + + "BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1" + + "29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB" + + "6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2" + + "513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869" + + "7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0" + + "A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403" + + "45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8" + + "FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E" + + "428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC" + + "EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279", 16))) + { + fail("G incorrect"); + } + + KeyPairGenerator g = KeyPairGenerator.getInstance("DSA", "SC"); + g.initialize(dsaP, new FixedSecureRandom(Hex.decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C"))); + KeyPair p = g.generateKeyPair(); + + DSAPrivateKey sKey = (DSAPrivateKey)p.getPrivate(); + DSAPublicKey vKey = (DSAPublicKey)p.getPublic(); + + if (!vKey.getY().equals(new BigInteger( + "2828003D7C747199143C370FDD07A286" + + "1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D" + + "1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA" + + "CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500" + + "C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF" + + "2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41" + + "9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF" + + "41566E26FAEE475137EC781A0DC088A26C8804A98C23140E" + + "7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D" + + "C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE" + + "A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B", 16))) + { + fail("Y value incorrect"); + } + + if (!sKey.getX().equals( + new BigInteger("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C", 16))) + { + fail("X value incorrect"); + } + + byte[] encodeParams = params.getEncoded(); + + AlgorithmParameters a2 = AlgorithmParameters.getInstance("DSA", "SC"); + a2.init(encodeParams); + + // a and a2 should be equivalent! + byte[] encodeParams_2 = a2.getEncoded(); + + if (!areEqual(encodeParams, encodeParams_2)) + { + fail("encode/decode parameters failed"); + } + + Signature s = Signature.getInstance("DSA", "SC"); + byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; + + s.initSign(sKey); + + s.update(data); + + byte[] sigBytes = s.sign(); + + s = Signature.getInstance("DSA", "SC"); + + s.initVerify(vKey); + + s.update(data); + + if (!s.verify(sigBytes)) + { + fail("DSA verification failed"); + } + } + + public void performTest() + throws Exception + { + testCompat(); + testNONEwithDSA(); + testECDSA239bitPrime(); + testNONEwithECDSA239bitPrime(); + testECDSA239bitBinary(); + testECDSA239bitBinary("RIPEMD160withECDSA", TeleTrusTObjectIdentifiers.ecSignWithRipemd160); + testECDSA239bitBinary("SHA1withECDSA", TeleTrusTObjectIdentifiers.ecSignWithSha1); + testECDSA239bitBinary("SHA224withECDSA", X9ObjectIdentifiers.ecdsa_with_SHA224); + testECDSA239bitBinary("SHA256withECDSA", X9ObjectIdentifiers.ecdsa_with_SHA256); + testECDSA239bitBinary("SHA384withECDSA", X9ObjectIdentifiers.ecdsa_with_SHA384); + testECDSA239bitBinary("SHA512withECDSA", X9ObjectIdentifiers.ecdsa_with_SHA512); + testECDSA239bitBinary("SHA1withCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_1); + testECDSA239bitBinary("SHA224withCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_224); + testECDSA239bitBinary("SHA256withCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_256); + testECDSA239bitBinary("SHA384withCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_384); + testECDSA239bitBinary("SHA512withCVC-ECDSA", EACObjectIdentifiers.id_TA_ECDSA_SHA_512); + + testGeneration(); + testParameters(); + testDSA2Parameters(); + } + + protected BigInteger[] derDecode( + byte[] encoding) + throws IOException + { + ByteArrayInputStream bIn = new ByteArrayInputStream(encoding); + ASN1InputStream aIn = new ASN1InputStream(bIn); + ASN1Sequence s = (ASN1Sequence)aIn.readObject(); + + BigInteger[] sig = new BigInteger[2]; + + sig[0] = ((DERInteger)s.getObjectAt(0)).getValue(); + sig[1] = ((DERInteger)s.getObjectAt(1)).getValue(); + + return sig; + } + + public String getName() + { + return "DSA/ECDSA"; + } + + public static void main( + String[] args) + { + Security.addProvider(new BouncyCastleProvider()); + + runTest(new DSATest()); + } + + private class DSATestSecureRandom + extends FixedSecureRandom + { + private boolean first = true; + + public DSATestSecureRandom(byte[] value) + { + super(value); + } + + public void nextBytes(byte[] bytes) + { + if (first) + { + super.nextBytes(bytes); + first = false; + } + else + { + bytes[bytes.length - 1] = 2; + } + } + } +} |