/*
* Copyright (c) 2005, 2009, 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.tools.KeyTool;
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 cmd
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 KeyTool.main() method will
// never block at user input
// use -debug so that KeyTool.main() will throw an Exception
// instead of calling System.exit()
KeyTool.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 {
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) {
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 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");
}
// The sqeTest reflects the test suggested by judy.gao and bill.situ at
// /net/sqesvr-nfs/global/nfs/sec/ws_6.0_int/security/src/SecurityTools/Keytool
//
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 -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.jks -storepass changeit -exportcert -file x.jks.p1.cert");
/* deleted */ testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert -noprompt");
/* deleted */ testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
testOK("yes\n", "-keystore x.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 -storepass changeit -delete -alias mykey");
testOK("\n", "-keystore x.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 -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 -storepass changeit -importcert -file nonexist");
testFail("no\n", "-keystore x.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 -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -new newpass -keyclone -dest p0"); // new pass
testOK("\n", "-keystore x.jks -storepass changeit -keypass changeit -keyclone -dest p1"); // new pass
testOK("\n", "-keystore x.jks -storepass changeit -keyclone -dest p2");
testFail("\n", "-keystore x.jks -storepass changeit -keyclone -dest p2");
testFail("\n", "-keystore x.jks -storepass changeit -keyclone -dest p3 -alias noexist");
// no cert
testOK("", "-keystore x.jks -storepass changeit -exportcert -file x.jks.p1.cert");
testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert -noprompt");
testFail("", "-keystore x.jks -storepass changeit -keypass changeit -new newpass -keyclone -dest p0"); // new pass
remove("x.jks");
}
// keypasswd: exist, short, nonexist err, cert err, misc
void sqeKeypasswdTest() throws Exception {
remove("x.jks");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -keypasswd -new newpass");
/*change back*/ testOK("", "-keystore x.jks -storepass changeit -keypass newpass -keypasswd -new changeit");
testOK("newpass\nnewpass\n", "-keystore x.jks -storepass changeit -keypass changeit -keypasswd");
/*change back*/ testOK("", "-keystore x.jks -storepass changeit -keypass newpass -keypasswd -new changeit");
testOK("new\nnew\nnewpass\nnewpass\n", "-keystore x.jks -storepass changeit -keypass changeit -keypasswd");
/*change back*/ testOK("", "-keystore x.jks -storepass changeit -keypass newpass -keypasswd -new changeit");
testOK("", "-keystore x.jks -storepass changeit -keypasswd -new newpass");
/*change back*/ testOK("", "-keystore x.jks -storepass changeit -keypass newpass -keypasswd -new changeit");
testOK("changeit\n", "-keystore x.jks -keypasswd -new newpass");
/*change back*/ testOK("", "-keystore x.jks -storepass changeit -keypass newpass -keypasswd -new changeit");
testFail("", "-keystore x.jks -storepass badpass -keypass changeit -keypasswd -new newpass");
testFail("", "-keystore x.jks -storepass changeit -keypass bad -keypasswd -new newpass");
// no cert
testOK("", "-keystore x.jks -storepass changeit -exportcert -file x.jks.p1.cert");
testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert -noprompt");
testFail("", "-keystore x.jks -storepass changeit -keypass changeit -keypasswd -new newpass");
// diff pass
testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -keypass keypass -genkeypair -dname CN=olala");
testFail("", "-keystore x.jks -storepass changeit -keypasswd -new newpass");
testOK("keypass\n", "-keystore x.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 -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.jks -storepass changeit -list");
testOK("", "-keystore x.jks -storepass changeit -list -alias mykey");
testFail("", "-keystore x.jks -storepass changeit -list -alias notexist");
testFail("", "-keystore x.jks -storepass badpass -list -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -keypass badpass -list -alias mykey"); // keypass ignore
testOK("\n", "-keystore x.jks -list");
assertTrue(err.indexOf("WARNING") != -1, "no storepass");
testOK("changeit\n", "-keystore x.jks -list");
assertTrue(err.indexOf("WARNING") == -1, "has storepass");
testFail("badpass\n", "-keystore x.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 -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.jks -storepass changeit -selfcert");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -selfcert");
testFail("", "-keystore x.jks -storepass changeit -keypass changeit -selfcert -alias nonexisting"); // not exist
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -selfcert -dname CN=NewName");
testFail("", "-keystore x.jks -storepass changeit -keypass changeit -selfcert -sigalg MD5withRSA"); // sig not compatible
testFail("", "-keystore x.jks -storepass wrong -keypass changeit -selfcert"); // bad pass
testFail("", "-keystore x.jks -storepass changeit -keypass wrong -selfcert"); // bad pass
//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 -storepass changeit -keypass keypass -genkeypair -dname CN=olala");
testFail("", "-keystore x.jks -storepass changeit -selfcert");
testOK("keypass\n", "-keystore x.jks -storepass changeit -selfcert");
testOK("", "-keystore x.jks -storepass changeit -exportcert -file x.jks.p1.cert");
testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert -noprompt");
testFail("", "-keystore x.jks -storepass changeit -selfcert"); // certentry cannot do selfcert
remove("x.jks");
}
// storepass: bad old, short new, misc
void sqeStorepassTest() throws Exception {
remove("x.jks");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-storepasswd -keystore x.jks -storepass changeit -new newstore"); // all in arg
/* Change back */ testOK("", "-storepasswd -keystore x.jks -storepass newstore -new changeit");
testOK("changeit\nnewstore\nnewstore\n", "-storepasswd -keystore x.jks"); // all not in arg, new twice
/* Change back */ testOK("", "-storepasswd -keystore x.jks -storepass newstore -new changeit");
testOK("changeit\n", "-storepasswd -keystore x.jks -new newstore"); // new in arg
/* Change back */ testOK("", "-storepasswd -keystore x.jks -storepass newstore -new changeit");
testOK("newstore\nnewstore\n", "-storepasswd -keystore x.jks -storepass changeit"); // old in arg
/* Change back */ testOK("", "-storepasswd -keystore x.jks -storepass newstore -new changeit");
testOK("new\nnew\nnewstore\nnewstore\n", "-storepasswd -keystore x.jks -storepass changeit"); // old in arg
/* Change back */ testOK("", "-storepasswd -keystore x.jks -storepass newstore -new changeit");
testFail("", "-storepasswd -keystore x.jks -storepass badold -new newstore"); // bad old
testFail("", "-storepasswd -keystore x.jks -storepass changeit -new new"); // short new
// misc
testFail("", "-storepasswd -keystore nonexist -storepass changeit -new newstore"); // non exist
testFail("", "-storepasswd -keystore badkeystore -storepass changeit -new newstore"); // bad file
testFail("", "-storepasswd -keystore aa\\bb//cc//dd -storepass changeit -new newstore"); // bad file
remove("x.jks");
}
void sqeGenkeyTest() throws Exception {
remove("x.jks");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -alias newentry");
testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -alias newentry");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg DSA -alias n1");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg RSA -alias n2");
testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg NoSuchAlg -alias n3");
testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keysize 56 -alias n4");
testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keysize 999 -alias n5");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keysize 512 -alias n6");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keysize 1024 -alias n7");
testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -sigalg NoSuchAlg -alias n8");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg RSA -sigalg MD2withRSA -alias n9");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg RSA -sigalg MD5withRSA -alias n10");
testOK("", "-keystore x.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 -storepass badpass -keypass changeit -genkeypair -dname CN=olala -alias n16");
testFail("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CNN=olala -alias n17");
remove("x.jks");
}
void sqeExportTest() throws Exception {
remove("x.jks");
testFail("", "-keystore x.jks -storepass changeit -export -file mykey.cert -alias mykey"); // nonexist
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.jks -storepass changeit -export -file mykey.cert -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -import -file mykey.cert -noprompt -alias c1");
testOK("", "-keystore x.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 -storepass badpass -export -file mykey.cert2 -alias c1");
remove("mykey.cert");
remove("mykey.cert2");
remove("x.jks");
}
void sqeDeleteTest() throws Exception {
remove("x.jks");
testFail("", "-keystore x.jks -storepass changeit -delete -alias mykey"); // nonexist
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testFail("", "-keystore aa\\bb//cc\\dd -storepass changeit -delete -alias mykey"); // keystore name illegal
testFail("", "-keystore nonexistkeystore -storepass changeit -delete -alias mykey"); // keystore not exist
testFail("", "-keystore badkeystore -storepass changeit -delete -alias mykey"); // keystore invalid
testFail("", "-keystore x.jks -storepass xxxxxxxx -delete -alias mykey"); // wrong pass
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 -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1 -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1");
testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1 -sigalg SHA1withDSA");
testFail("", "-keystore x.jks -storepass changeit -certreq -file csr1 -sigalg MD5withRSA"); // unmatched sigalg
// misc test
testFail("", "-keystore x.jks -storepass badstorepass -certreq -file csr1"); // bad storepass
testOK("changeit\n", "-keystore x.jks -certreq -file csr1"); // storepass from terminal
testFail("\n", "-keystore x.jks -certreq -file csr1"); // must provide storepass
testFail("", "-keystore x.jks -storepass changeit -keypass badkeypass -certreq -file csr1"); // bad keypass
testFail("", "-keystore x.jks -storepass changeit -certreq -file aa\\bb//cc\\dd"); // bad filepath
testFail("", "-keystore noexistks -storepass changeit -certreq -file csr1"); // non-existing keystore
// Try the RSA private key
testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keyalg RSA");
testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1 -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1");
testFail("", "-keystore x.jks -storepass changeit -certreq -file csr1 -sigalg SHA1withDSA"); // unmatched sigalg
testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1 -sigalg MD5withRSA");
// TrustedCertificateEntry cannot do certreq
testOK("", "-keystore x.jks -storepass changeit -exportcert -file x.jks.p1.cert");
testOK("", "-keystore x.jks -storepass changeit -delete -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -importcert -file x.jks.p1.cert -noprompt");
testFail("", "-keystore x.jks -storepass changeit -certreq -file csr1 -alias mykey");
testFail("", "-keystore x.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 -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.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 -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");
testFail("", pre + "ku5 -ext KU=d"); // ambigous value
testFail("", pre + "ku6 -ext KU=cs"); // cRLSign cannot be cs
testOK("", pre + "ku11 -ext KU=nr");
testFail("", pre + "ku12 -ext KU=ke"); // ke also means keyAgreement
testOK("", pre + "ku12 -ext KU=keyE");
testFail("", pre + "ku13 -ext KU=de"); // de also means decipherOnly
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 = ((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() {
@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);
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");
// 3. keytool -list -v -storepass password
testOK("", "-list -v -storepass password -keystore x.jks");
// 4. keytool -list -v Type "a" for the keystore password. Check error (wrong keystore password).
testFail("a\n", "-list -v -keystore x.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");
assertTrue(ex.indexOf("alias 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");
// 7. keytool -list -v Type 'password' for the store password.
testOK("password\n", "-list -v -keystore x.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");
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");
// 10. keytool -selfcert -v -alias mykey -storepass password
testOK("", "-selfcert -v -alias mykey -storepass password -keystore x.jks");
// 11. keytool -list -v -storepass password
testOK("", "-list -v -storepass password -keystore x.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");
// 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");
assertTrue(ex.indexOf("Certificate reply and certificate in keystore are identical") != -1);
// 14. keytool -printcert -file cert
testOK("", "-printcert -file cert -keystore x.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");
//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");
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");
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");
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 {
// 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!!!");
}
}
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