| /* |
| * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* |
| * |
| * |
| * @summary Testing keytool |
| * @author weijun.wang |
| * |
| * Run through autotest.sh and manualtest.sh |
| * |
| * Testing non-PKCS11 keystores: |
| * echo | java -Dfile KeyToolTest |
| * |
| * Testing NSS PKCS11 keystores: |
| * # testing NSS |
| * # make sure the NSS db files are in current directory and writable |
| * echo | java -Dnss -Dnss.lib=/path/to/libsoftokn3.so KeyToolTest |
| * |
| * Testing Solaris Cryptography Framework PKCS11 keystores: |
| * # make sure you've already run pktool and set test12 as pin |
| * echo | java -Dsolaris KeyToolTest |
| * |
| * ATTENTION: |
| * Exception in thread "main" java.security.ProviderException: |
| * sun.security.pkcs11.wrapper.PKCS11Exception: CKR_KEY_SIZE_RANGE |
| * at sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:420) |
| * ... |
| * Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_KEY_SIZE_RANGE |
| * at sun.security.pkcs11.wrapper.PKCS11.C_SignFinal(Native Method) |
| * at sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:391) |
| * ... |
| * been observed. Possibly a Solaris bug |
| * |
| * ATTENTION: |
| * NSS PKCS11 config file are changed, DSA not supported now. |
| */ |
| |
| import java.security.KeyStore; |
| import sun.security.x509.*; |
| import java.io.*; |
| import java.security.KeyPairGenerator; |
| import java.security.NoSuchAlgorithmException; |
| import java.util.*; |
| import java.security.cert.X509Certificate; |
| import sun.security.util.ObjectIdentifier; |
| |
| public class KeyToolTest { |
| |
| // The stdout and stderr outputs after a keytool run |
| String out; |
| String err; |
| |
| // the output of println() in KeyTool.run |
| String ex; |
| |
| String lastInput = "", lastCommand = ""; |
| private static final boolean debug = |
| System.getProperty("debug") != null; |
| |
| static final String NSS_P11_ARG = |
| "-keystore NONE -storetype PKCS11 -providerName SunPKCS11-nss " + |
| "-providerClass sun.security.pkcs11.SunPKCS11 " + |
| "-providerArg p11-nss.txt "; |
| static final String NSS_SRC_P11_ARG = |
| "-srckeystore NONE -srcstoretype PKCS11 " + |
| "-srcproviderName SunPKCS11-nss " + |
| "-providerClass sun.security.pkcs11.SunPKCS11 " + |
| "-providerArg p11-nss.txt "; |
| static final String NZZ_P11_ARG = |
| "-keystore NONE -storetype PKCS11 -providerName SunPKCS11-nzz " + |
| "-providerClass sun.security.pkcs11.SunPKCS11 " + |
| "-providerArg p11-nzz.txt "; |
| static final String NZZ_SRC_P11_ARG = |
| "-srckeystore NONE -srcstoretype PKCS11 " + |
| "-srcproviderName SunPKCS11-nzz " + |
| "-providerClass sun.security.pkcs11.SunPKCS11 " + |
| "-providerArg p11-nzz.txt "; |
| static final String SUN_P11_ARG = "-keystore NONE -storetype PKCS11 "; |
| static final String SUN_SRC_P11_ARG = |
| "-srckeystore NONE -srcstoretype PKCS11 "; |
| |
| String p11Arg, srcP11Arg; |
| |
| /** Creates a new instance of KeyToolTest */ |
| KeyToolTest() { |
| // so that there is "Warning" and not translated into other language |
| Locale.setDefault(Locale.US); |
| } |
| |
| /** |
| * Helper, removes a file |
| */ |
| void remove(String filename) { |
| if (debug) { |
| System.err.println("Removing " + filename); |
| } |
| new File(filename).delete(); |
| if (new File(filename).exists()) { |
| throw new RuntimeException("Error deleting " + filename); |
| } |
| } |
| |
| /** |
| * Run a set of keytool command with given terminal input. |
| * @param input the terminal inputs, the characters typed by human |
| * if <code>cmd</code> is running on a terminal |
| * @param cmd the argument of a keytool command line |
| * @throws if keytool goes wrong in some place |
| */ |
| void test(String input, String cmd) throws Exception { |
| lastInput = input; |
| lastCommand = cmd; |
| |
| // "X" is appended so that we can precisely test how input is consumed |
| HumanInputStream in = new HumanInputStream(input+"X"); |
| test(in, cmd); |
| // make sure the input string is no more no less |
| if(in.read() != 'X' || in.read() != -1) |
| throw new Exception("Input not consumed exactly"); |
| } |
| |
| void test(InputStream in, String cmd) throws Exception { |
| |
| // save the original 3 streams |
| if (debug) { |
| System.err.println(cmd); |
| } else { |
| System.err.print("."); |
| } |
| PrintStream p1 = System.out; |
| PrintStream p2 = System.err; |
| InputStream i1 = System.in; |
| |
| ByteArrayOutputStream b1 = new ByteArrayOutputStream(); |
| ByteArrayOutputStream b2 = new ByteArrayOutputStream(); |
| |
| try { |
| System.setIn(in); |
| System.setOut(new PrintStream(b1)); |
| System.setErr(new PrintStream(b2)); |
| |
| // since System.in is overrided, the |
| // sun.security.tools.keytool.Main.main() method will |
| // never block at user input |
| |
| // use -debug so that main() will throw an Exception |
| // instead of calling System.exit() |
| sun.security.tools.keytool.Main.main(("-debug "+cmd).split("\\s+")); |
| } finally { |
| out = b1.toString(); |
| err = b2.toString(); |
| ex = out; // now it goes to System.out |
| System.setIn(i1); |
| System.setOut(p1); |
| System.setErr(p2); |
| } |
| } |
| |
| /** |
| * Call this method if you expect test(input, cmd) should go OK |
| */ |
| void testOK(String input, String cmd) throws Exception { |
| try { |
| // Workaround for "8057810: Make SHA256withDSA the default |
| // jarsigner and keytool algorithm for DSA keys". Unfortunately |
| // SunPKCS11-NSS does not support SHA256withDSA yet. |
| if (cmd.contains("p11-nss.txt") && cmd.contains("-genkey") |
| && !cmd.contains("-keyalg")) { |
| cmd += " -sigalg SHA1withDSA -keysize 1024"; |
| } |
| test(input, cmd); |
| } catch(Exception e) { |
| afterFail(input, cmd, "OK"); |
| throw e; |
| } |
| } |
| |
| /** |
| * Call this method if you expect test(input, cmd) should fail and throw |
| * an exception |
| */ |
| void testFail(String input, String cmd) throws Exception { |
| boolean ok; |
| try { |
| test(input, cmd); |
| ok = true; |
| } catch(Exception e) { |
| if (e instanceof MissingResourceException) { |
| ok = true; |
| } else { |
| ok = false; |
| } |
| } |
| if(ok) { |
| afterFail(input, cmd, "FAIL"); |
| throw new RuntimeException(); |
| } |
| } |
| |
| /** |
| * Call this method if you expect test(input, cmd) should go OK |
| */ |
| void testOK(InputStream is, String cmd) throws Exception { |
| try { |
| test(is, cmd); |
| } catch(Exception e) { |
| afterFail("", cmd, "OK"); |
| throw e; |
| } |
| } |
| |
| /** |
| * Call this method if you expect test(input, cmd) should fail and throw |
| * an exception |
| */ |
| void testFail(InputStream is, String cmd) throws Exception { |
| boolean ok; |
| try { |
| test(is, cmd); |
| ok = true; |
| } catch(Exception e) { |
| ok = false; |
| } |
| if(ok) { |
| afterFail("", cmd, "FAIL"); |
| throw new RuntimeException(); |
| } |
| } |
| |
| /** |
| * Call this method if you just want to run the command and does |
| * not care if it succeeds or fails. |
| */ |
| void testAnyway(String input, String cmd) { |
| try { |
| test(input, cmd); |
| } catch(Exception e) { |
| ; |
| } |
| } |
| |
| /** |
| * Helper method, print some output after a test does not do as expected |
| */ |
| void afterFail(String input, String cmd, String should) { |
| if (cmd.contains("p11-nss.txt")) { |
| cmd = "-J-Dnss.lib=" + System.getProperty("nss.lib") + " " + cmd; |
| } |
| System.err.println("\nTest fails for the command ---\n" + |
| "keytool " + cmd + "\nOr its debug version ---\n" + |
| "keytool -debug " + cmd); |
| |
| System.err.println("The command result should be " + should + |
| ", but it's not. Try run the command manually and type" + |
| " these input into it: "); |
| char[] inputChars = input.toCharArray(); |
| |
| for (int i=0; i<inputChars.length; i++) { |
| char ch = inputChars[i]; |
| if (ch == '\n') System.err.print("ENTER "); |
| else if (ch == ' ') System.err.print("SPACE "); |
| else System.err.print(ch + " "); |
| } |
| System.err.println(""); |
| |
| System.err.println("ERR is:\n"+err); |
| System.err.println("OUT is:\n"+out); |
| } |
| |
| void assertTrue(boolean bool, String msg) { |
| if (debug) { |
| System.err.println("If not " + bool + ", " + msg); |
| } else { |
| System.err.print("v"); |
| } |
| if(!bool) { |
| afterFail(lastInput, lastCommand, "TRUE"); |
| System.err.println(msg); |
| throw new RuntimeException(msg); |
| } |
| } |
| |
| void assertTrue(boolean bool) { |
| assertTrue(bool, "well..."); |
| } |
| /** |
| * Helper method, load a keystore |
| * @param file file for keystore, null or "NONE" for PKCS11 |
| * @pass password for the keystore |
| * @type keystore type |
| * @returns the KeyStore object |
| * @exception Exception if anything goes wrong |
| */ |
| KeyStore loadStore(String file, String pass, String type) throws Exception { |
| KeyStore ks = KeyStore.getInstance(type); |
| FileInputStream is = null; |
| if (file != null && !file.equals("NONE")) { |
| is = new FileInputStream(file); |
| } |
| ks.load(is, pass.toCharArray()); |
| is.close(); |
| return ks; |
| } |
| |
| /** |
| * The test suite. |
| * Maybe it's better to put this outside the KeyToolTest class |
| */ |
| void testAll() throws Exception { |
| KeyStore ks; |
| |
| remove("x.jks"); |
| remove("x.jceks"); |
| remove("x.p12"); |
| remove("x2.jceks"); |
| remove("x2.jks"); |
| remove("x.jks.p1.cert"); |
| |
| // name changes: genkeypair, importcert, exportcert |
| remove("x.jks"); |
| remove("x.jks.p1.cert"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -alias p1 -dname CN=olala"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-exportcert -alias p1 -file x.jks.p1.cert"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.getKey("p1", "changeit".toCharArray()) != null, |
| "key not DSA"); |
| assertTrue(new File("x.jks.p1.cert").exists(), "p1 export err"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-delete -alias p1"); |
| // importcert, prompt for Yes/No |
| testOK("y\n", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -alias c1 -file x.jks.p1.cert"); |
| // importcert, -noprompt |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -alias c2 -file x.jks.p1.cert -noprompt"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.getCertificate("c1") != null, "import c1 err"); |
| |
| // v3 |
| byte[] encoded = ks.getCertificate("c1").getEncoded(); |
| X509CertImpl certImpl = new X509CertImpl(encoded); |
| assertTrue(certImpl.getVersion() == 3, "Version is not 3"); |
| |
| // changealias and keyclone |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -alias p1 -dname CN=olala"); |
| testOK("changeit\n", "-keystore x.jks -storetype JKS " + |
| "-changealias -alias p1 -destalias p11"); |
| testOK("changeit\n", "-keystore x.jks -storetype JKS " + |
| "-changealias -alias c1 -destalias c11"); |
| // press ENTER when prompt for p111's keypass |
| testOK("changeit\n\n", "-keystore x.jks -storetype JKS " + |
| "-keyclone -alias p11 -destalias p111"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(!ks.containsAlias("p1"), "there is no p1"); |
| assertTrue(!ks.containsAlias("c1"), "there is no c1"); |
| assertTrue(ks.containsAlias("p11"), "there is p11"); |
| assertTrue(ks.containsAlias("c11"), "there is c11"); |
| assertTrue(ks.containsAlias("p111"), "there is p111"); |
| |
| // genSecKey |
| remove("x.jceks"); |
| // DES, no need keysize |
| testOK("changeit\nchangeit\n\n", "-keystore x.jceks -storetype JCEKS " + |
| "-genseckey -alias s1"); |
| // DES, keysize cannot be 128 |
| testFail("changeit\n\n", "-keystore x.jceks -storetype JCEKS " + |
| "-genseckey -alias s11 -keysize 128"); |
| // DESede. no need keysize |
| testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS " + |
| "-genseckey -keyalg DESede -alias s2"); |
| // AES, need keysize |
| testFail("changeit\n\n", "-keystore x.jceks -storetype AES " + |
| "-genseckey -keyalg Rijndael -alias s3"); |
| testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS " + |
| "-genseckey -keyalg AES -alias s3 -keysize 128"); |
| // about keypass |
| // can accept storepass |
| testOK("\n", "-keystore x.jceks -storetype JCEKS -storepass changeit " + |
| "-genseckey -alias s4"); |
| // or a new one |
| testOK("keypass\nkeypass\n", "-keystore x.jceks -storetype JCEKS " + |
| "-storepass changeit -genseckey -alias s5"); |
| // keypass must be valid (prompt 3 times) |
| testOK("bad\n\bad\nkeypass\nkeypass\n", "-keystore x.jceks " + |
| "-storetype JCEKS -storepass changeit -genseckey -alias s6"); |
| // keypass must be valid (prompt 3 times) |
| testFail("bad\n\bad\nbad\n", "-keystore x.jceks -storetype JCEKS " + |
| "-storepass changeit -genseckey -alias s7"); |
| // keypass must be valid (prompt 3 times) |
| testFail("bad\n\bad\nbad\nkeypass\n", "-keystore x.jceks " + |
| "-storetype JCEKS -storepass changeit -genseckey -alias s7"); |
| ks = loadStore("x.jceks", "changeit", "JCEKS"); |
| assertTrue(ks.getKey("s1", "changeit".toCharArray()) |
| .getAlgorithm().equalsIgnoreCase("DES"), "s1 is DES"); |
| assertTrue(ks.getKey("s1", "changeit".toCharArray()) |
| .getEncoded().length == 8, "DES is 56"); |
| assertTrue(ks.getKey("s2", "changeit".toCharArray()) |
| .getEncoded().length == 24, "DESede is 168"); |
| assertTrue(ks.getKey("s2", "changeit".toCharArray()) |
| .getAlgorithm().equalsIgnoreCase("DESede"), "s2 is DESede"); |
| assertTrue(ks.getKey("s3", "changeit".toCharArray()) |
| .getAlgorithm().equalsIgnoreCase("AES"), "s3 is AES"); |
| assertTrue(ks.getKey("s4", "changeit".toCharArray()) |
| .getAlgorithm().equalsIgnoreCase("DES"), "s4 is DES"); |
| assertTrue(ks.getKey("s5", "keypass".toCharArray()) |
| .getAlgorithm().equalsIgnoreCase("DES"), "s5 is DES"); |
| assertTrue(ks.getKey("s6", "keypass".toCharArray()) |
| .getAlgorithm().equalsIgnoreCase("DES"), "s6 is DES"); |
| assertTrue(!ks.containsAlias("s7"), "s7 not created"); |
| |
| // maybe we needn't test this, one day JKS will support SecretKey |
| //testFail("changeit\nchangeit\n", "-keystore x.jks -storetype JKS " + |
| // "-genseckey -keyalg AES -alias s3 -keysize 128"); |
| |
| // importKeyStore |
| remove("x.jks"); |
| remove("x.jceks"); |
| // create 2 entries... |
| testOK("changeit\nchangeit\n\n", "-keystore x.jceks -storetype JCEKS " + |
| "-genkeypair -alias p1 -dname CN=Olala"); |
| testOK("", "-keystore x.jceks -storetype JCEKS -storepass changeit " + |
| "-importcert -alias c1 -file x.jks.p1.cert -noprompt"); |
| ks = loadStore("x.jceks", "changeit", "JCEKS"); |
| assertTrue(ks.size() == 2, "2 entries in JCEKS"); |
| // import, shouldn't mention destalias/srckeypass/destkeypass |
| // if srcalias is no given |
| testFail("changeit\nchangeit\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS -destalias pp"); |
| testFail("changeit\nchangeit\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS -srckeypass changeit"); |
| testFail("changeit\nchangeit\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS -destkeypass changeit"); |
| // normal import |
| testOK("changeit\nchangeit\nchangeit\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.size() == 2, "2 entries in JKS"); |
| // import again, type yes to overwrite old entries |
| testOK("changeit\nchangeit\ny\ny\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| // import again, specify -nopromt |
| testOK("changeit\nchangeit\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS -noprompt"); |
| assertTrue(err.indexOf("Warning") != -1, "noprompt will warn"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.size() == 2, "2 entries in JKS"); |
| // import again, type into new aliases when prompted |
| testOK("changeit\nchangeit\n\ns1\n\ns2\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.size() == 4, "4 entries in JKS"); |
| |
| // importkeystore single |
| // normal |
| remove("x.jks"); |
| testOK("changeit\nchangeit\nchangeit\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS -srcalias p1"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.size() == 1, "1 entries in JKS"); |
| // overwrite |
| testOK("changeit\nchangeit\ny\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS -srcalias p1"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.size() == 1, "1 entries in JKS"); |
| // noprompt |
| testOK("changeit\nchangeit\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS " + |
| "-srcalias p1 -noprompt"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.size() == 1, "1 entries in JKS"); |
| // rename |
| testOK("changeit\nchangeit\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS " + |
| "-srcalias p1 -destalias p2"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.size() == 2, "2 entries in JKS"); |
| // another rename |
| testOK("changeit\nchangeit\n\nnewalias\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS -srcalias p1"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.size() == 3, "3 entries in JKS"); |
| |
| // importkeystore single, different keypass |
| remove("x.jks"); |
| // generate entry with different keypass |
| testOK("changeit\nkeypass\nkeypass\n", "-keystore x.jceks " + |
| "-storetype JCEKS -genkeypair -alias p2 -dname CN=Olala"); |
| // prompt |
| testOK("changeit\nchangeit\nchangeit\nkeypass\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS -srcalias p2"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.size() == 1, "1 entries in JKS"); |
| // diff destkeypass |
| testOK("changeit\nchangeit\nkeypass\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS " + |
| "-srcalias p2 -destalias p3 -destkeypass keypass2"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.size() == 2, "2 entries in JKS"); |
| assertTrue(ks.getKey("p2", "keypass".toCharArray()) != null, |
| "p2 has old password"); |
| assertTrue(ks.getKey("p3", "keypass2".toCharArray()) != null, |
| "p3 has new password"); |
| |
| // importkeystore single, cert |
| remove("x.jks"); |
| // normal |
| testOK("changeit\nchangeit\nchangeit\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS -srcalias c1"); |
| // in fact srcstorepass can be ignored |
| testOK("changeit\n\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS " + |
| "-srcalias c1 -destalias c2"); |
| assertTrue(err.indexOf("WARNING") != -1, "But will warn"); |
| // 2nd import, press y to overwrite ... |
| testOK("changeit\n\ny\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS " + |
| "-srcalias c1 -destalias c2"); |
| // ... or rename |
| testOK("changeit\n\n\nc3\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS " + |
| "-srcalias c1 -destalias c2"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| // c1, c2, c3 |
| assertTrue(ks.size() == 3, "3 entries in JKS"); |
| |
| // importkeystore, secretkey |
| remove("x.jks"); |
| // create SecretKeyEntry |
| testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS " + |
| "-genseckey -alias s1"); |
| // create SecretKeyEntry |
| testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS " + |
| "-genseckey -alias s2"); |
| // remove the keypass!=storepass one |
| testOK("changeit\n", "-keystore x.jceks -storetype JCEKS " + |
| "-delete -alias p2"); |
| ks = loadStore("x.jceks", "changeit", "JCEKS"); |
| // p1, c1, s1, s2 |
| assertTrue(ks.size() == 4, "4 entries in JCEKS"); |
| // normal |
| testOK("changeit\nchangeit\nchangeit\n", "-importkeystore " + |
| "-srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS -srcalias s1"); |
| assertTrue(err.indexOf("not imported") != -1, "Not imported"); |
| assertTrue(err.indexOf("Cannot store non-PrivateKeys") != -1, |
| "Not imported"); |
| |
| // Importing a JCEKS keystore to a JKS one. Will warn |
| // for the 2 SecretKey entries |
| |
| remove("x.jks"); |
| // Two "no" answers to bypass warnings |
| // normal |
| testOK("\n\n", "-srcstorepass changeit -deststorepass changeit " + |
| "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS"); |
| assertTrue(err.indexOf("s1 not") != -1, "s1 not"); |
| assertTrue(err.indexOf("s2 not") != -1, "s2 not"); |
| assertTrue(err.indexOf("c1 success") != -1, "c1 success"); |
| assertTrue(err.indexOf("p1 success") != -1, "p1 success"); |
| remove("x.jks"); |
| // One "yes" to stop |
| // normal |
| testOK("yes\n", "-srcstorepass changeit -deststorepass changeit " + |
| "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS " + |
| "-destkeystore x.jks -deststoretype JKS"); |
| // maybe c1 or p1 has been imported before s1 or s2 is touched, |
| // anyway we know yesNo is only asked once. |
| |
| // pkcs12 |
| remove("x.jks"); |
| // JKS prompt for keypass |
| testFail("changeit\nchangeit\n", "-keystore x.jks -storetype JKS " + |
| "-genkeypair -alias p1 -dname CN=olala"); |
| remove("x.jks"); |
| // just type ENTER means keypass=storepass |
| testOK("changeit\nchangeit\n\n", "-keystore x.jks -storetype JKS " + |
| "-genkeypair -alias p1 -dname CN=olala"); |
| remove("x.p12"); |
| // PKCS12 only need storepass |
| testOK("", "-keystore x.p12 -storetype PKCS12 -storepass changeit " + |
| "-genkeypair -alias p0 -dname CN=olala"); |
| testOK("changeit\n", "-keystore x.p12 -storetype PKCS12 " + |
| "-genkeypair -alias p1 -dname CN=olala"); |
| // when specify keypass, make sure keypass==storepass... |
| testOK("changeit\n", "-keystore x.p12 -keypass changeit " + |
| "-storetype PKCS12 -genkeypair -alias p3 -dname CN=olala"); |
| assertTrue(err.indexOf("Warning") == -1, |
| "PKCS12 silent when keypass == storepass"); |
| // otherwise, print a warning |
| testOK("changeit\n", "-keystore x.p12 -keypass another" + |
| " -storetype PKCS12 -genkeypair -alias p2 -dname CN=olala"); |
| assertTrue(err.indexOf("Warning") != -1, |
| "PKCS12 warning when keypass != storepass"); |
| // no -keypasswd for PKCS12 |
| testFail("", "-keystore x.p12 -storepass changeit -storetype PKCS12" + |
| " -keypasswd -new changeit -alias p3"); |
| testOK("", "-keystore x.p12 -storepass changeit -storetype PKCS12 " + |
| "-changealias -alias p3 -destalias p33"); |
| testOK("", "-keystore x.p12 -storepass changeit -storetype PKCS12 " + |
| "-keyclone -alias p33 -destalias p3"); |
| |
| // pkcs12 |
| remove("x.p12"); |
| // PKCS12 only need storepass |
| testOK("", "-keystore x.p12 -storetype PKCS12 -storepass changeit " + |
| "-genkeypair -alias p0 -dname CN=olala"); |
| testOK("", "-storepass changeit -keystore x.p12 -storetype PKCS12 " + |
| "-genkeypair -alias p1 -dname CN=olala"); |
| // when specify keypass, make sure keypass==storepass... |
| testOK("", "-storepass changeit -keystore x.p12 -keypass changeit " + |
| "-storetype PKCS12 -genkeypair -alias p3 -dname CN=olala"); |
| assertTrue(err.indexOf("Warning") == -1, |
| "PKCS12 silent when keypass == storepass"); |
| // otherwise, print a warning |
| testOK("", "-storepass changeit -keystore x.p12 -keypass another " + |
| "-storetype PKCS12 -genkeypair -alias p2 -dname CN=olala"); |
| assertTrue(err.indexOf("Warning") != -1, |
| "PKCS12 warning when keypass != storepass"); |
| |
| remove("x.jks"); |
| remove("x.jceks"); |
| remove("x.p12"); |
| remove("x2.jceks"); |
| remove("x2.jks"); |
| remove("x.jks.p1.cert"); |
| } |
| |
| void testPKCS11() throws Exception { |
| KeyStore ks; |
| // pkcs11, the password maybe different and maybe PKCS11 not supported |
| |
| // in case last test is not executed successfully |
| testAnyway("", p11Arg + "-storepass test12 -delete -alias p1"); |
| testAnyway("", p11Arg + "-storepass test12 -delete -alias p2"); |
| testAnyway("", p11Arg + "-storepass test12 -delete -alias p3"); |
| testAnyway("", p11Arg + "-storepass test12 -delete -alias nss"); |
| |
| testOK("", p11Arg + "-storepass test12 -list"); |
| assertTrue(out.indexOf("Your keystore contains 0 entries") != -1, |
| "*** MAKE SURE YOU HAVE NO ENTRIES IN YOUR PKCS11 KEYSTORE " + |
| "BEFORE THIS TEST ***"); |
| |
| testOK("", p11Arg + |
| "-storepass test12 -genkeypair -alias p1 -dname CN=olala"); |
| testOK("test12\n", p11Arg + "-genkeypair -alias p2 -dname CN=olala2"); |
| // cannot provide keypass for PKCS11 |
| testFail("test12\n", p11Arg + |
| "-keypass test12 -genkeypair -alias p3 -dname CN=olala3"); |
| // cannot provide keypass for PKCS11 |
| testFail("test12\n", p11Arg + |
| "-keypass nonsense -genkeypair -alias p3 -dname CN=olala3"); |
| |
| testOK("", p11Arg + "-storepass test12 -list"); |
| assertTrue(out.indexOf("Your keystore contains 2 entries") != -1, |
| "2 entries in p11"); |
| |
| testOK("test12\n", p11Arg + "-alias p1 -changealias -destalias p3"); |
| testOK("", p11Arg + "-storepass test12 -list -alias p3"); |
| testFail("", p11Arg + "-storepass test12 -list -alias p1"); |
| |
| testOK("test12\n", p11Arg + "-alias p3 -keyclone -destalias p1"); |
| // in PKCS11, keyclone will delete old |
| testFail("", p11Arg + "-storepass test12 -list -alias p3"); |
| testOK("", p11Arg + "-storepass test12 -list -alias p1"); |
| |
| // cannot change password for PKCS11 |
| testFail("test12\n", p11Arg + "-alias p1 -keypasswd -new another"); |
| |
| testOK("", p11Arg + "-storepass test12 -list"); |
| assertTrue(out.indexOf("Your keystore contains 2 entries") != -1, |
| "2 entries in p11"); |
| |
| testOK("", p11Arg + "-storepass test12 -delete -alias p1"); |
| testOK("", p11Arg + "-storepass test12 -delete -alias p2"); |
| |
| testOK("", p11Arg + "-storepass test12 -list"); |
| assertTrue(out.indexOf("Your keystore contains 0 entries") != -1, |
| "*** MAKE SURE YOU HAVE NO ENTRIES IN YOUR PKCS11 KEYSTORE" + |
| " BEFORE THIS TEST ***"); |
| } |
| |
| void testPKCS11ImportKeyStore() throws Exception { |
| |
| KeyStore ks; |
| testOK("", p11Arg + |
| "-storepass test12 -genkeypair -alias p1 -dname CN=olala"); |
| testOK("test12\n", p11Arg + "-genkeypair -alias p2 -dname CN=olala2"); |
| // test importkeystore for pkcs11 |
| |
| remove("x.jks"); |
| // pkcs11 -> jks |
| testOK("changeit\nchangeit\ntest12\n", srcP11Arg + |
| ("-importkeystore -destkeystore x.jks -deststoretype JKS " + |
| "-srcalias p1")); |
| assertTrue(err.indexOf("not imported") != -1, |
| "cannot import key without destkeypass"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(!ks.containsAlias("p1"), "p1 is not imported"); |
| |
| testOK("changeit\ntest12\n", srcP11Arg + |
| ("-importkeystore -destkeystore x.jks -deststoretype JKS " + |
| "-srcalias p1 -destkeypass changeit")); |
| testOK("changeit\ntest12\n", srcP11Arg + |
| ("-importkeystore -destkeystore x.jks -deststoretype JKS " + |
| "-srcalias p2 -destkeypass changeit")); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.containsAlias("p1"), "p1 is imported"); |
| assertTrue(ks.containsAlias("p2"), "p2 is imported"); |
| // jks -> pkcs11 |
| testOK("", p11Arg + "-storepass test12 -delete -alias p1"); |
| testOK("", p11Arg + "-storepass test12 -delete -alias p2"); |
| testOK("test12\nchangeit\n", p11Arg + |
| "-importkeystore -srckeystore x.jks -srcstoretype JKS"); |
| testOK("", p11Arg + "-storepass test12 -list -alias p1"); |
| testOK("", p11Arg + "-storepass test12 -list -alias p2"); |
| testOK("", p11Arg + "-storepass test12 -list"); |
| assertTrue(out.indexOf("Your keystore contains 2 entries") != -1, |
| "2 entries in p11"); |
| // clean up |
| testOK("", p11Arg + "-storepass test12 -delete -alias p1"); |
| testOK("", p11Arg + "-storepass test12 -delete -alias p2"); |
| testOK("", p11Arg + "-storepass test12 -list"); |
| assertTrue(out.indexOf("Your keystore contains 0 entries") != -1, |
| "empty p11"); |
| |
| remove("x.jks"); |
| } |
| |
| // Selected sqeTest |
| void sqeTest() throws Exception { |
| FileOutputStream fos = new FileOutputStream("badkeystore"); |
| for (int i=0; i<100; i++) { |
| fos.write(i); |
| } |
| fos.close(); |
| |
| sqeCsrTest(); |
| sqePrintcertTest(); |
| sqeDeleteTest(); |
| sqeExportTest(); |
| sqeGenkeyTest(); |
| sqeImportTest(); |
| sqeKeyclonetest(); |
| sqeKeypasswdTest(); |
| sqeListTest(); |
| sqeSelfCertTest(); |
| sqeStorepassTest(); |
| |
| remove("badkeystore"); |
| } |
| |
| // Import: cacert, prompt, trusted, non-trusted, bad chain, not match |
| void sqeImportTest() throws Exception { |
| KeyStore ks; |
| remove("x.jks"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-exportcert -file x.jks.p1.cert"); |
| /* deleted */ testOK("", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -delete -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -file x.jks.p1.cert -noprompt"); |
| /* deleted */ testOK("", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -delete -alias mykey"); |
| testOK("yes\n", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -file x.jks.p1.cert"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(ks.containsAlias("mykey"), "imported"); |
| /* deleted */ testOK("", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -delete -alias mykey"); |
| testOK("\n", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -file x.jks.p1.cert"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(!ks.containsAlias("mykey"), "imported"); |
| testOK("no\n", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -file x.jks.p1.cert"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(!ks.containsAlias("mykey"), "imported"); |
| testFail("no\n", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -file nonexist"); |
| testFail("no\n", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -file x.jks"); |
| remove("x.jks"); |
| } |
| // keyclone: exist. nonexist err, cert err, dest exist, misc |
| void sqeKeyclonetest() throws Exception { |
| remove("x.jks"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| // new pass |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -new newpass -keyclone -dest p0"); |
| // new pass |
| testOK("\n", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -keyclone -dest p1"); |
| testOK("\n", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keyclone -dest p2"); |
| testFail("\n", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keyclone -dest p2"); |
| testFail("\n", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keyclone -dest p3 -alias noexist"); |
| // no cert |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-exportcert -file x.jks.p1.cert"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-delete -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -file x.jks.p1.cert -noprompt"); |
| // new pass |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -new newpass -keyclone -dest p0"); |
| remove("x.jks"); |
| } |
| // keypasswd: exist, short, nonexist err, cert err, misc |
| void sqeKeypasswdTest() throws Exception { |
| remove("x.jks"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -keypasswd -new newpass"); |
| /*change back*/ testOK("", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -keypass newpass -keypasswd -new changeit"); |
| testOK("newpass\nnewpass\n", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -keypass changeit -keypasswd"); |
| /*change back*/ testOK("", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -keypass newpass -keypasswd -new changeit"); |
| testOK("new\nnew\nnewpass\nnewpass\n", "-keystore x.jks " + |
| "-storetype JKS -storepass changeit -keypass changeit -keypasswd"); |
| /*change back*/ testOK("", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -keypass newpass -keypasswd -new changeit"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypasswd -new newpass"); |
| /*change back*/ testOK("", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -keypass newpass -keypasswd -new changeit"); |
| testOK("changeit\n", "-keystore x.jks -storetype JKS " + |
| "-keypasswd -new newpass"); |
| /*change back*/ testOK("", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -keypass newpass -keypasswd -new changeit"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass badpass " + |
| "-keypass changeit -keypasswd -new newpass"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass bad -keypasswd -new newpass"); |
| // no cert |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-exportcert -file x.jks.p1.cert"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-delete -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -file x.jks.p1.cert -noprompt"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -keypasswd -new newpass"); |
| // diff pass |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-delete -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass keypass -genkeypair -dname CN=olala"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypasswd -new newpass"); |
| testOK("keypass\n", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -keypasswd -new newpass"); |
| // i hate those misc test |
| remove("x.jks"); |
| } |
| // list: -f -alias, exist, nonexist err; |
| // otherwise, check all shows, -rfc shows more, and misc |
| void sqeListTest() throws Exception { |
| remove("x.jks"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit -list"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-list -alias mykey"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-list -alias notexist"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass badpass " + |
| "-list -alias mykey"); |
| // keypass ignore |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass badpass -list -alias mykey"); |
| testOK("\n", "-keystore x.jks -storetype JKS -list"); |
| assertTrue(err.indexOf("WARNING") != -1, "no storepass"); |
| testOK("changeit\n", "-keystore x.jks -storetype JKS -list"); |
| assertTrue(err.indexOf("WARNING") == -1, "has storepass"); |
| testFail("badpass\n", "-keystore x.jks -storetype JKS -list"); |
| // misc |
| testFail("", "-keystore aa\\bb//cc -storepass changeit -list"); |
| testFail("", "-keystore nonexisting -storepass changeit -list"); |
| testFail("", "-keystore badkeystore -storepass changeit -list"); |
| remove("x.jks"); |
| } |
| // selfcert: exist, non-exist err, cert err, sig, dname, wrong keypass, misc |
| void sqeSelfCertTest() throws Exception { |
| remove("x.jks"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit -selfcert"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -selfcert"); |
| // not exist |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -selfcert -alias nonexisting"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -selfcert -dname CN=NewName"); |
| // sig not compatible |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -selfcert -sigalg MD5withRSA"); |
| // bad pass |
| testFail("", "-keystore x.jks -storetype JKS -storepass wrong " + |
| "-keypass changeit -selfcert"); |
| // bad pass |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass wrong -selfcert"); |
| //misc |
| testFail("", "-keystore nonexist -storepass changeit " + |
| "-keypass changeit -selfcert"); |
| testFail("", "-keystore aa//dd\\gg -storepass changeit " + |
| "-keypass changeit -selfcert"); |
| // diff pass |
| remove("x.jks"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass keypass -genkeypair -dname CN=olala"); |
| testFail("", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -selfcert"); |
| testOK("keypass\n", "-keystore x.jks -storetype JKS " + |
| "-storepass changeit -selfcert"); |
| |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-exportcert -file x.jks.p1.cert"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-delete -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -file x.jks.p1.cert -noprompt"); |
| // certentry cannot do selfcert |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-selfcert"); |
| remove("x.jks"); |
| } |
| // storepass: bad old, short new, misc |
| void sqeStorepassTest() throws Exception { |
| remove("x.jks"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| // all in arg |
| testOK("", "-storepasswd -keystore x.jks -storetype JKS " + |
| "-storepass changeit -new newstore"); |
| /* Change back */ testOK("", "-storepasswd -keystore x.jks" + |
| " -storetype JKS -storepass newstore -new changeit"); |
| // all not in arg, new twice |
| testOK("changeit\nnewstore\nnewstore\n", "-storepasswd " + |
| "-keystore x.jks -storetype JKS"); |
| /* Change back */ testOK("", "-storepasswd -keystore x.jks " + |
| "-storetype JKS -storepass newstore -new changeit"); |
| // new in arg |
| testOK("changeit\n", "-storepasswd -keystore x.jks " + |
| "-storetype JKS -new newstore"); |
| /* Change back */ testOK("", "-storepasswd -keystore x.jks " + |
| "-storetype JKS -storepass newstore -new changeit"); |
| // old in arg |
| testOK("newstore\nnewstore\n", "-storepasswd -keystore x.jks " + |
| "-storetype JKS -storepass changeit"); |
| /* Change back */ testOK("", "-storepasswd -keystore x.jks " + |
| "-storetype JKS -storepass newstore -new changeit"); |
| // old in arg |
| testOK("new\nnew\nnewstore\nnewstore\n", "-storepasswd " + |
| "-keystore x.jks -storetype JKS -storepass changeit"); |
| /* Change back */ testOK("", "-storepasswd -keystore x.jks " + |
| "-storetype JKS -storepass newstore -new changeit"); |
| // bad old |
| testFail("", "-storepasswd -keystore x.jks -storetype JKS " + |
| "-storepass badold -new newstore"); |
| // short new |
| testFail("", "-storepasswd -keystore x.jks -storetype JKS " + |
| "-storepass changeit -new new"); |
| // misc |
| // non exist |
| testFail("", "-storepasswd -keystore nonexist " + |
| "-storepass changeit -new newstore"); |
| // bad file |
| testFail("", "-storepasswd -keystore badkeystore " + |
| "-storepass changeit -new newstore"); |
| // bad file |
| testFail("", "-storepasswd -keystore aa\\bb//cc//dd " + |
| "-storepass changeit -new newstore"); |
| remove("x.jks"); |
| } |
| |
| void sqeGenkeyTest() throws Exception { |
| |
| remove("x.jks"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -alias newentry"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -alias newentry"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keyalg DSA " + |
| "-alias n1"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA " + |
| "-alias n2"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala " + |
| "-keyalg NoSuchAlg -alias n3"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keysize 56 " + |
| "-alias n4"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keysize 999 " + |
| "-alias n5"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keysize 512 " + |
| "-alias n6"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keysize 1024 " + |
| "-alias n7"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala " + |
| "-sigalg NoSuchAlg -alias n8"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA " + |
| "-sigalg MD2withRSA -alias n9"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA " + |
| "-sigalg MD5withRSA -alias n10"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA " + |
| "-sigalg SHA1withRSA -alias n11"); |
| testFail("", "-keystore aa\\bb//cc\\dd -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA " + |
| "-sigalg NoSuchAlg -alias n12"); |
| testFail("", "-keystore badkeystore -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala " + |
| "-alias n14"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass badpass " + |
| "-keypass changeit -genkeypair -dname CN=olala -alias n16"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CNN=olala -alias n17"); |
| remove("x.jks"); |
| } |
| |
| void sqeExportTest() throws Exception { |
| remove("x.jks"); |
| // nonexist |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-export -file mykey.cert -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-export -file mykey.cert -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-delete -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-import -file mykey.cert -noprompt -alias c1"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-export -file mykey.cert2 -alias c1"); |
| testFail("", "-keystore aa\\bb//cc\\dd -storepass changeit " + |
| "-export -file mykey.cert2 -alias c1"); |
| testFail("", "-keystore nonexistkeystore -storepass changeit " + |
| "-export -file mykey.cert2 -alias c1"); |
| testFail("", "-keystore badkeystore -storepass changeit " + |
| "-export -file mykey.cert2 -alias c1"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass badpass " + |
| "-export -file mykey.cert2 -alias c1"); |
| remove("mykey.cert"); |
| remove("mykey.cert2"); |
| remove("x.jks"); |
| } |
| |
| void sqeDeleteTest() throws Exception { |
| remove("x.jks"); |
| // nonexist |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-delete -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-delete -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| // keystore name illegal |
| testFail("", "-keystore aa\\bb//cc\\dd -storepass changeit " + |
| "-delete -alias mykey"); |
| // keystore not exist |
| testFail("", "-keystore nonexistkeystore -storepass changeit " + |
| "-delete -alias mykey"); |
| // keystore invalid |
| testFail("", "-keystore badkeystore -storepass changeit " + |
| "-delete -alias mykey"); |
| // wrong pass |
| testFail("", "-keystore x.jks -storetype JKS -storepass xxxxxxxx " + |
| "-delete -alias mykey"); |
| remove("x.jks"); |
| } |
| |
| void sqeCsrTest() throws Exception { |
| remove("x.jks"); |
| remove("x.jks.p1.cert"); |
| remove("csr1"); |
| // PrivateKeyEntry can do certreq |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keysize 1024"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-certreq -file csr1 -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-certreq -file csr1"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-certreq -file csr1 -sigalg SHA1withDSA"); |
| // unmatched sigalg |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-certreq -file csr1 -sigalg MD5withRSA"); |
| // misc test |
| // bad storepass |
| testFail("", "-keystore x.jks -storetype JKS -storepass badstorepass " + |
| "-certreq -file csr1"); |
| // storepass from terminal |
| testOK("changeit\n", "-keystore x.jks -storetype JKS " + |
| "-certreq -file csr1"); |
| // must provide storepass |
| testFail("\n", "-keystore x.jks -storetype JKS " + |
| "-certreq -file csr1"); |
| // bad keypass |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass badkeypass -certreq -file csr1"); |
| // bad filepath |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-certreq -file aa\\bb//cc\\dd"); |
| // non-existing keystore |
| testFail("", "-keystore noexistks -storepass changeit " + |
| "-certreq -file csr1"); |
| // Try the RSA private key |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-delete -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-certreq -file csr1 -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-certreq -file csr1"); |
| // unmatched sigalg |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-certreq -file csr1 -sigalg SHA1withDSA"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-certreq -file csr1 -sigalg MD5withRSA"); |
| // TrustedCertificateEntry cannot do certreq |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-exportcert -file x.jks.p1.cert"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-delete -alias mykey"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-importcert -file x.jks.p1.cert -noprompt"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-certreq -file csr1 -alias mykey"); |
| testFail("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-certreq -file csr1"); |
| remove("x.jks"); |
| remove("x.jks.p1.cert"); |
| remove("csr1"); |
| } |
| |
| void sqePrintcertTest() throws Exception { |
| remove("x.jks"); |
| remove("mykey.cert"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -genkeypair -dname CN=olala"); |
| testOK("", "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-export -file mykey.cert -alias mykey"); |
| testFail("", "-printcert -file badkeystore"); |
| testFail("", "-printcert -file a/b/c/d"); |
| testOK("", "-printcert -file mykey.cert"); |
| FileInputStream fin = new FileInputStream("mykey.cert"); |
| testOK(fin, "-printcert"); |
| fin.close(); |
| remove("x.jks"); |
| remove("mykey.cert"); |
| } |
| |
| void v3extTest(String keyAlg) throws Exception { |
| KeyStore ks; |
| remove("x.jks"); |
| String simple = "-keystore x.jks -storetype JKS -storepass changeit " + |
| "-keypass changeit -noprompt -keyalg " + keyAlg + " "; |
| String pre = simple + "-genkeypair -dname CN=Olala -alias "; |
| |
| // Version and SKID |
| testOK("", pre + "o1"); |
| |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(((X509Certificate)ks.getCertificate("o1")).getVersion() == 3); |
| assertTrue(((X509CertImpl)ks.getCertificate("o1")) |
| .getSubjectKeyIdentifierExtension() != null); |
| |
| // BC |
| testOK("", pre + "b1 -ext BC:critical"); |
| testOK("", pre + "b2 -ext BC"); |
| testOK("", pre + "b3 -ext bc"); |
| testOK("", pre + "b4 -ext BasicConstraints"); |
| testOK("", pre + "b5 -ext basicconstraints"); |
| testOK("", pre + "b6 -ext BC=ca:true,pathlen:12"); |
| testOK("", pre + "b7 -ext BC=ca:false"); |
| testOK("", pre + "b8 -ext BC:critical=ca:false"); |
| testOK("", pre + "b9 -ext BC=12"); |
| |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(((X509CertImpl)ks.getCertificate("b1")) |
| .getBasicConstraintsExtension().isCritical()); |
| assertTrue(!((X509CertImpl)ks.getCertificate("b2")) |
| .getBasicConstraintsExtension().isCritical()); |
| assertTrue(((X509CertImpl)ks.getCertificate("b8")) |
| .getBasicConstraintsExtension().isCritical()); |
| assertTrue(((X509Certificate)ks.getCertificate("b1")) |
| .getBasicConstraints() == Integer.MAX_VALUE); |
| assertTrue(((X509Certificate)ks.getCertificate("b2")) |
| .getBasicConstraints() == Integer.MAX_VALUE); |
| assertTrue(((X509Certificate)ks.getCertificate("b3")) |
| .getBasicConstraints() == Integer.MAX_VALUE); |
| assertTrue(((X509Certificate)ks.getCertificate("b4")) |
| .getBasicConstraints() == Integer.MAX_VALUE); |
| assertTrue(((X509Certificate)ks.getCertificate("b5")) |
| .getBasicConstraints() == Integer.MAX_VALUE); |
| assertTrue(((X509Certificate)ks.getCertificate("b6")) |
| .getBasicConstraints() == 12); |
| assertTrue(((X509Certificate)ks.getCertificate("b7")) |
| .getBasicConstraints() == -1); |
| assertTrue(((X509Certificate)ks.getCertificate("b9")) |
| .getBasicConstraints() == 12); |
| |
| // KU |
| testOK("", pre + "ku1 -ext KeyUsage:critical=digitalsignature"); |
| testOK("", pre + "ku2 -ext KU=digitalSignature"); |
| testOK("", pre + "ku3 -ext KU=ds"); |
| testOK("", pre + "ku4 -ext KU=dig"); |
| // ambigous value |
| testFail("", pre + "ku5 -ext KU=d"); |
| // cRLSign cannot be cs |
| testFail("", pre + "ku6 -ext KU=cs"); |
| testOK("", pre + "ku11 -ext KU=nr"); |
| // ke also means keyAgreement |
| testFail("", pre + "ku12 -ext KU=ke"); |
| testOK("", pre + "ku12 -ext KU=keyE"); |
| // de also means decipherOnly |
| testFail("", pre + "ku13 -ext KU=de"); |
| testOK("", pre + "ku13 -ext KU=dataE"); |
| testOK("", pre + "ku14 -ext KU=ka"); |
| testOK("", pre + "ku15 -ext KU=kcs"); |
| testOK("", pre + "ku16 -ext KU=crls"); |
| testOK("", pre + "ku17 -ext KU=eo"); |
| testOK("", pre + "ku18 -ext KU=do"); |
| testOK("", pre + "ku19 -ext KU=cc"); |
| |
| testOK("", pre + "ku017 -ext KU=ds,cc,eo"); |
| testOK("", pre + "ku135 -ext KU=nr,dataEncipherment,keyCertSign"); |
| testOK("", pre + "ku246 -ext KU=keyEnc,cRL,keyA"); |
| testOK("", pre + "ku1234 -ext KU=ka,da,keyE,nonR"); |
| |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| class CheckKU { |
| void check(KeyStore ks, String alias, int... pos) throws Exception { |
| System.err.print("x"); |
| boolean[] bs = ((X509Certificate)ks.getCertificate(alias)) |
| .getKeyUsage(); |
| bs = Arrays.copyOf(bs, 9); |
| for (int i=0; i<bs.length; i++) { |
| boolean found = false; |
| for (int p: pos) { |
| if (p == i) found = true; |
| } |
| if (!found ^ bs[i]) { |
| // OK |
| } else { |
| throw new RuntimeException("KU not match at " + i + |
| ": " + found + " vs " + bs[i]); |
| } |
| } |
| } |
| } |
| CheckKU c = new CheckKU(); |
| assertTrue(((X509CertImpl)ks.getCertificate("ku1")) |
| .getExtension(PKIXExtensions.KeyUsage_Id).isCritical()); |
| assertTrue(!((X509CertImpl)ks.getCertificate("ku2")) |
| .getExtension(PKIXExtensions.KeyUsage_Id).isCritical()); |
| c.check(ks, "ku1", 0); |
| c.check(ks, "ku2", 0); |
| c.check(ks, "ku3", 0); |
| c.check(ks, "ku4", 0); |
| c.check(ks, "ku11", 1); |
| c.check(ks, "ku12", 2); |
| c.check(ks, "ku13", 3); |
| c.check(ks, "ku14", 4); |
| c.check(ks, "ku15", 5); |
| c.check(ks, "ku16", 6); |
| c.check(ks, "ku17", 7); |
| c.check(ks, "ku18", 8); |
| c.check(ks, "ku19", 1); |
| c.check(ks, "ku11", 1); |
| c.check(ks, "ku11", 1); |
| c.check(ks, "ku11", 1); |
| c.check(ks, "ku017", 0, 1, 7); |
| c.check(ks, "ku135", 1, 3, 5); |
| c.check(ks, "ku246", 6, 2, 4); |
| c.check(ks, "ku1234", 1, 2, 3, 4); |
| |
| // EKU |
| testOK("", pre + "eku1 -ext EKU:critical=sa"); |
| testOK("", pre + "eku2 -ext ExtendedKeyUsage=ca"); |
| testOK("", pre + "eku3 -ext EKU=cs"); |
| testOK("", pre + "eku4 -ext EKU=ep"); |
| testOK("", pre + "eku8 -ext EKU=ts"); |
| testFail("", pre + "eku9 -ext EKU=os"); |
| testOK("", pre + "eku9 -ext EKU=ocsps"); |
| testOK("", pre + "eku10 -ext EKU=any"); |
| testOK("", pre + "eku11 -ext EKU=1.2.3.4,1.3.5.7,ep"); |
| testFail("", pre + "eku12 -ext EKU=c"); |
| testFail("", pre + "eku12 -ext EKU=nothing"); |
| |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| class CheckEKU { |
| void check(KeyStore ks, String alias, String... pos) throws Exception { |
| System.err.print("x"); |
| List<String> bs = ((X509Certificate)ks.getCertificate(alias)) |
| .getExtendedKeyUsage(); |
| int found = 0; |
| for (String p: pos) { |
| if (bs.contains(p)) { |
| found++; |
| } else { |
| throw new RuntimeException("EKU: not included " + p); |
| } |
| } |
| if (found != bs.size()) { |
| throw new RuntimeException("EKU: more items than expected"); |
| } |
| } |
| } |
| CheckEKU cx = new CheckEKU(); |
| assertTrue(((X509CertImpl)ks.getCertificate("eku1")) |
| .getExtension(PKIXExtensions.ExtendedKeyUsage_Id).isCritical()); |
| assertTrue(!((X509CertImpl)ks.getCertificate("eku2")) |
| .getExtension(PKIXExtensions.ExtendedKeyUsage_Id).isCritical()); |
| cx.check(ks, "eku1", "1.3.6.1.5.5.7.3.1"); |
| cx.check(ks, "eku2", "1.3.6.1.5.5.7.3.2"); |
| cx.check(ks, "eku3", "1.3.6.1.5.5.7.3.3"); |
| cx.check(ks, "eku4", "1.3.6.1.5.5.7.3.4"); |
| cx.check(ks, "eku8", "1.3.6.1.5.5.7.3.8"); |
| cx.check(ks, "eku9", "1.3.6.1.5.5.7.3.9"); |
| cx.check(ks, "eku10", "2.5.29.37.0"); |
| cx.check(ks, "eku11", "1.3.6.1.5.5.7.3.4", "1.2.3.4", "1.3.5.7"); |
| |
| // SAN |
| testOK("", pre+"san1 -ext san:critical=email:me@me.org"); |
| testOK("", pre+"san2 -ext san=uri:http://me.org"); |
| testOK("", pre+"san3 -ext san=dns:me.org"); |
| testOK("", pre+"san4 -ext san=ip:192.168.0.1"); |
| testOK("", pre+"san5 -ext san=oid:1.2.3.4"); |
| testOK("", pre+"san235 -ext san=uri:http://me.org,dns:me.org,oid:1.2.3.4"); |
| |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| class CheckSAN { |
| // Please sort items with name type |
| void check(KeyStore ks, String alias, int type, Object... items) |
| throws Exception { |
| int pos = 0; |
| System.err.print("x"); |
| Object[] names = null; |
| if (type == 0) names = ((X509Certificate)ks.getCertificate(alias)) |
| .getSubjectAlternativeNames().toArray(); |
| else names = ((X509Certificate)ks.getCertificate(alias)) |
| .getIssuerAlternativeNames().toArray(); |
| Arrays.sort(names, new Comparator() { |
| public int compare(Object o1, Object o2) { |
| int i1 = (Integer)((List)o1).get(0); |
| int i2 = (Integer)((List)o2).get(0); |
| return i1 - i2; |
| } |
| }); |
| for (Object o: names) { |
| List l = (List)o; |
| for (Object o2: l) { |
| if (!items[pos++].equals(o2)) { |
| throw new RuntimeException("Not equals at " + pos |
| + ": " + items[pos-1] + " vs " + o2); |
| } |
| } |
| } |
| if (pos != items.length) { |
| throw new RuntimeException("Extra items, pos is " + pos); |
| } |
| } |
| } |
| CheckSAN csan = new CheckSAN(); |
| assertTrue(((X509CertImpl)ks.getCertificate("san1")) |
| .getSubjectAlternativeNameExtension().isCritical()); |
| assertTrue(!((X509CertImpl)ks.getCertificate("san2")) |
| .getSubjectAlternativeNameExtension().isCritical()); |
| csan.check(ks, "san1", 0, 1, "me@me.org"); |
| csan.check(ks, "san2", 0, 6, "http://me.org"); |
| csan.check(ks, "san3", 0, 2, "me.org"); |
| csan.check(ks, "san4", 0, 7, "192.168.0.1"); |
| csan.check(ks, "san5", 0, 8, "1.2.3.4"); |
| csan.check(ks, "san235", 0, 2, "me.org", 6, "http://me.org", 8, "1.2.3.4"); |
| |
| // IAN |
| testOK("", pre+"ian1 -ext ian:critical=email:me@me.org"); |
| testOK("", pre+"ian2 -ext ian=uri:http://me.org"); |
| testOK("", pre+"ian3 -ext ian=dns:me.org"); |
| testOK("", pre+"ian4 -ext ian=ip:192.168.0.1"); |
| testOK("", pre+"ian5 -ext ian=oid:1.2.3.4"); |
| testOK("", pre+"ian235 -ext ian=uri:http://me.org,dns:me.org,oid:1.2.3.4"); |
| |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(((X509CertImpl)ks.getCertificate("ian1")) |
| .getIssuerAlternativeNameExtension().isCritical()); |
| assertTrue(!((X509CertImpl)ks.getCertificate("ian2")) |
| .getIssuerAlternativeNameExtension().isCritical()); |
| csan.check(ks, "ian1", 1, 1, "me@me.org"); |
| csan.check(ks, "ian2", 1, 6, "http://me.org"); |
| csan.check(ks, "ian3", 1, 2, "me.org"); |
| csan.check(ks, "ian4", 1, 7, "192.168.0.1"); |
| csan.check(ks, "ian5", 1, 8, "1.2.3.4"); |
| csan.check(ks, "ian235", 1, 2, "me.org", 6, "http://me.org", 8, "1.2.3.4"); |
| |
| // SIA |
| testOK("", pre+"sia1 -ext sia=care:uri:ldap://ca.com/cn=CA"); |
| testOK("", pre+"sia2 -ext sia=ts:email:ts@ca.com"); |
| testFail("SIA never critical", pre + |
| "sia3 -ext sia:critical=ts:email:ts@ca.com"); |
| |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| class CheckSia { |
| void check(KeyStore ks, String alias, int type, Object... items) |
| throws Exception { |
| int pos = 0; |
| System.err.print("x"); |
| AccessDescription[] ads = null; |
| if (type == 0) { |
| SubjectInfoAccessExtension siae = (SubjectInfoAccessExtension) |
| ((X509CertImpl)ks.getCertificate(alias)) |
| .getExtension(PKIXExtensions.SubjectInfoAccess_Id); |
| ads = siae.getAccessDescriptions() |
| .toArray(new AccessDescription[0]); |
| } else { |
| AuthorityInfoAccessExtension aiae = |
| (AuthorityInfoAccessExtension) |
| ((X509CertImpl)ks.getCertificate(alias)) |
| .getExtension(PKIXExtensions.AuthInfoAccess_Id); |
| ads = aiae.getAccessDescriptions() |
| .toArray(new AccessDescription[0]); |
| } |
| Arrays.sort(ads, new Comparator<AccessDescription>() { |
| @Override |
| public int compare(AccessDescription o1, |
| AccessDescription o2) { |
| return o1.getAccessMethod().toString() |
| .compareTo(o2.getAccessMethod().toString()); |
| } |
| }); |
| for (AccessDescription ad: ads) { |
| if (!ad.getAccessMethod().equals(items[pos++]) || |
| !new Integer(ad.getAccessLocation().getType()) |
| .equals(items[pos++])) { |
| throw new RuntimeException("Not same type at " + pos); |
| } |
| String name = null; |
| switch (ad.getAccessLocation().getType()) { |
| case 1: |
| name = ((RFC822Name)ad.getAccessLocation() |
| .getName()).getName(); |
| break; |
| case 6: |
| name = ((URIName)ad.getAccessLocation() |
| .getName()).getURI().toString(); |
| break; |
| default: |
| throw new RuntimeException("Not implemented: " + ad); |
| } |
| if (!name.equals(items[pos++])) { |
| throw new Exception("Name not same for " + ad + |
| " at pos " + pos); |
| } |
| } |
| } |
| } |
| CheckSia csia = new CheckSia(); |
| assertTrue(!((X509CertImpl)ks.getCertificate("sia1")) |
| .getExtension(PKIXExtensions.SubjectInfoAccess_Id).isCritical()); |
| csia.check(ks, "sia1", 0, |
| AccessDescription.Ad_CAREPOSITORY_Id, 6, "ldap://ca.com/cn=CA"); |
| csia.check(ks, "sia2", |
| 0, AccessDescription.Ad_TIMESTAMPING_Id, 1, "ts@ca.com"); |
| |
| // AIA |
| testOK("", pre+"aia1 -ext aia=cai:uri:ldap://ca.com/cn=CA"); |
| testOK("", pre+"aia2 -ext aia=ocsp:email:ocsp@ca.com"); |
| testFail("AIA never critical", pre + |
| "aia3 -ext aia:critical=ts:email:ts@ca.com"); |
| |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| assertTrue(!((X509CertImpl)ks.getCertificate("aia1")) |
| .getExtension(PKIXExtensions.AuthInfoAccess_Id).isCritical()); |
| csia.check(ks, "aia1", 1, |
| AccessDescription.Ad_CAISSUERS_Id, 6, "ldap://ca.com/cn=CA"); |
| csia.check(ks, "aia2", 1, |
| AccessDescription.Ad_OCSP_Id, 1, "ocsp@ca.com"); |
| |
| // OID |
| testOK("", pre+"oid1 -ext 1.2.3:critical=0102"); |
| testOK("", pre+"oid2 -ext 1.2.3"); |
| testOK("", pre+"oid12 -ext 1.2.3 -ext 1.2.4=01:02:03"); |
| |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| class CheckOid { |
| void check(KeyStore ks, String alias, String oid, byte[] value) |
| throws Exception { |
| int pos = 0; |
| System.err.print("x"); |
| Extension ex = ((X509CertImpl)ks.getCertificate(alias)) |
| .getExtension(new ObjectIdentifier(oid)); |
| if (!Arrays.equals(value, ex.getValue())) { |
| throw new RuntimeException("Not same content in " + |
| alias + " for " + oid); |
| } |
| } |
| } |
| CheckOid coid = new CheckOid(); |
| assertTrue(((X509CertImpl)ks.getCertificate("oid1")) |
| .getExtension(new ObjectIdentifier("1.2.3")).isCritical()); |
| assertTrue(!((X509CertImpl)ks.getCertificate("oid2")) |
| .getExtension(new ObjectIdentifier("1.2.3")).isCritical()); |
| coid.check(ks, "oid1", "1.2.3", new byte[]{1,2}); |
| coid.check(ks, "oid2", "1.2.3", new byte[]{}); |
| coid.check(ks, "oid12", "1.2.3", new byte[]{}); |
| coid.check(ks, "oid12", "1.2.4", new byte[]{1,2,3}); |
| |
| // honored |
| testOK("", pre+"ca"); |
| testOK("", pre+"a"); |
| // request: BC,KU,1.2.3,1.2.4,1.2.5 |
| testOK("", simple+"-alias a -certreq " + |
| "-ext BC=1 -ext KU=crl " + |
| "-ext 1.2.3=01 -ext 1.2.4:critical=0102 -ext 1.2.5=010203 " + |
| "-rfc -file test.req"); |
| // printcertreq |
| testOK("", "-printcertreq -file test.req"); |
| // issue: deny KU, change criticality of 1.2.3 and 1.2.4, |
| // change content of BC, add 2.3.4 |
| testOK("", simple+"-gencert -alias ca -infile test.req -ext " + |
| "honored=all,-KU,1.2.3:critical,1.2.4:non-critical " + |
| "-ext BC=2 -ext 2.3.4=01020304 " + |
| "-debug -rfc -outfile test.cert"); |
| testOK("", simple+"-importcert -file test.cert -alias a"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| X509CertImpl a = (X509CertImpl)ks.getCertificate("a"); |
| assertTrue(a.getAuthorityKeyIdentifierExtension() != null); |
| assertTrue(a.getSubjectKeyIdentifierExtension() != null); |
| assertTrue(a.getKeyUsage() == null); |
| assertTrue(a.getExtension(new ObjectIdentifier("1.2.3")).isCritical()); |
| assertTrue(!a.getExtension(new ObjectIdentifier("1.2.4")).isCritical()); |
| assertTrue(!a.getExtension(new ObjectIdentifier("1.2.5")).isCritical()); |
| assertTrue(a.getExtensionValue("1.2.3").length == 3); |
| assertTrue(a.getExtensionValue("1.2.4").length == 4); |
| assertTrue(a.getExtensionValue("1.2.5").length == 5); |
| assertTrue(a.getBasicConstraints() == 2); |
| assertTrue(!a.getExtension(new ObjectIdentifier("2.3.4")).isCritical()); |
| assertTrue(a.getExtensionValue("2.3.4").length == 6); |
| |
| // 8073181: keytool -ext honored not working correctly |
| testOK("", simple+"-gencert -alias ca -infile test.req -ext " + |
| "honored=1.2.3,KU,1.2.4:critical " + |
| "-debug -rfc -outfile test2.cert"); |
| testOK("", simple+"-importcert -file test2.cert -alias b"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| X509CertImpl b = (X509CertImpl)ks.getCertificate("b"); |
| assertTrue(!b.getExtension(new ObjectIdentifier("1.2.3")).isCritical()); |
| assertTrue(b.getExtension(new ObjectIdentifier("1.2.4")).isCritical()); |
| |
| // 8073182: keytool may generate duplicate extensions |
| testOK("", pre+"dup -ext bc=2 -ext 2.5.29.19=30030101FF -ext bc=3"); |
| ks = loadStore("x.jks", "changeit", "JKS"); |
| X509CertImpl dup = (X509CertImpl)ks.getCertificate("dup"); |
| assertTrue(dup.getBasicConstraints() == 3); |
| |
| remove("x.jks"); |
| remove("test.req"); |
| remove("test.cert"); |
| } |
| |
| void i18nTest() throws Exception { |
| // 1. keytool -help |
| remove("x.jks"); |
| testOK("", "-help"); |
| |
| // 2. keytool -genkey -v -keysize 512 Enter "a" for the keystore |
| // password. Check error (password too short). Enter "password" for |
| // the keystore password. Hit 'return' for "first and last name", |
| // "organizational unit", "City", "State", and "Country Code". |
| // Type "yes" when they ask you if everything is correct. |
| // Type 'return' for new key password. |
| testOK("a\npassword\npassword\nMe\nHere\nNow\nPlace\nPlace\nUS\nyes\n\n", |
| "-genkey -v -keysize 512 -keystore x.jks -storetype JKS"); |
| // 3. keytool -list -v -storepass password |
| testOK("", "-list -v -storepass password -keystore x.jks -storetype JKS"); |
| // 4. keytool -list -v Type "a" for the keystore password. |
| // Check error (wrong keystore password). |
| testFail("a\n", "-list -v -keystore x.jks -storetype JKS"); |
| assertTrue(ex.indexOf("password was incorrect") != -1); |
| // 5. keytool -genkey -v -keysize 512 Enter "password" as the password. |
| // Check error (alias 'mykey' already exists). |
| testFail("password\n", "-genkey -v -keysize 512" + |
| " -keystore x.jks -storetype JKS"); |
| assertTrue(ex.indexOf("alias <mykey> already exists") != -1); |
| // 6. keytool -genkey -v -keysize 512 -alias mykey2 -storepass password |
| // Hit 'return' for "first and last name", "organizational unit", "City", |
| // "State", and "Country Code". Type "yes" when they ask you if |
| // everything is correct. Type 'return' for new key password. |
| testOK("\n\n\n\n\n\nyes\n\n", "-genkey -v -keysize 512 -alias mykey2" + |
| " -storepass password -keystore x.jks -storetype JKS"); |
| // 7. keytool -list -v Type 'password' for the store password. |
| testOK("password\n", "-list -v -keystore x.jks -storetype JKS"); |
| // 8. keytool -keypasswd -v -alias mykey2 -storepass password |
| // Type "a" for the new key password. Type "aaaaaa" for the new key |
| // password. Type "bbbbbb" when re-entering the new key password. |
| // Type "a" for the new key password. Check Error (too many failures). |
| testFail("a\naaaaaa\nbbbbbb\na\n", "-keypasswd -v -alias mykey2" + |
| " -storepass password -keystore x.jks -storetype JKS"); |
| assertTrue(ex.indexOf("Too many failures - try later") != -1); |
| // 9. keytool -keypasswd -v -alias mykey2 -storepass password |
| // Type "aaaaaa" for the new key password. Type "aaaaaa" |
| // when re-entering the new key password. |
| testOK("aaaaaa\naaaaaa\n", "-keypasswd -v -alias mykey2 " + |
| "-storepass password -keystore x.jks -storetype JKS"); |
| // 10. keytool -selfcert -v -alias mykey -storepass password |
| testOK("", "-selfcert -v -alias mykey -storepass password " + |
| "-keystore x.jks -storetype JKS"); |
| // 11. keytool -list -v -storepass password |
| testOK("", "-list -v -storepass password -keystore x.jks -storetype JKS"); |
| // 12. keytool -export -v -alias mykey -file cert -storepass password |
| remove("cert"); |
| testOK("", "-export -v -alias mykey -file cert -storepass password " + |
| "-keystore x.jks -storetype JKS"); |
| // 13. keytool -import -v -file cert -storepass password |
| // Check error (Certificate reply and cert are the same) |
| testFail("", "-import -v -file cert -storepass password" + |
| " -keystore x.jks -storetype JKS"); |
| assertTrue(ex.indexOf("Certificate reply and certificate" + |
| " in keystore are identical") != -1); |
| // 14. keytool -printcert -file cert |
| testOK("", "-printcert -file cert -keystore x.jks -storetype JKS"); |
| remove("cert"); |
| // 15. keytool -list -storepass password -provider sun.security.provider.Sun |
| testOK("", "-list -storepass password" + |
| " -provider sun.security.provider.Sun" + |
| " -keystore x.jks -storetype JKS"); |
| |
| //Error tests |
| |
| // 1. keytool -storepasswd -storepass password -new abc |
| // Check error (password too short) |
| testFail("", "-storepasswd -storepass password -new abc"); |
| assertTrue(ex.indexOf("New password must be at least 6 characters") != -1); |
| // Changed, no NONE needed now |
| // 2. keytool -list -storetype PKCS11 Check error (-keystore must be NONE) |
| //testFail("", "-list -storetype PKCS11"); |
| //assertTrue(err.indexOf("keystore must be NONE") != -1); |
| // 3. keytool -storepasswd -storetype PKCS11 -keystore NONE |
| // Check error (unsupported operation) |
| testFail("", "-storepasswd -storetype PKCS11 -keystore NONE"); |
| assertTrue(ex.indexOf("UnsupportedOperationException") != -1); |
| // 4. keytool -keypasswd -storetype PKCS11 -keystore NONE |
| // Check error (unsupported operation) |
| testFail("", "-keypasswd -storetype PKCS11 -keystore NONE"); |
| assertTrue(ex.indexOf("UnsupportedOperationException") != -1); |
| // 5. keytool -list -protected -storepass password |
| // Check error (password can not be specified with -protected) |
| testFail("", "-list -protected -storepass password " + |
| "-keystore x.jks -storetype JKS"); |
| assertTrue(ex.indexOf("if -protected is specified, then") != -1); |
| // 6. keytool -keypasswd -protected -keypass password |
| // Check error (password can not be specified with -protected) |
| testFail("", "-keypasswd -protected -keypass password " + |
| "-keystore x.jks -storetype JKS"); |
| assertTrue(ex.indexOf("if -protected is specified, then") != -1); |
| // 7. keytool -keypasswd -protected -new password |
| // Check error (password can not be specified with -protected) |
| testFail("", "-keypasswd -protected -new password " + |
| "-keystore x.jks -storetype JKS"); |
| assertTrue(ex.indexOf("if -protected is specified, then") != -1); |
| remove("x.jks"); |
| } |
| |
| void i18nPKCS11Test() throws Exception { |
| //PKCS#11 tests |
| |
| // 1. sccs edit cert8.db key3.db |
| //Runtime.getRuntime().exec("/usr/ccs/bin/sccs edit cert8.db key3.db"); |
| testOK("", p11Arg + ("-storepass test12 -genkey -alias genkey" + |
| " -dname cn=genkey -keysize 512 -keyalg rsa")); |
| testOK("", p11Arg + "-storepass test12 -list"); |
| testOK("", p11Arg + "-storepass test12 -list -alias genkey"); |
| testOK("", p11Arg + |
| "-storepass test12 -certreq -alias genkey -file genkey.certreq"); |
| testOK("", p11Arg + |
| "-storepass test12 -export -alias genkey -file genkey.cert"); |
| testOK("", "-printcert -file genkey.cert"); |
| testOK("", p11Arg + |
| "-storepass test12 -selfcert -alias genkey -dname cn=selfCert"); |
| testOK("", p11Arg + |
| "-storepass test12 -list -alias genkey -v"); |
| assertTrue(out.indexOf("Owner: CN=selfCert") != -1); |
| //(check that cert subject DN is [cn=selfCert]) |
| testOK("", p11Arg + "-storepass test12 -delete -alias genkey"); |
| testOK("", p11Arg + "-storepass test12 -list"); |
| assertTrue(out.indexOf("Your keystore contains 0 entries") != -1); |
| //(check for empty database listing) |
| //Runtime.getRuntime().exec("/usr/ccs/bin/sccs unedit cert8.db key3.db"); |
| remove("genkey.cert"); |
| remove("genkey.certreq"); |
| // 12. sccs unedit cert8.db key3.db |
| } |
| |
| // tesing new option -srcProviderName |
| void sszzTest() throws Exception { |
| testAnyway("", NSS_P11_ARG+"-delete -alias nss -storepass test12"); |
| testAnyway("", NZZ_P11_ARG+"-delete -alias nss -storepass test12"); |
| testOK("", NSS_P11_ARG+"-genkeypair -dname CN=NSS " + |
| "-alias nss -storepass test12"); |
| testOK("", NSS_SRC_P11_ARG + NZZ_P11_ARG + |
| "-importkeystore -srcstorepass test12 -deststorepass test12"); |
| testAnyway("", NSS_P11_ARG+"-delete -alias nss -storepass test12"); |
| testAnyway("", NZZ_P11_ARG+"-delete -alias nss -storepass test12"); |
| } |
| |
| public static void main(String[] args) throws Exception { |
| Locale reservedLocale = Locale.getDefault(); |
| try { |
| // first test if HumanInputStream really acts like a human being |
| HumanInputStream.test(); |
| KeyToolTest t = new KeyToolTest(); |
| |
| if (System.getProperty("file") != null) { |
| t.sqeTest(); |
| t.testAll(); |
| t.i18nTest(); |
| t.v3extTest("RSA"); |
| t.v3extTest("DSA"); |
| boolean testEC = true; |
| try { |
| KeyPairGenerator.getInstance("EC"); |
| } catch (NoSuchAlgorithmException nae) { |
| testEC = false; |
| } |
| if (testEC) t.v3extTest("EC"); |
| } |
| |
| if (System.getProperty("nss") != null) { |
| t.srcP11Arg = NSS_SRC_P11_ARG; |
| t.p11Arg = NSS_P11_ARG; |
| |
| t.testPKCS11(); |
| |
| // FAIL: |
| // 1. we still don't have srcprovidername yet |
| // 2. cannot store privatekey into NSS keystore |
| // java.security.KeyStoreException: sun.security.pkcs11 |
| // .wrapper.PKCS11Exception: CKR_TEMPLATE_INCOMPLETE. |
| //t.testPKCS11ImportKeyStore(); |
| |
| t.i18nPKCS11Test(); |
| //FAIL: currently PKCS11-NSS does not support |
| // 2 NSS KeyStores to be loaded at the same time |
| //t.sszzTest(); |
| } |
| |
| if (System.getProperty("solaris") != null) { |
| // For Solaris Cryptography Framework |
| t.srcP11Arg = SUN_SRC_P11_ARG; |
| t.p11Arg = SUN_P11_ARG; |
| t.testPKCS11(); |
| t.testPKCS11ImportKeyStore(); |
| t.i18nPKCS11Test(); |
| } |
| |
| System.out.println("Test pass!!!"); |
| } finally { |
| // restore the reserved locale |
| Locale.setDefault(reservedLocale); |
| } |
| } |
| } |
| |
| class TestException extends Exception { |
| public TestException(String e) { |
| super(e); |
| } |
| } |
| |
| /** |
| * HumanInputStream tries to act like a human sitting in front of a computer |
| * terminal typing on the keyboard while the keytool program is running. |
| * |
| * keytool has called InputStream.read() and BufferedReader.readLine() in |
| * various places. a call to B.readLine() will try to buffer as much input as |
| * possible. Thus, a trivial InputStream will find it impossible to feed |
| * anything to I.read() after a B.readLine() call. |
| * |
| * This is why i create HumanInputStream, which will only send a single line |
| * to B.readLine(), no more, no less, and the next I.read() can have a chance |
| * to read the exact character right after "\n". |
| * |
| * I don't know why HumanInputStream works. |
| */ |
| class HumanInputStream extends InputStream { |
| byte[] src; |
| int pos; |
| int length; |
| boolean inLine; |
| int stopIt; |
| |
| public HumanInputStream(String input) { |
| src = input.getBytes(); |
| pos = 0; |
| length = src.length; |
| stopIt = 0; |
| inLine = false; |
| } |
| |
| // the trick: when called through read(byte[], int, int), |
| // return -1 twice after "\n" |
| |
| @Override public int read() throws IOException { |
| int re; |
| if(pos < length) { |
| re = src[pos]; |
| if(inLine) { |
| if(stopIt > 0) { |
| stopIt--; |
| re = -1; |
| } else { |
| if(re == '\n') { |
| stopIt = 2; |
| } |
| pos++; |
| } |
| } else { |
| pos++; |
| } |
| } else { |
| re = -1;//throw new IOException("NO MORE TO READ"); |
| } |
| //if (re < 32) System.err.printf("[%02d]", re); |
| //else System.err.printf("[%c]", (char)re); |
| return re; |
| } |
| @Override public int read(byte[] buffer, int offset, int len) { |
| inLine = true; |
| try { |
| int re = super.read(buffer, offset, len); |
| return re; |
| } catch(Exception e) { |
| throw new RuntimeException("HumanInputStream error"); |
| } finally { |
| inLine = false; |
| } |
| } |
| @Override public int available() { |
| if(pos < length) return 1; |
| return 0; |
| } |
| |
| // test part |
| static void assertTrue(boolean bool) { |
| if(!bool) |
| throw new RuntimeException(); |
| } |
| |
| public static void test() throws Exception { |
| |
| class Tester { |
| HumanInputStream is; |
| BufferedReader reader; |
| Tester(String s) { |
| is = new HumanInputStream(s); |
| reader = new BufferedReader(new InputStreamReader(is)); |
| } |
| |
| // three kinds of test method |
| // 1. read byte by byte from InputStream |
| void testStreamReadOnce(int expection) throws Exception { |
| assertTrue(is.read() == expection); |
| } |
| void testStreamReadMany(String expection) throws Exception { |
| char[] keys = expection.toCharArray(); |
| for(int i=0; i<keys.length; i++) { |
| assertTrue(is.read() == keys[i]); |
| } |
| } |
| // 2. read a line with a newly created Reader |
| void testReaderReadline(String expection) throws Exception { |
| String s = new BufferedReader(new InputStreamReader(is)).readLine(); |
| if(s == null) assertTrue(expection == null); |
| else assertTrue(s.equals(expection)); |
| } |
| // 3. read a line with the old Reader |
| void testReaderReadline2(String expection) throws Exception { |
| String s = reader.readLine(); |
| if(s == null) assertTrue(expection == null); |
| else assertTrue(s.equals(expection)); |
| } |
| } |
| |
| Tester test; |
| |
| test = new Tester("111\n222\n\n444\n\n"); |
| test.testReaderReadline("111"); |
| test.testReaderReadline("222"); |
| test.testReaderReadline(""); |
| test.testReaderReadline("444"); |
| test.testReaderReadline(""); |
| test.testReaderReadline(null); |
| |
| test = new Tester("111\n222\n\n444\n\n"); |
| test.testReaderReadline2("111"); |
| test.testReaderReadline2("222"); |
| test.testReaderReadline2(""); |
| test.testReaderReadline2("444"); |
| test.testReaderReadline2(""); |
| test.testReaderReadline2(null); |
| |
| test = new Tester("111\n222\n\n444\n\n"); |
| test.testReaderReadline2("111"); |
| test.testReaderReadline("222"); |
| test.testReaderReadline2(""); |
| test.testReaderReadline2("444"); |
| test.testReaderReadline(""); |
| test.testReaderReadline2(null); |
| |
| test = new Tester("1\n2"); |
| test.testStreamReadMany("1\n2"); |
| test.testStreamReadOnce(-1); |
| |
| test = new Tester("12\n234"); |
| test.testStreamReadOnce('1'); |
| test.testReaderReadline("2"); |
| test.testStreamReadOnce('2'); |
| test.testReaderReadline2("34"); |
| test.testReaderReadline2(null); |
| |
| test = new Tester("changeit\n"); |
| test.testStreamReadMany("changeit\n"); |
| test.testReaderReadline(null); |
| |
| test = new Tester("changeit\nName\nCountry\nYes\n"); |
| test.testStreamReadMany("changeit\n"); |
| test.testReaderReadline("Name"); |
| test.testReaderReadline("Country"); |
| test.testReaderReadline("Yes"); |
| test.testReaderReadline(null); |
| |
| test = new Tester("Me\nHere\n"); |
| test.testReaderReadline2("Me"); |
| test.testReaderReadline2("Here"); |
| } |
| } |