diff options
Diffstat (limited to 'libraries/spongycastle/prov/src/test/java/org/spongycastle/jce/provider/test/KeyStoreTest.java')
-rw-r--r-- | libraries/spongycastle/prov/src/test/java/org/spongycastle/jce/provider/test/KeyStoreTest.java | 424 |
1 files changed, 424 insertions, 0 deletions
diff --git a/libraries/spongycastle/prov/src/test/java/org/spongycastle/jce/provider/test/KeyStoreTest.java b/libraries/spongycastle/prov/src/test/java/org/spongycastle/jce/provider/test/KeyStoreTest.java new file mode 100644 index 000000000..dd25100bd --- /dev/null +++ b/libraries/spongycastle/prov/src/test/java/org/spongycastle/jce/provider/test/KeyStoreTest.java @@ -0,0 +1,424 @@ +package org.spongycastle.jce.provider.test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.Key; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Date; +import java.util.Hashtable; +import java.util.Vector; + +import org.spongycastle.jce.X509Principal; +import org.spongycastle.jce.provider.BouncyCastleProvider; +import org.spongycastle.jce.spec.ECParameterSpec; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.util.encoders.Base64; +import org.spongycastle.util.encoders.Hex; +import org.spongycastle.util.test.SimpleTest; +import org.spongycastle.x509.X509V3CertificateGenerator; + +/** + * Exercise the various key stores, making sure we at least get back what we put in! + * <p> + * This tests both the BKS, and the UBER key store. + */ +public class KeyStoreTest + extends SimpleTest +{ + static char[] passwd = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd' }; + + byte[] v1BKS = Base64.decode( + "AAAAAQAAABTqZbNMyPjsFazhFplWWDMBLPRdRAAABcYEAAdhbmRyb2lkAAAB" + + "NOifkPwAAAAAAAAAPAAAABTZOLhcyhB0gKyfoDvyQbpzftB7GgAABEYPrZP8" + + "q20AJLETjDv0K9C5rIl1erpyvpv20bqcbghK6wD0b8OP5/XzOz/8knhxmqJZ" + + "3yRJMw=="); + byte[] v2BKS = Base64.decode( + "AAAAAgAAABSkmTXz4VIznO1SSUqsIHdxWcxsuQAABFMEAAdhbmRyb2lkAAABN" + + "OifkPwAAAAAAAAAPAAAABTZOLhcyhB0gKyfoDvyQbpzftB7GgAABEYPrZP8q2" + + "0AJLETjDv0K9C5rIl1erpyvpv20bqcbghK6wBO59KOGPvSrmJpd32P6ZAh9qLZJw=="); + + byte[] v1UBER = Base64.decode( + "AAAAAQAAABRP0F6p2p3FyQKqyJiJt3NbvdybiwAAB2znqrO779YIW5gMtbt+" + + "NUs96VPPcfZiKJPg7RKH7Yu3CQB0/g9nYsvgFB0fQ05mHcW3KjntN2/31A6G" + + "i00n4ZnUTjJL16puZnQrloeGXxFy58tjwkFuwJ7V7ELYgiZlls0beHSdDGQW" + + "iyYECwWs1la/"); + byte[] v2UBER = Base64.decode( + "AAAAAgAAABQ/D9k3376OG/REg4Ams9Up332tLQAABujoVcsRcKWwhlo4mMg5" + + "lF2vJfK+okIYecJGWCvdykF5r8kDn68llt52IDXDkpRXVXcNJ0/aD7sa7iZ0" + + "SL0TAwcfp/9v4j/w8slj/qgO0i/76+zROrP0NGFIa5k/iOg5Z0Tj77muMaJf" + + "n3vLlIHa4IsX"); + + byte[] negSaltBKS = Base64.decode( + "AAAAAv////+WnyglO06djy6JgCxGiIemnZdcOwAAB2AEAAdhbmRyb2lkAAAB" + + "NOifkPwAAAAAAAAAPAAAABTZOLhcyhB0gKyfoDvyQbpzftB7GgAABEYPrZP8" + + "q20AJLETjDv0K9C5rIl1erpyvpv20bqcbghK6wDrg6gUHsh27wNjUwkR+REe" + + "NeFYBg=="); + + char[] oldStorePass = "fredfred".toCharArray(); + + public void ecStoreTest( + String storeName) + throws Exception + { + 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 + + KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "SC"); + + g.initialize(ecSpec, new SecureRandom()); + + KeyPair keyPair = g.generateKeyPair(); + + PublicKey pubKey = keyPair.getPublic(); + PrivateKey privKey = keyPair.getPrivate(); + + // + // distinguished name table. + // + Hashtable attrs = new Hashtable(); + Vector order = new Vector(); + + attrs.put(X509Principal.C, "AU"); + attrs.put(X509Principal.O, "The Legion of the Bouncy Castle"); + attrs.put(X509Principal.L, "Melbourne"); + attrs.put(X509Principal.ST, "Victoria"); + attrs.put(X509Principal.E, "feedback-crypto@bouncycastle.org"); + + order.addElement(X509Principal.C); + order.addElement(X509Principal.O); + order.addElement(X509Principal.L); + order.addElement(X509Principal.ST); + order.addElement(X509Principal.E); + + // + // create the certificate - version 3 + // + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.setSerialNumber(BigInteger.valueOf(1)); + certGen.setIssuerDN(new X509Principal(order, attrs)); + certGen.setNotBefore(new Date(System.currentTimeMillis() - 50000)); + certGen.setNotAfter(new Date(System.currentTimeMillis() + 50000)); + certGen.setSubjectDN(new X509Principal(order, attrs)); + certGen.setPublicKey(pubKey); + certGen.setSignatureAlgorithm("ECDSAwithSHA1"); + + Certificate[] chain = new Certificate[1]; + + try + { + X509Certificate cert = certGen.generate(privKey); + + cert.checkValidity(new Date()); + + cert.verify(pubKey); + + ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); + CertificateFactory fact = CertificateFactory.getInstance("X.509", "SC"); + + cert = (X509Certificate)fact.generateCertificate(bIn); + + chain[0] = cert; + } + catch (Exception e) + { + fail("error generating cert - " + e.toString()); + } + + KeyStore store = KeyStore.getInstance(storeName, "SC"); + + store.load(null, null); + + store.setKeyEntry("private", privKey, passwd, chain); + + // + // write out and read back store + // + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + store.store(bOut, passwd); + + ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray()); + + // + // start with a new key store + // + store = KeyStore.getInstance(storeName, "SC"); + + store.load(bIn, passwd); + + // + // load the private key + // + privKey = (PrivateKey)store.getKey("private", passwd); + + // + // double public key encoding test + // + byte[] pubEnc = pubKey.getEncoded(); + KeyFactory keyFac = KeyFactory.getInstance(pubKey.getAlgorithm(), "SC"); + X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc); + + pubKey = (PublicKey)keyFac.generatePublic(pubX509); + + pubEnc = pubKey.getEncoded(); + keyFac = KeyFactory.getInstance(pubKey.getAlgorithm(), "SC"); + pubX509 = new X509EncodedKeySpec(pubEnc); + + pubKey = (PublicKey)keyFac.generatePublic(pubX509); + + // + // double private key encoding test + // + byte[] privEnc = privKey.getEncoded(); + + keyFac = KeyFactory.getInstance(privKey.getAlgorithm(), "SC"); + + PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc); + privKey = (PrivateKey)keyFac.generatePrivate(privPKCS8); + + keyFac = KeyFactory.getInstance(privKey.getAlgorithm(), "SC"); + privPKCS8 = new PKCS8EncodedKeySpec(privEnc); + privKey = (PrivateKey)keyFac.generatePrivate(privPKCS8); + } + + public void keyStoreTest( + String storeName) + throws Exception + { + KeyStore store = KeyStore.getInstance(storeName, "SC"); + + store.load(null, null); + + KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA", "SC"); + + gen.initialize(1024, new SecureRandom()); + + KeyPair pair = gen.generateKeyPair(); + RSAPrivateKey privKey = (RSAPrivateKey)pair.getPrivate(); + RSAPublicKey pubKey = (RSAPublicKey)pair.getPublic(); + BigInteger modulus = privKey.getModulus(); + BigInteger privateExponent = privKey.getPrivateExponent(); + + + // + // distinguished name table. + // + Hashtable attrs = new Hashtable(); + Vector order = new Vector(); + + attrs.put(X509Principal.C, "AU"); + attrs.put(X509Principal.O, "The Legion of the Bouncy Castle"); + attrs.put(X509Principal.L, "Melbourne"); + attrs.put(X509Principal.ST, "Victoria"); + attrs.put(X509Principal.EmailAddress, "feedback-crypto@bouncycastle.org"); + + order.addElement(X509Principal.C); + order.addElement(X509Principal.O); + order.addElement(X509Principal.L); + order.addElement(X509Principal.ST); + order.addElement(X509Principal.EmailAddress); + + // + // extensions + // + + // + // create the certificate. + // + X509V3CertificateGenerator certGen = new X509V3CertificateGenerator(); + + certGen.setSerialNumber(BigInteger.valueOf(1)); + certGen.setIssuerDN(new X509Principal(order, attrs)); + certGen.setNotBefore(new Date(System.currentTimeMillis() - 50000)); + certGen.setNotAfter(new Date(System.currentTimeMillis() + 50000)); + certGen.setSubjectDN(new X509Principal(order, attrs)); + certGen.setPublicKey(pubKey); + certGen.setSignatureAlgorithm("MD5WithRSAEncryption"); + + Certificate[] chain = new Certificate[1]; + + try + { + X509Certificate cert = certGen.generate(privKey); + + cert.checkValidity(new Date()); + + cert.verify(pubKey); + + ByteArrayInputStream bIn = new ByteArrayInputStream(cert.getEncoded()); + CertificateFactory fact = CertificateFactory.getInstance("X.509", "SC"); + + cert = (X509Certificate)fact.generateCertificate(bIn); + + chain[0] = cert; + } + catch (Exception e) + { + fail("error generating cert - " + e.toString()); + } + + store.setKeyEntry("private", privKey, passwd, chain); + + // + // write out and read back store + // + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + store.store(bOut, passwd); + + ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray()); + + // + // start with a new key store + // + store = KeyStore.getInstance(storeName, "SC"); + + store.load(bIn, passwd); + + // + // verify public key + // + privKey = (RSAPrivateKey)store.getKey("private", passwd); + + if (!privKey.getModulus().equals(modulus)) + { + fail("private key modulus wrong"); + } + else if (!privKey.getPrivateExponent().equals(privateExponent)) + { + fail("private key exponent wrong"); + } + + // + // verify certificate + // + Certificate cert = store.getCertificateChain("private")[0]; + + cert.verify(pubKey); + } + + private void oldStoreTest() + throws Exception + { + checkStore(KeyStore.getInstance("BKS", "SC"), v1BKS); + checkStore(KeyStore.getInstance("BKS", "SC"), v2BKS); + checkStore(KeyStore.getInstance("UBER", "SC"), v1UBER); + checkStore(KeyStore.getInstance("UBER", "SC"), v2UBER); + + checkOldStore(KeyStore.getInstance("BKS-V1", "SC"), v1BKS); + checkOldStore(KeyStore.getInstance("BKS-V1", "SC"), v2BKS); + } + + private void checkStore(KeyStore ks, byte[] data) + throws Exception + { + ks.load(new ByteArrayInputStream(data), oldStorePass); + + if (!ks.containsAlias("android")) + { + fail("cannot find alias"); + } + + Key key = ks.getKey("android", oldStorePass); + if (key == null) + { + fail("cannot find key"); + } + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + ks.store(bOut, oldStorePass); + } + + private void checkOldStore(KeyStore ks, byte[] data) + throws Exception + { + ks.load(new ByteArrayInputStream(data), oldStorePass); + + if (!ks.containsAlias("android")) + { + fail("cannot find alias"); + } + + Key key = ks.getKey("android", oldStorePass); + if (key == null) + { + fail("cannot find key"); + } + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + ks.store(bOut, oldStorePass); + + if (data.length != bOut.toByteArray().length) + { + fail("Old version key store write incorrect"); + } + } + + private void checkException() + throws Exception + { + KeyStore ks = KeyStore.getInstance("BKS", "SC"); + + try + { + ks.load(new ByteArrayInputStream(negSaltBKS), oldStorePass); + } + catch (IOException e) + { + if (!e.getMessage().equals("Invalid salt detected")) + { + fail("negative salt length not detected"); + } + } + } + + public String getName() + { + return "KeyStore"; + } + + public void performTest() + throws Exception + { + keyStoreTest("BKS"); + keyStoreTest("UBER"); + keyStoreTest("BKS-V1"); + ecStoreTest("BKS"); + oldStoreTest(); + checkException(); + } + + public static void main( + String[] args) + { + Security.addProvider(new BouncyCastleProvider()); + + runTest(new KeyStoreTest()); + } +} |