aboutsummaryrefslogtreecommitdiffstats
path: root/libraries/spongycastle/prov/src/test/java/org/spongycastle/jce/provider/test/KeyStoreTest.java
diff options
context:
space:
mode:
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.java424
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());
+ }
+}