1/*
2 * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 *
26 *
27 * @summary Testing keytool
28 * @author weijun.wang
29 *
30 * Run through autotest.sh and manualtest.sh
31 *
32 * Testing non-PKCS11 keystores:
33 *       echo | java -Dfile KeyToolTest
34 *
35 * Testing NSS PKCS11 keystores:
36 *       # testing NSS
37 *       # make sure the NSS db files are in current directory and writable
38 *       echo | java -Dnss -Dnss.lib=/path/to/libsoftokn3.so KeyToolTest
39 *
40 * Testing Solaris Cryptography Framework PKCS11 keystores:
41 *       # make sure you've already run pktool and set test12 as pin
42 *       echo | java -Dsolaris KeyToolTest
43 *
44 * ATTENTION:
45 * Exception in thread "main" java.security.ProviderException:
46 *   sun.security.pkcs11.wrapper.PKCS11Exception: CKR_KEY_SIZE_RANGE
47 *       at sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:420)
48 *       ...
49 * Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_KEY_SIZE_RANGE
50 *       at sun.security.pkcs11.wrapper.PKCS11.C_SignFinal(Native Method)
51 *       at sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:391)
52 *       ...
53 * been observed. Possibly a Solaris bug
54 *
55 * ATTENTION:
56 * NSS PKCS11 config file are changed, DSA not supported now.
57 */
58
59import java.nio.file.Files;
60import java.nio.file.Paths;
61import java.security.KeyStore;
62import sun.security.x509.*;
63import java.io.*;
64import java.security.KeyPairGenerator;
65import java.security.NoSuchAlgorithmException;
66import java.util.*;
67import java.security.cert.X509Certificate;
68import sun.security.util.ObjectIdentifier;
69
70public class KeyToolTest {
71
72    // The stdout and stderr outputs after a keytool run
73    String out;
74    String err;
75
76    // the output of println() in KeyTool.run
77    String ex;
78
79    String lastInput = "", lastCommand = "";
80    private static final boolean debug =
81        System.getProperty("debug") != null;
82
83    static final String NSS_P11_ARG =
84            "-keystore NONE -storetype PKCS11 -providerName SunPKCS11-nss " +
85            "-addprovider SunPKCS11 " +
86            "-providerArg p11-nss.txt ";
87    // Use -providerClass here, to confirm it still works for SunPKCS11.
88    static final String NSS_SRC_P11_ARG =
89            "-srckeystore NONE -srcstoretype PKCS11 " +
90            "-srcproviderName SunPKCS11-nss " +
91            "-providerClass sun.security.pkcs11.SunPKCS11 " +
92            "-providerArg p11-nss.txt ";
93    static final String NZZ_P11_ARG =
94            "-keystore NONE -storetype PKCS11 -providerName SunPKCS11-nzz " +
95            "-addprovider SunPKCS11 " +
96            "-providerArg p11-nzz.txt ";
97    static final String NZZ_SRC_P11_ARG =
98            "-srckeystore NONE -srcstoretype PKCS11 " +
99            "-srcproviderName SunPKCS11-nzz " +
100            "-addprovider SunPKCS11 " +
101            "-providerArg p11-nzz.txt ";
102    static final String SUN_P11_ARG = "-keystore NONE -storetype PKCS11 ";
103    static final String SUN_SRC_P11_ARG =
104            "-srckeystore NONE -srcstoretype PKCS11 ";
105
106    String p11Arg, srcP11Arg;
107
108    /** Creates a new instance of KeyToolTest */
109    KeyToolTest() {
110        // so that there is "Warning" and not translated into other language
111        Locale.setDefault(Locale.US);
112    }
113
114    /**
115     * Helper, removes a file
116     */
117    void remove(String filename) {
118        if (debug) {
119            System.err.println("Removing " + filename);
120        }
121        new File(filename).delete();
122        if (new File(filename).exists()) {
123            throw new RuntimeException("Error deleting " + filename);
124        }
125    }
126
127    /**
128     * Run a set of keytool command with given terminal input.
129     * @param input the terminal inputs, the characters typed by human
130     *        if <code>cmd</code> is running on a terminal
131     * @param cmd the argument of a keytool command line
132     * @throws if keytool goes wrong in some place
133     */
134    void test(String input, String cmd) throws Exception {
135        lastInput = input;
136        lastCommand = cmd;
137
138        // "X" is appended so that we can precisely test how input is consumed
139        HumanInputStream in = new HumanInputStream(input+"X");
140        test(in, cmd);
141        // make sure the input string is no more no less
142        if(in.read() != 'X' || in.read() != -1)
143            throw new Exception("Input not consumed exactly");
144    }
145
146    void test(InputStream in, String cmd) throws Exception {
147
148        // save the original 3 streams
149        if (debug) {
150            System.err.println(cmd);
151        } else {
152            System.err.print(".");
153        }
154        PrintStream p1 = System.out;
155        PrintStream p2 = System.err;
156        InputStream i1 = System.in;
157
158        ByteArrayOutputStream b1 = new ByteArrayOutputStream();
159        ByteArrayOutputStream b2 = new ByteArrayOutputStream();
160
161        try {
162            System.setIn(in);
163            System.setOut(new PrintStream(b1));
164            System.setErr(new PrintStream(b2));
165
166            // since System.in is overrided, the
167            // sun.security.tools.keytool.Main.main() method will
168            // never block at user input
169
170            // use -debug so that main() will throw an Exception
171            // instead of calling System.exit()
172            sun.security.tools.keytool.Main.main(("-debug "+cmd).split("\\s+"));
173        } finally {
174            out = b1.toString();
175            err = b2.toString();
176            ex = out;   // now it goes to System.out
177            System.setIn(i1);
178            System.setOut(p1);
179            System.setErr(p2);
180        }
181    }
182
183    /**
184     * Call this method if you expect test(input, cmd) should go OK
185     */
186    void testOK(String input, String cmd) throws Exception {
187        try {
188            // Workaround for "8057810: Make SHA256withDSA the default
189            // jarsigner and keytool algorithm for DSA keys". Unfortunately
190            // SunPKCS11-NSS does not support SHA256withDSA yet.
191            if (cmd.contains("p11-nss.txt") && cmd.contains("-genkey")
192                    && !cmd.contains("-keyalg")) {
193                cmd += " -sigalg SHA1withDSA -keysize 1024";
194            }
195            test(input, cmd);
196        } catch(Exception e) {
197            afterFail(input, cmd, "OK");
198            throw e;
199        }
200    }
201
202    /**
203     * Call this method if you expect test(input, cmd) should fail and throw
204     * an exception
205     */
206    void testFail(String input, String cmd) throws Exception {
207        boolean ok;
208        try {
209            test(input, cmd);
210            ok = true;
211        } catch(Exception e) {
212            if (e instanceof MissingResourceException) {
213                ok = true;
214            } else {
215                ok = false;
216            }
217        }
218        if(ok) {
219            afterFail(input, cmd, "FAIL");
220            throw new RuntimeException();
221        }
222    }
223
224    /**
225     * Call this method if you expect test(input, cmd) should go OK
226     */
227    void testOK(InputStream is, String cmd) throws Exception {
228        try {
229            test(is, cmd);
230        } catch(Exception e) {
231            afterFail("", cmd, "OK");
232            throw e;
233        }
234    }
235
236    /**
237     * Call this method if you expect test(input, cmd) should fail and throw
238     * an exception
239     */
240    void testFail(InputStream is, String cmd) throws Exception {
241        boolean ok;
242        try {
243            test(is, cmd);
244            ok = true;
245        } catch(Exception e) {
246            ok = false;
247        }
248        if(ok) {
249            afterFail("", cmd, "FAIL");
250            throw new RuntimeException();
251        }
252    }
253
254    /**
255     * Call this method if you just want to run the command and does
256     * not care if it succeeds or fails.
257     */
258    void testAnyway(String input, String cmd) {
259        try {
260            test(input, cmd);
261        } catch(Exception e) {
262            ;
263        }
264    }
265
266    /**
267     * Helper method, print some output after a test does not do as expected
268     */
269    void afterFail(String input, String cmd, String should) {
270        if (cmd.contains("p11-nss.txt")) {
271            cmd = "-J-Dnss.lib=" + System.getProperty("nss.lib") + " " + cmd;
272        }
273        System.err.println("\nTest fails for the command ---\n" +
274                "keytool " + cmd + "\nOr its debug version ---\n" +
275                "keytool -debug " + cmd);
276
277        System.err.println("The command result should be " + should +
278                ", but it's not. Try run the command manually and type" +
279                " these input into it: ");
280        char[] inputChars = input.toCharArray();
281
282        for (int i=0; i<inputChars.length; i++) {
283            char ch = inputChars[i];
284            if (ch == '\n') System.err.print("ENTER ");
285            else if (ch == ' ') System.err.print("SPACE ");
286            else System.err.print(ch + " ");
287        }
288        System.err.println("");
289
290        System.err.println("ERR is:\n"+err);
291        System.err.println("OUT is:\n"+out);
292    }
293
294    void assertTrue(boolean bool, String msg) {
295        if (debug) {
296            System.err.println("If not " + bool + ", " + msg);
297        } else {
298            System.err.print("v");
299        }
300        if(!bool) {
301            afterFail(lastInput, lastCommand, "TRUE");
302                System.err.println(msg);
303            throw new RuntimeException(msg);
304        }
305    }
306
307    void assertTrue(boolean bool) {
308        assertTrue(bool, "well...");
309    }
310    /**
311     * Helper method, load a keystore
312     * @param file file for keystore, null or "NONE" for PKCS11
313     * @pass password for the keystore
314     * @type keystore type
315     * @returns the KeyStore object
316     * @exception Exception if anything goes wrong
317     */
318    KeyStore loadStore(String file, String pass, String type) throws Exception {
319        KeyStore ks = KeyStore.getInstance(type);
320        FileInputStream is = null;
321        if (file != null && !file.equals("NONE")) {
322            is = new FileInputStream(file);
323        }
324        ks.load(is, pass.toCharArray());
325        is.close();
326        return ks;
327    }
328
329    /**
330     * The test suite.
331     * Maybe it's better to put this outside the KeyToolTest class
332     */
333    void testAll() throws Exception {
334        KeyStore ks;
335
336        remove("x.jks");
337        remove("x.jceks");
338        remove("x.p12");
339        remove("x2.jceks");
340        remove("x2.jks");
341        remove("x.jks.p1.cert");
342
343        // name changes: genkeypair, importcert, exportcert
344        remove("x.jks");
345        remove("x.jks.p1.cert");
346        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
347                "-keypass changeit -genkeypair -alias p1 -dname CN=olala");
348        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
349                "-exportcert -alias p1 -file x.jks.p1.cert");
350        ks = loadStore("x.jks", "changeit", "JKS");
351        assertTrue(ks.getKey("p1", "changeit".toCharArray()) != null,
352            "key not DSA");
353        assertTrue(new File("x.jks.p1.cert").exists(), "p1 export err");
354        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
355                "-delete -alias p1");
356        // importcert, prompt for Yes/No
357        testOK("y\n", "-keystore x.jks -storetype JKS -storepass changeit " +
358                "-importcert -alias c1 -file x.jks.p1.cert");
359        // importcert, -noprompt
360        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
361                "-importcert -alias c2 -file x.jks.p1.cert -noprompt");
362        ks = loadStore("x.jks", "changeit", "JKS");
363        assertTrue(ks.getCertificate("c1") != null, "import c1 err");
364
365        // v3
366        byte[] encoded = ks.getCertificate("c1").getEncoded();
367        X509CertImpl certImpl = new X509CertImpl(encoded);
368        assertTrue(certImpl.getVersion() == 3, "Version is not 3");
369
370        // changealias and keyclone
371        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
372                "-keypass changeit -genkeypair -alias p1 -dname CN=olala");
373        testOK("changeit\n", "-keystore x.jks -storetype JKS " +
374                "-changealias -alias p1 -destalias p11");
375        testOK("changeit\n", "-keystore x.jks -storetype JKS " +
376                "-changealias -alias c1 -destalias c11");
377        // press ENTER when prompt for p111's keypass
378        testOK("changeit\n\n", "-keystore x.jks -storetype JKS " +
379                "-keyclone -alias p11 -destalias p111");
380        ks = loadStore("x.jks", "changeit", "JKS");
381        assertTrue(!ks.containsAlias("p1"), "there is no p1");
382        assertTrue(!ks.containsAlias("c1"), "there is no c1");
383        assertTrue(ks.containsAlias("p11"), "there is p11");
384        assertTrue(ks.containsAlias("c11"), "there is c11");
385        assertTrue(ks.containsAlias("p111"), "there is p111");
386
387        // genSecKey
388        remove("x.jceks");
389        // DES, no need keysize
390        testOK("changeit\nchangeit\n\n", "-keystore x.jceks -storetype JCEKS " +
391                "-genseckey -alias s1");
392        // DES, keysize cannot be 128
393        testFail("changeit\n\n", "-keystore x.jceks -storetype JCEKS " +
394                "-genseckey -alias s11 -keysize 128");
395        // DESede. no need keysize
396        testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS " +
397                "-genseckey -keyalg DESede -alias s2");
398        // AES, need keysize
399        testFail("changeit\n\n", "-keystore x.jceks -storetype AES " +
400                "-genseckey -keyalg Rijndael -alias s3");
401        testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS " +
402                "-genseckey -keyalg AES -alias s3 -keysize 128");
403        // about keypass
404        // can accept storepass
405        testOK("\n", "-keystore x.jceks -storetype JCEKS -storepass changeit " +
406                "-genseckey -alias s4");
407        // or a new one
408        testOK("keypass\nkeypass\n", "-keystore x.jceks -storetype JCEKS " +
409                "-storepass changeit -genseckey -alias s5");
410        // keypass must be valid (prompt 3 times)
411        testOK("bad\n\bad\nkeypass\nkeypass\n", "-keystore x.jceks " +
412                "-storetype JCEKS -storepass changeit -genseckey -alias s6");
413        // keypass must be valid (prompt 3 times)
414        testFail("bad\n\bad\nbad\n", "-keystore x.jceks -storetype JCEKS " +
415                "-storepass changeit -genseckey -alias s7");
416        // keypass must be valid (prompt 3 times)
417        testFail("bad\n\bad\nbad\nkeypass\n", "-keystore x.jceks " +
418                "-storetype JCEKS -storepass changeit -genseckey -alias s7");
419        ks = loadStore("x.jceks", "changeit", "JCEKS");
420        assertTrue(ks.getKey("s1", "changeit".toCharArray())
421                .getAlgorithm().equalsIgnoreCase("DES"), "s1 is DES");
422        assertTrue(ks.getKey("s1", "changeit".toCharArray())
423                .getEncoded().length == 8,  "DES is 56");
424        assertTrue(ks.getKey("s2", "changeit".toCharArray())
425                .getEncoded().length == 24,  "DESede is 168");
426        assertTrue(ks.getKey("s2", "changeit".toCharArray())
427                .getAlgorithm().equalsIgnoreCase("DESede"), "s2 is DESede");
428        assertTrue(ks.getKey("s3", "changeit".toCharArray())
429                .getAlgorithm().equalsIgnoreCase("AES"), "s3 is AES");
430        assertTrue(ks.getKey("s4", "changeit".toCharArray())
431                .getAlgorithm().equalsIgnoreCase("DES"), "s4 is DES");
432        assertTrue(ks.getKey("s5", "keypass".toCharArray())
433                .getAlgorithm().equalsIgnoreCase("DES"), "s5 is DES");
434        assertTrue(ks.getKey("s6", "keypass".toCharArray())
435                .getAlgorithm().equalsIgnoreCase("DES"), "s6 is DES");
436        assertTrue(!ks.containsAlias("s7"), "s7 not created");
437
438        // maybe we needn't test this, one day JKS will support SecretKey
439        //testFail("changeit\nchangeit\n", "-keystore x.jks -storetype JKS " +
440        //        "-genseckey -keyalg AES -alias s3 -keysize 128");
441
442        // importKeyStore
443        remove("x.jks");
444        remove("x.jceks");
445        // create 2 entries...
446        testOK("changeit\nchangeit\n\n", "-keystore x.jceks -storetype JCEKS " +
447                "-genkeypair -alias p1 -dname CN=Olala");
448        testOK("", "-keystore x.jceks -storetype JCEKS -storepass changeit " +
449                "-importcert -alias c1 -file x.jks.p1.cert -noprompt");
450        ks = loadStore("x.jceks", "changeit", "JCEKS");
451        assertTrue(ks.size() == 2, "2 entries in JCEKS");
452        // import, shouldn't mention destalias/srckeypass/destkeypass
453        // if srcalias is no given
454        testFail("changeit\nchangeit\n", "-importkeystore " +
455                "-srckeystore x.jceks -srcstoretype JCEKS " +
456                "-destkeystore x.jks -deststoretype JKS -destalias pp");
457        testFail("changeit\nchangeit\n", "-importkeystore " +
458                "-srckeystore x.jceks -srcstoretype JCEKS " +
459                "-destkeystore x.jks -deststoretype JKS -srckeypass changeit");
460        testFail("changeit\nchangeit\n", "-importkeystore " +
461                "-srckeystore x.jceks -srcstoretype JCEKS " +
462                "-destkeystore x.jks -deststoretype JKS -destkeypass changeit");
463        // normal import
464        testOK("changeit\nchangeit\nchangeit\n", "-importkeystore " +
465                "-srckeystore x.jceks -srcstoretype JCEKS " +
466                "-destkeystore x.jks -deststoretype JKS");
467        ks = loadStore("x.jks", "changeit", "JKS");
468        assertTrue(ks.size() == 2, "2 entries in JKS");
469        // import again, type yes to overwrite old entries
470        testOK("changeit\nchangeit\ny\ny\n", "-importkeystore " +
471                "-srckeystore x.jceks -srcstoretype JCEKS " +
472                "-destkeystore x.jks -deststoretype JKS");
473        ks = loadStore("x.jks", "changeit", "JKS");
474        // import again, specify -nopromt
475        testOK("changeit\nchangeit\n", "-importkeystore " +
476                "-srckeystore x.jceks -srcstoretype JCEKS " +
477                "-destkeystore x.jks -deststoretype JKS -noprompt");
478        assertTrue(err.indexOf("Warning") != -1, "noprompt will warn");
479        ks = loadStore("x.jks", "changeit", "JKS");
480        assertTrue(ks.size() == 2, "2 entries in JKS");
481        // import again, type into new aliases when prompted
482        testOK("changeit\nchangeit\n\ns1\n\ns2\n", "-importkeystore " +
483                "-srckeystore x.jceks -srcstoretype JCEKS " +
484                "-destkeystore x.jks -deststoretype JKS");
485        ks = loadStore("x.jks", "changeit", "JKS");
486        assertTrue(ks.size() == 4, "4 entries in JKS");
487
488        // importkeystore single
489        // normal
490        remove("x.jks");
491        testOK("changeit\nchangeit\nchangeit\n", "-importkeystore " +
492                "-srckeystore x.jceks -srcstoretype JCEKS " +
493                "-destkeystore x.jks -deststoretype JKS -srcalias p1");
494        ks = loadStore("x.jks", "changeit", "JKS");
495        assertTrue(ks.size() == 1, "1 entries in JKS");
496        // overwrite
497        testOK("changeit\nchangeit\ny\n", "-importkeystore " +
498                "-srckeystore x.jceks -srcstoretype JCEKS " +
499                "-destkeystore x.jks -deststoretype JKS -srcalias p1");
500        ks = loadStore("x.jks", "changeit", "JKS");
501        assertTrue(ks.size() == 1, "1 entries in JKS");
502        // noprompt
503        testOK("changeit\nchangeit\n", "-importkeystore " +
504                "-srckeystore x.jceks -srcstoretype JCEKS " +
505                "-destkeystore x.jks -deststoretype JKS " +
506                "-srcalias p1 -noprompt");
507        ks = loadStore("x.jks", "changeit", "JKS");
508        assertTrue(ks.size() == 1, "1 entries in JKS");
509        // rename
510        testOK("changeit\nchangeit\n", "-importkeystore " +
511                "-srckeystore x.jceks -srcstoretype JCEKS " +
512                "-destkeystore x.jks -deststoretype JKS " +
513                "-srcalias p1 -destalias p2");
514        ks = loadStore("x.jks", "changeit", "JKS");
515        assertTrue(ks.size() == 2, "2 entries in JKS");
516        // another rename
517        testOK("changeit\nchangeit\n\nnewalias\n", "-importkeystore " +
518                "-srckeystore x.jceks -srcstoretype JCEKS " +
519                "-destkeystore x.jks -deststoretype JKS -srcalias p1");
520        ks = loadStore("x.jks", "changeit", "JKS");
521        assertTrue(ks.size() == 3, "3 entries in JKS");
522
523        // importkeystore single, different keypass
524        remove("x.jks");
525        // generate entry with different keypass
526        testOK("changeit\nkeypass\nkeypass\n", "-keystore x.jceks " +
527                "-storetype JCEKS -genkeypair -alias p2 -dname CN=Olala");
528        // prompt
529        testOK("changeit\nchangeit\nchangeit\nkeypass\n", "-importkeystore " +
530                "-srckeystore x.jceks -srcstoretype JCEKS " +
531                "-destkeystore x.jks -deststoretype JKS -srcalias p2");
532        ks = loadStore("x.jks", "changeit", "JKS");
533        assertTrue(ks.size() == 1, "1 entries in JKS");
534        // diff destkeypass
535        testOK("changeit\nchangeit\nkeypass\n", "-importkeystore " +
536                "-srckeystore x.jceks -srcstoretype JCEKS " +
537                "-destkeystore x.jks -deststoretype JKS " +
538                "-srcalias p2 -destalias p3 -destkeypass keypass2");
539        ks = loadStore("x.jks", "changeit", "JKS");
540        assertTrue(ks.size() == 2, "2 entries in JKS");
541        assertTrue(ks.getKey("p2", "keypass".toCharArray()) != null,
542                "p2 has old password");
543        assertTrue(ks.getKey("p3", "keypass2".toCharArray()) != null,
544                "p3 has new password");
545
546        // importkeystore single, cert
547        remove("x.jks");
548        // normal
549        testOK("changeit\nchangeit\nchangeit\n", "-importkeystore " +
550                "-srckeystore x.jceks -srcstoretype JCEKS " +
551                "-destkeystore x.jks -deststoretype JKS -srcalias c1");
552        // in fact srcstorepass can be ignored
553        testOK("changeit\n\n", "-importkeystore " +
554                "-srckeystore x.jceks -srcstoretype JCEKS " +
555                "-destkeystore x.jks -deststoretype JKS " +
556                "-srcalias c1 -destalias c2");
557        assertTrue(err.indexOf("WARNING") != -1, "But will warn");
558        // 2nd import, press y to overwrite ...
559        testOK("changeit\n\ny\n", "-importkeystore " +
560                "-srckeystore x.jceks -srcstoretype JCEKS " +
561                "-destkeystore x.jks -deststoretype JKS " +
562                "-srcalias c1 -destalias c2");
563        // ... or rename
564        testOK("changeit\n\n\nc3\n", "-importkeystore " +
565                "-srckeystore x.jceks -srcstoretype JCEKS " +
566                "-destkeystore x.jks -deststoretype JKS " +
567                "-srcalias c1 -destalias c2");
568        ks = loadStore("x.jks", "changeit", "JKS");
569        // c1, c2, c3
570        assertTrue(ks.size() == 3, "3 entries in JKS");
571
572        // importkeystore, secretkey
573        remove("x.jks");
574        // create SecretKeyEntry
575        testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS " +
576                "-genseckey -alias s1");
577        // create SecretKeyEntry
578        testOK("changeit\n\n", "-keystore x.jceks -storetype JCEKS " +
579                "-genseckey -alias s2");
580        // remove the keypass!=storepass one
581        testOK("changeit\n", "-keystore x.jceks -storetype JCEKS " +
582                "-delete -alias p2");
583        ks = loadStore("x.jceks", "changeit", "JCEKS");
584        // p1, c1, s1, s2
585        assertTrue(ks.size() == 4, "4 entries in JCEKS");
586        // normal
587        testOK("changeit\nchangeit\nchangeit\n", "-importkeystore " +
588                "-srckeystore x.jceks -srcstoretype JCEKS " +
589                "-destkeystore x.jks -deststoretype JKS -srcalias s1");
590        assertTrue(err.indexOf("not imported") != -1, "Not imported");
591        assertTrue(err.indexOf("Cannot store non-PrivateKeys") != -1,
592                "Not imported");
593
594        // Importing a JCEKS keystore to a JKS one. Will warn
595        // for the 2 SecretKey entries
596
597        remove("x.jks");
598        // Two "no" answers to bypass warnings
599        // normal
600        testOK("\n\n", "-srcstorepass changeit -deststorepass changeit " +
601                "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS " +
602                "-destkeystore x.jks -deststoretype JKS");
603        assertTrue(err.indexOf("s1 not") != -1, "s1 not");
604        assertTrue(err.indexOf("s2 not") != -1, "s2 not");
605        assertTrue(err.indexOf("c1 success") != -1, "c1 success");
606        assertTrue(err.indexOf("p1 success") != -1, "p1 success");
607        remove("x.jks");
608        // One "yes" to stop
609        // normal
610        testOK("yes\n", "-srcstorepass changeit -deststorepass changeit " +
611                "-importkeystore -srckeystore x.jceks -srcstoretype JCEKS " +
612                "-destkeystore x.jks -deststoretype JKS");
613        // maybe c1 or p1 has been imported before s1 or s2 is touched,
614        // anyway we know yesNo is only asked once.
615
616        // pkcs12
617        remove("x.jks");
618        // JKS prompt for keypass
619        testFail("changeit\nchangeit\n", "-keystore x.jks -storetype JKS " +
620                "-genkeypair -alias p1 -dname CN=olala");
621        remove("x.jks");
622        // just type ENTER means keypass=storepass
623        testOK("changeit\nchangeit\n\n", "-keystore x.jks -storetype JKS " +
624                "-genkeypair -alias p1 -dname CN=olala");
625        remove("x.p12");
626        // PKCS12 only need storepass
627        testOK("", "-keystore x.p12 -storetype PKCS12 -storepass changeit " +
628                "-genkeypair -alias p0 -dname CN=olala");
629        testOK("changeit\n", "-keystore x.p12 -storetype PKCS12 " +
630                "-genkeypair -alias p1 -dname CN=olala");
631        // when specify keypass, make sure keypass==storepass...
632        testOK("changeit\n", "-keystore x.p12 -keypass changeit " +
633                "-storetype PKCS12 -genkeypair -alias p3 -dname CN=olala");
634        assertTrue(err.indexOf("Warning") == -1,
635                "PKCS12 silent when keypass == storepass");
636        // otherwise, print a warning
637        testOK("changeit\n", "-keystore x.p12 -keypass another" +
638                " -storetype PKCS12 -genkeypair -alias p2 -dname CN=olala");
639        assertTrue(err.indexOf("Warning") != -1,
640                "PKCS12 warning when keypass != storepass");
641        // no -keypasswd for PKCS12
642        testFail("", "-keystore x.p12 -storepass changeit -storetype PKCS12" +
643                " -keypasswd -new changeit -alias p3");
644        testOK("", "-keystore x.p12 -storepass changeit -storetype PKCS12 " +
645                "-changealias -alias p3 -destalias p33");
646        testOK("", "-keystore x.p12 -storepass changeit -storetype PKCS12 " +
647                "-keyclone -alias p33 -destalias p3");
648
649        // pkcs12
650        remove("x.p12");
651        // PKCS12 only need storepass
652        testOK("", "-keystore x.p12 -storetype PKCS12 -storepass changeit " +
653                "-genkeypair -alias p0 -dname CN=olala");
654        testOK("", "-storepass changeit -keystore x.p12 -storetype PKCS12 " +
655                "-genkeypair -alias p1 -dname CN=olala");
656        // when specify keypass, make sure keypass==storepass...
657        testOK("", "-storepass changeit -keystore x.p12 -keypass changeit " +
658                "-storetype PKCS12 -genkeypair -alias p3 -dname CN=olala");
659        assertTrue(err.indexOf("Warning") == -1,
660                "PKCS12 silent when keypass == storepass");
661        // otherwise, print a warning
662        testOK("", "-storepass changeit -keystore x.p12 -keypass another " +
663                "-storetype PKCS12 -genkeypair -alias p2 -dname CN=olala");
664        assertTrue(err.indexOf("Warning") != -1,
665                "PKCS12 warning when keypass != storepass");
666
667        remove("x.jks");
668        remove("x.jceks");
669        remove("x.p12");
670        remove("x2.jceks");
671        remove("x2.jks");
672        remove("x.jks.p1.cert");
673    }
674
675    void testPKCS11() throws Exception {
676        KeyStore ks;
677        // pkcs11, the password maybe different and maybe PKCS11 not supported
678
679        // in case last test is not executed successfully
680        testAnyway("", p11Arg + "-storepass test12 -delete -alias p1");
681        testAnyway("", p11Arg + "-storepass test12 -delete -alias p2");
682        testAnyway("", p11Arg + "-storepass test12 -delete -alias p3");
683        testAnyway("", p11Arg + "-storepass test12 -delete -alias nss");
684
685        testOK("", p11Arg + "-storepass test12 -list");
686        assertTrue(out.indexOf("Your keystore contains 0 entries") != -1,
687                "*** MAKE SURE YOU HAVE NO ENTRIES IN YOUR PKCS11 KEYSTORE " +
688                        "BEFORE THIS TEST ***");
689
690        testOK("", p11Arg +
691                "-storepass test12 -genkeypair -alias p1 -dname CN=olala");
692        testOK("test12\n", p11Arg + "-genkeypair -alias p2 -dname CN=olala2");
693        // cannot provide keypass for PKCS11
694        testFail("test12\n", p11Arg +
695                "-keypass test12 -genkeypair -alias p3 -dname CN=olala3");
696        // cannot provide keypass for PKCS11
697        testFail("test12\n", p11Arg +
698                "-keypass nonsense -genkeypair -alias p3 -dname CN=olala3");
699
700        testOK("", p11Arg + "-storepass test12 -list");
701        assertTrue(out.indexOf("Your keystore contains 2 entries") != -1,
702                "2 entries in p11");
703
704        testOK("test12\n", p11Arg + "-alias p1 -changealias -destalias p3");
705        testOK("", p11Arg + "-storepass test12 -list -alias p3");
706        testFail("", p11Arg + "-storepass test12 -list -alias p1");
707
708        testOK("test12\n", p11Arg + "-alias p3 -keyclone -destalias p1");
709        // in PKCS11, keyclone will delete old
710        testFail("", p11Arg + "-storepass test12 -list -alias p3");
711        testOK("", p11Arg + "-storepass test12 -list -alias p1");
712
713        // cannot change password for PKCS11
714        testFail("test12\n", p11Arg + "-alias p1 -keypasswd -new another");
715
716        testOK("", p11Arg + "-storepass test12 -list");
717        assertTrue(out.indexOf("Your keystore contains 2 entries") != -1,
718                "2 entries in p11");
719
720        testOK("", p11Arg + "-storepass test12 -delete -alias p1");
721        testOK("", p11Arg + "-storepass test12 -delete -alias p2");
722
723        testOK("", p11Arg + "-storepass test12 -list");
724        assertTrue(out.indexOf("Your keystore contains 0 entries") != -1,
725                "*** MAKE SURE YOU HAVE NO ENTRIES IN YOUR PKCS11 KEYSTORE" +
726                        " BEFORE THIS TEST ***");
727    }
728
729    void testPKCS11ImportKeyStore() throws Exception {
730
731        KeyStore ks;
732        testOK("", p11Arg +
733                "-storepass test12 -genkeypair -alias p1 -dname CN=olala");
734        testOK("test12\n", p11Arg + "-genkeypair -alias p2 -dname CN=olala2");
735        // test importkeystore for pkcs11
736
737        remove("x.jks");
738        // pkcs11 -> jks
739        testOK("changeit\nchangeit\ntest12\n", srcP11Arg +
740                ("-importkeystore -destkeystore x.jks -deststoretype JKS " +
741                "-srcalias p1"));
742        assertTrue(err.indexOf("not imported") != -1,
743                "cannot import key without destkeypass");
744        ks = loadStore("x.jks", "changeit", "JKS");
745        assertTrue(!ks.containsAlias("p1"), "p1 is not imported");
746
747        testOK("changeit\ntest12\n", srcP11Arg +
748                ("-importkeystore -destkeystore x.jks -deststoretype JKS " +
749                "-srcalias p1 -destkeypass changeit"));
750        testOK("changeit\ntest12\n", srcP11Arg +
751                ("-importkeystore -destkeystore x.jks -deststoretype JKS " +
752                "-srcalias p2 -destkeypass changeit"));
753        ks = loadStore("x.jks", "changeit", "JKS");
754        assertTrue(ks.containsAlias("p1"), "p1 is imported");
755        assertTrue(ks.containsAlias("p2"), "p2 is imported");
756        // jks -> pkcs11
757        testOK("", p11Arg + "-storepass test12 -delete -alias p1");
758        testOK("", p11Arg + "-storepass test12 -delete -alias p2");
759        testOK("test12\nchangeit\n", p11Arg +
760                "-importkeystore -srckeystore x.jks -srcstoretype JKS");
761        testOK("", p11Arg + "-storepass test12 -list -alias p1");
762        testOK("", p11Arg + "-storepass test12 -list -alias p2");
763        testOK("", p11Arg + "-storepass test12 -list");
764        assertTrue(out.indexOf("Your keystore contains 2 entries") != -1,
765                "2 entries in p11");
766        // clean up
767        testOK("", p11Arg + "-storepass test12 -delete -alias p1");
768        testOK("", p11Arg + "-storepass test12 -delete -alias p2");
769        testOK("", p11Arg + "-storepass test12 -list");
770        assertTrue(out.indexOf("Your keystore contains 0 entries") != -1,
771                "empty p11");
772
773        remove("x.jks");
774    }
775
776    // Selected sqeTest
777    void sqeTest() throws Exception {
778        FileOutputStream fos = new FileOutputStream("badkeystore");
779        for (int i=0; i<100; i++) {
780            fos.write(i);
781        }
782        fos.close();
783
784        sqeCsrTest();
785        sqePrintcertTest();
786        sqeDeleteTest();
787        sqeExportTest();
788        sqeGenkeyTest();
789        sqeImportTest();
790        sqeKeyclonetest();
791        sqeKeypasswdTest();
792        sqeListTest();
793        sqeSelfCertTest();
794        sqeStorepassTest();
795
796        remove("badkeystore");
797    }
798
799    // Import: cacert, prompt, trusted, non-trusted, bad chain, not match
800    void sqeImportTest() throws Exception {
801        KeyStore ks;
802        remove("x.jks");
803        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
804                "-keypass changeit -genkeypair -dname CN=olala");
805        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
806                "-exportcert -file x.jks.p1.cert");
807        /* deleted */ testOK("", "-keystore x.jks -storetype JKS " +
808                "-storepass changeit -delete -alias mykey");
809        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
810                "-importcert -file x.jks.p1.cert -noprompt");
811        /* deleted */ testOK("", "-keystore x.jks -storetype JKS " +
812                "-storepass changeit -delete -alias mykey");
813        testOK("yes\n", "-keystore x.jks -storetype JKS -storepass changeit " +
814                "-importcert -file x.jks.p1.cert");
815        ks = loadStore("x.jks", "changeit", "JKS");
816        assertTrue(ks.containsAlias("mykey"), "imported");
817        /* deleted */ testOK("", "-keystore x.jks -storetype JKS " +
818                "-storepass changeit -delete -alias mykey");
819        testOK("\n", "-keystore x.jks -storetype JKS -storepass changeit " +
820                "-importcert -file x.jks.p1.cert");
821        ks = loadStore("x.jks", "changeit", "JKS");
822        assertTrue(!ks.containsAlias("mykey"), "imported");
823        testOK("no\n", "-keystore x.jks -storetype JKS -storepass changeit " +
824                "-importcert -file x.jks.p1.cert");
825        ks = loadStore("x.jks", "changeit", "JKS");
826        assertTrue(!ks.containsAlias("mykey"), "imported");
827        testFail("no\n", "-keystore x.jks -storetype JKS -storepass changeit " +
828                "-importcert -file nonexist");
829        testFail("no\n", "-keystore x.jks -storetype JKS -storepass changeit " +
830                "-importcert -file x.jks");
831        remove("x.jks");
832    }
833    // keyclone: exist. nonexist err, cert err, dest exist, misc
834    void sqeKeyclonetest() throws Exception {
835        remove("x.jks");
836        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
837                "-keypass changeit -genkeypair -dname CN=olala");
838        // new pass
839        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
840                "-keypass changeit -new newpass -keyclone -dest p0");
841        // new pass
842        testOK("\n", "-keystore x.jks -storetype JKS -storepass changeit " +
843                "-keypass changeit -keyclone -dest p1");
844        testOK("\n", "-keystore x.jks -storetype JKS -storepass changeit " +
845                "-keyclone -dest p2");
846        testFail("\n", "-keystore x.jks -storetype JKS -storepass changeit " +
847                "-keyclone -dest p2");
848        testFail("\n", "-keystore x.jks -storetype JKS -storepass changeit " +
849                "-keyclone -dest p3 -alias noexist");
850        // no cert
851        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
852                "-exportcert -file x.jks.p1.cert");
853        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
854                "-delete -alias mykey");
855        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
856                "-importcert -file x.jks.p1.cert -noprompt");
857        // new pass
858        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
859                "-keypass changeit -new newpass -keyclone -dest p0");
860        remove("x.jks");
861    }
862    // keypasswd: exist, short, nonexist err, cert err, misc
863    void sqeKeypasswdTest() throws Exception {
864        remove("x.jks");
865        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
866                "-keypass changeit -genkeypair -dname CN=olala");
867        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
868                "-keypass changeit -keypasswd -new newpass");
869        /*change back*/ testOK("", "-keystore x.jks -storetype JKS " +
870                "-storepass changeit -keypass newpass -keypasswd -new changeit");
871        testOK("newpass\nnewpass\n", "-keystore x.jks -storetype JKS " +
872                "-storepass changeit -keypass changeit -keypasswd");
873        /*change back*/ testOK("", "-keystore x.jks -storetype JKS " +
874                "-storepass changeit -keypass newpass -keypasswd -new changeit");
875        testOK("new\nnew\nnewpass\nnewpass\n", "-keystore x.jks " +
876                "-storetype JKS -storepass changeit -keypass changeit -keypasswd");
877        /*change back*/ testOK("", "-keystore x.jks -storetype JKS " +
878                "-storepass changeit -keypass newpass -keypasswd -new changeit");
879        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
880                "-keypasswd -new newpass");
881        /*change back*/ testOK("", "-keystore x.jks -storetype JKS " +
882                "-storepass changeit -keypass newpass -keypasswd -new changeit");
883        testOK("changeit\n", "-keystore x.jks -storetype JKS " +
884                "-keypasswd -new newpass");
885        /*change back*/ testOK("", "-keystore x.jks -storetype JKS " +
886                "-storepass changeit -keypass newpass -keypasswd -new changeit");
887        testFail("", "-keystore x.jks -storetype JKS -storepass badpass " +
888                "-keypass changeit -keypasswd -new newpass");
889        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
890                "-keypass bad -keypasswd -new newpass");
891        // no cert
892        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
893                "-exportcert -file x.jks.p1.cert");
894        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
895                "-delete -alias mykey");
896        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
897                "-importcert -file x.jks.p1.cert -noprompt");
898        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
899                "-keypass changeit -keypasswd -new newpass");
900        // diff pass
901        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
902                "-delete -alias mykey");
903        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
904                "-keypass keypass -genkeypair -dname CN=olala");
905        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
906                "-keypasswd -new newpass");
907        testOK("keypass\n", "-keystore x.jks -storetype JKS " +
908                "-storepass changeit -keypasswd -new newpass");
909        // i hate those misc test
910        remove("x.jks");
911    }
912    // list: -f -alias, exist, nonexist err;
913    // otherwise, check all shows, -rfc shows more, and misc
914    void sqeListTest() throws Exception {
915        remove("x.jks");
916        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
917                "-keypass changeit -genkeypair -dname CN=olala");
918        testOK("", "-keystore x.jks -storetype JKS -storepass changeit -list");
919        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
920                "-list -alias mykey");
921        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
922                "-list -alias notexist");
923        testFail("", "-keystore x.jks -storetype JKS -storepass badpass " +
924                "-list -alias mykey");
925        // keypass ignore
926        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
927                "-keypass badpass -list -alias mykey");
928        testOK("\n", "-keystore x.jks -storetype JKS -list");
929        assertTrue(err.indexOf("WARNING") != -1, "no storepass");
930        testOK("changeit\n", "-keystore x.jks -storetype JKS -list");
931        assertTrue(err.indexOf("WARNING") == -1, "has storepass");
932        testFail("badpass\n", "-keystore x.jks -storetype JKS -list");
933        // misc
934        testFail("", "-keystore aa\\bb//cc -storepass changeit -list");
935        testFail("", "-keystore nonexisting -storepass changeit -list");
936        testFail("", "-keystore badkeystore -storepass changeit -list");
937        remove("x.jks");
938    }
939    // selfcert: exist, non-exist err, cert err, sig, dname, wrong keypass, misc
940    void sqeSelfCertTest() throws Exception {
941        remove("x.jks");
942        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
943                "-keypass changeit -genkeypair -dname CN=olala");
944        testOK("", "-keystore x.jks -storetype JKS -storepass changeit -selfcert");
945        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
946                "-keypass changeit -selfcert");
947        // not exist
948        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
949                "-keypass changeit -selfcert -alias nonexisting");
950        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
951                "-keypass changeit -selfcert -dname CN=NewName");
952        // sig not compatible
953        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
954                "-keypass changeit -selfcert -sigalg MD5withRSA");
955        // bad pass
956        testFail("", "-keystore x.jks -storetype JKS -storepass wrong " +
957                "-keypass changeit -selfcert");
958        // bad pass
959        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
960                "-keypass wrong -selfcert");
961        //misc
962        testFail("", "-keystore nonexist -storepass changeit " +
963                "-keypass changeit -selfcert");
964        testFail("", "-keystore aa//dd\\gg -storepass changeit " +
965                "-keypass changeit -selfcert");
966        // diff pass
967        remove("x.jks");
968        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
969                "-keypass keypass -genkeypair -dname CN=olala");
970        testFail("", "-keystore x.jks -storetype JKS " +
971                "-storepass changeit -selfcert");
972        testOK("keypass\n", "-keystore x.jks -storetype JKS " +
973                "-storepass changeit -selfcert");
974
975        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
976                "-exportcert -file x.jks.p1.cert");
977        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
978                "-delete -alias mykey");
979        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
980                "-importcert -file x.jks.p1.cert -noprompt");
981        // certentry cannot do selfcert
982        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
983                "-selfcert");
984        remove("x.jks");
985    }
986    // storepass: bad old, short new, misc
987    void sqeStorepassTest() throws Exception {
988        remove("x.jks");
989        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
990                "-keypass changeit -genkeypair -dname CN=olala");
991        // all in arg
992        testOK("", "-storepasswd -keystore x.jks -storetype JKS " +
993                "-storepass changeit -new newstore");
994        /* Change back */ testOK("", "-storepasswd -keystore x.jks" +
995                " -storetype JKS -storepass newstore -new changeit");
996        // all not in arg, new twice
997        testOK("changeit\nnewstore\nnewstore\n", "-storepasswd " +
998                "-keystore x.jks -storetype JKS");
999        /* Change back */ testOK("", "-storepasswd -keystore x.jks " +
1000                "-storetype JKS -storepass newstore -new changeit");
1001        // new in arg
1002        testOK("changeit\n", "-storepasswd -keystore x.jks " +
1003                "-storetype JKS -new newstore");
1004        /* Change back */ testOK("", "-storepasswd -keystore x.jks " +
1005                "-storetype JKS -storepass newstore -new changeit");
1006        // old in arg
1007        testOK("newstore\nnewstore\n", "-storepasswd -keystore x.jks " +
1008                "-storetype JKS -storepass changeit");
1009        /* Change back */ testOK("", "-storepasswd -keystore x.jks " +
1010                "-storetype JKS -storepass newstore -new changeit");
1011        // old in arg
1012        testOK("new\nnew\nnewstore\nnewstore\n", "-storepasswd " +
1013                "-keystore x.jks -storetype JKS -storepass changeit");
1014        /* Change back */ testOK("", "-storepasswd -keystore x.jks " +
1015                "-storetype JKS -storepass newstore -new changeit");
1016        // bad old
1017        testFail("", "-storepasswd -keystore x.jks -storetype JKS " +
1018                "-storepass badold -new newstore");
1019        // short new
1020        testFail("", "-storepasswd -keystore x.jks -storetype JKS " +
1021                "-storepass changeit -new new");
1022        // misc
1023        // non exist
1024        testFail("", "-storepasswd -keystore nonexist " +
1025                "-storepass changeit -new newstore");
1026        // bad file
1027        testFail("", "-storepasswd -keystore badkeystore " +
1028                "-storepass changeit -new newstore");
1029        // bad file
1030        testFail("", "-storepasswd -keystore aa\\bb//cc//dd " +
1031                "-storepass changeit -new newstore");
1032        remove("x.jks");
1033    }
1034
1035    void sqeGenkeyTest() throws Exception {
1036
1037        remove("x.jks");
1038        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1039                "-keypass changeit -genkeypair -dname CN=olala");
1040        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1041                "-keypass changeit -genkeypair -dname CN=olala");
1042        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1043                "-keypass changeit -genkeypair -dname CN=olala -alias newentry");
1044        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1045                "-keypass changeit -genkeypair -dname CN=olala -alias newentry");
1046        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1047                "-keypass changeit -genkeypair -dname CN=olala -keyalg DSA " +
1048                "-alias n1");
1049        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1050                "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA " +
1051                "-alias n2");
1052        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1053                "-keypass changeit -genkeypair -dname CN=olala " +
1054                "-keyalg NoSuchAlg -alias n3");
1055        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1056                "-keypass changeit -genkeypair -dname CN=olala -keysize 56 " +
1057                "-alias n4");
1058        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1059                "-keypass changeit -genkeypair -dname CN=olala -keysize 999 " +
1060                "-alias n5");
1061        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1062                "-keypass changeit -genkeypair -dname CN=olala -keysize 512 " +
1063                "-alias n6");
1064        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1065                "-keypass changeit -genkeypair -dname CN=olala -keysize 1024 " +
1066                "-alias n7");
1067        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1068                "-keypass changeit -genkeypair -dname CN=olala " +
1069                "-sigalg NoSuchAlg -alias n8");
1070        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1071                "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA " +
1072                "-sigalg MD2withRSA -alias n9");
1073        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1074                "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA " +
1075                "-sigalg MD5withRSA -alias n10");
1076        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1077                "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA " +
1078                "-sigalg SHA1withRSA -alias n11");
1079        testFail("", "-keystore aa\\bb//cc\\dd -storepass changeit " +
1080                "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA " +
1081                "-sigalg NoSuchAlg -alias n12");
1082        testFail("", "-keystore badkeystore -storepass changeit " +
1083                "-keypass changeit -genkeypair -dname CN=olala " +
1084                "-alias n14");
1085        testFail("", "-keystore x.jks -storetype JKS -storepass badpass " +
1086                "-keypass changeit -genkeypair -dname CN=olala -alias n16");
1087        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1088                "-keypass changeit -genkeypair -dname CNN=olala -alias n17");
1089        remove("x.jks");
1090    }
1091
1092    void sqeExportTest() throws Exception {
1093        remove("x.jks");
1094        // nonexist
1095        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1096                "-export -file mykey.cert -alias mykey");
1097        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1098                "-keypass changeit -genkeypair -dname CN=olala");
1099        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1100                "-export -file mykey.cert -alias mykey");
1101        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1102                "-delete -alias mykey");
1103        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1104                "-import -file mykey.cert -noprompt -alias c1");
1105        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1106                "-export -file mykey.cert2 -alias c1");
1107        testFail("", "-keystore aa\\bb//cc\\dd -storepass changeit " +
1108                "-export -file mykey.cert2 -alias c1");
1109        testFail("", "-keystore nonexistkeystore -storepass changeit " +
1110                "-export -file mykey.cert2 -alias c1");
1111        testFail("", "-keystore badkeystore -storepass changeit " +
1112                "-export -file mykey.cert2 -alias c1");
1113        testFail("", "-keystore x.jks -storetype JKS -storepass badpass " +
1114                "-export -file mykey.cert2 -alias c1");
1115        remove("mykey.cert");
1116        remove("mykey.cert2");
1117        remove("x.jks");
1118    }
1119
1120    void sqeDeleteTest() throws Exception {
1121        remove("x.jks");
1122        // nonexist
1123        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1124                "-delete -alias mykey");
1125        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1126                "-keypass changeit -genkeypair -dname CN=olala");
1127        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1128                "-delete -alias mykey");
1129        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1130                "-keypass changeit -genkeypair -dname CN=olala");
1131        // keystore name illegal
1132        testFail("", "-keystore aa\\bb//cc\\dd -storepass changeit " +
1133                "-delete -alias mykey");
1134        // keystore not exist
1135        testFail("", "-keystore nonexistkeystore -storepass changeit " +
1136                "-delete -alias mykey");
1137        // keystore invalid
1138        testFail("", "-keystore badkeystore -storepass changeit " +
1139                "-delete -alias mykey");
1140        // wrong pass
1141        testFail("", "-keystore x.jks -storetype JKS -storepass xxxxxxxx " +
1142                "-delete -alias mykey");
1143        remove("x.jks");
1144    }
1145
1146    void sqeCsrTest() throws Exception {
1147        remove("x.jks");
1148        remove("x.jks.p1.cert");
1149        remove("csr1");
1150        // PrivateKeyEntry can do certreq
1151        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1152                "-keypass changeit -genkeypair -dname CN=olala -keysize 1024");
1153        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1154                "-certreq -file csr1 -alias mykey");
1155        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1156                "-certreq -file csr1");
1157        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1158                "-certreq -file csr1 -sigalg SHA1withDSA");
1159        // unmatched sigalg
1160        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1161                "-certreq -file csr1 -sigalg MD5withRSA");
1162        // misc test
1163        // bad storepass
1164        testFail("", "-keystore x.jks -storetype JKS -storepass badstorepass " +
1165                "-certreq -file csr1");
1166        // storepass from terminal
1167        testOK("changeit\n", "-keystore x.jks -storetype JKS " +
1168                "-certreq -file csr1");
1169        // must provide storepass
1170        testFail("\n", "-keystore x.jks -storetype JKS " +
1171                "-certreq -file csr1");
1172        // bad keypass
1173        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1174                "-keypass badkeypass -certreq -file csr1");
1175        // bad filepath
1176        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1177                "-certreq -file aa\\bb//cc\\dd");
1178        // non-existing keystore
1179        testFail("", "-keystore noexistks -storepass changeit " +
1180                "-certreq -file csr1");
1181        // Try the RSA private key
1182        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1183                "-delete -alias mykey");
1184        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1185                "-keypass changeit -genkeypair -dname CN=olala -keyalg RSA");
1186        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1187                "-certreq -file csr1 -alias mykey");
1188        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1189                "-certreq -file csr1");
1190        // unmatched sigalg
1191        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1192                "-certreq -file csr1 -sigalg SHA1withDSA");
1193        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1194                "-certreq -file csr1 -sigalg MD5withRSA");
1195        // TrustedCertificateEntry cannot do certreq
1196        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1197                "-exportcert -file x.jks.p1.cert");
1198        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1199                "-delete -alias mykey");
1200        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1201                "-importcert -file x.jks.p1.cert -noprompt");
1202        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1203                "-certreq -file csr1 -alias mykey");
1204        testFail("", "-keystore x.jks -storetype JKS -storepass changeit " +
1205                "-certreq -file csr1");
1206        remove("x.jks");
1207        remove("x.jks.p1.cert");
1208        remove("csr1");
1209    }
1210
1211    void sqePrintcertTest() throws Exception {
1212        remove("x.jks");
1213        remove("mykey.cert");
1214        remove("myweakkey.cert");
1215        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1216                "-keypass changeit -genkeypair -dname CN=olala");
1217        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1218                "-export -file mykey.cert -alias mykey");
1219        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1220                "-keypass changeit -genkeypair -dname CN=weak -keyalg rsa " +
1221                "-keysize 512 -sigalg MD5withRSA -alias myweakkey");
1222        testOK("", "-keystore x.jks -storetype JKS -storepass changeit " +
1223                "-export -file myweakkey.cert -alias myweakkey");
1224        testFail("", "-printcert -file badkeystore");
1225        testFail("", "-printcert -file a/b/c/d");
1226        testOK("", "-printcert -file mykey.cert");
1227        testOK("", "-printcert -file myweakkey.cert");
1228        FileInputStream fin = new FileInputStream("mykey.cert");
1229        testOK(fin, "-printcert");
1230        fin.close();
1231        remove("x.jks");
1232        remove("mykey.cert");
1233        remove("myweakkey.cert");
1234    }
1235
1236    // 8074935: jdk8 keytool doesn't validate pem files for RFC 1421 correctness
1237    static void checkPem(String file) throws Exception {
1238        boolean maybeLast = false;
1239        for (String s: Files.readAllLines(Paths.get(file))) {
1240            if (s.isEmpty()) continue;
1241            if (s.startsWith("---")) continue;
1242            if (maybeLast) {
1243                throw new Exception("Last line already seen");
1244            }
1245            if (s.length() > 64) {
1246                throw new Exception(s);
1247            }
1248            if (s.length() < 64) {
1249                maybeLast = true;
1250            }
1251        }
1252    }
1253
1254    void v3extTest(String keyAlg) throws Exception {
1255        KeyStore ks;
1256        remove("x.jks");
1257        String simple = "-keystore x.jks -storetype JKS -storepass changeit " +
1258                "-keypass changeit -noprompt -keyalg " + keyAlg + " ";
1259        String pre = simple + "-genkeypair -dname CN=Olala -alias ";
1260
1261        // Version and SKID
1262        testOK("", pre + "o1");
1263
1264        ks = loadStore("x.jks", "changeit", "JKS");
1265        assertTrue(((X509Certificate)ks.getCertificate("o1")).getVersion() == 3);
1266        assertTrue(((X509CertImpl)ks.getCertificate("o1"))
1267                .getSubjectKeyIdentifierExtension() != null);
1268
1269        // BC
1270        testOK("", pre + "b1 -ext BC:critical");
1271        testOK("", pre + "b2 -ext BC");
1272        testOK("", pre + "b3 -ext bc");
1273        testOK("", pre + "b4 -ext BasicConstraints");
1274        testOK("", pre + "b5 -ext basicconstraints");
1275        testOK("", pre + "b6 -ext BC=ca:true,pathlen:12");
1276        testOK("", pre + "b7 -ext BC=ca:false");
1277        testOK("", pre + "b8 -ext BC:critical=ca:false");
1278        testOK("", pre + "b9 -ext BC=12");
1279
1280        ks = loadStore("x.jks", "changeit", "JKS");
1281        assertTrue(((X509CertImpl)ks.getCertificate("b1"))
1282                .getBasicConstraintsExtension().isCritical());
1283        assertTrue(!((X509CertImpl)ks.getCertificate("b2"))
1284                .getBasicConstraintsExtension().isCritical());
1285        assertTrue(((X509CertImpl)ks.getCertificate("b8"))
1286                .getBasicConstraintsExtension().isCritical());
1287        assertTrue(((X509Certificate)ks.getCertificate("b1"))
1288                .getBasicConstraints() == Integer.MAX_VALUE);
1289        assertTrue(((X509Certificate)ks.getCertificate("b2"))
1290                .getBasicConstraints() == Integer.MAX_VALUE);
1291        assertTrue(((X509Certificate)ks.getCertificate("b3"))
1292                .getBasicConstraints() == Integer.MAX_VALUE);
1293        assertTrue(((X509Certificate)ks.getCertificate("b4"))
1294                .getBasicConstraints() == Integer.MAX_VALUE);
1295        assertTrue(((X509Certificate)ks.getCertificate("b5"))
1296                .getBasicConstraints() == Integer.MAX_VALUE);
1297        assertTrue(((X509Certificate)ks.getCertificate("b6"))
1298                .getBasicConstraints() == 12);
1299        assertTrue(((X509Certificate)ks.getCertificate("b7"))
1300                .getBasicConstraints() == -1);
1301        assertTrue(((X509Certificate)ks.getCertificate("b9"))
1302                .getBasicConstraints() == 12);
1303
1304        // KU
1305        testOK("", pre + "ku1 -ext KeyUsage:critical=digitalsignature");
1306        testOK("", pre + "ku2 -ext KU=digitalSignature");
1307        testOK("", pre + "ku3 -ext KU=ds");
1308        testOK("", pre + "ku4 -ext KU=dig");
1309        // ambigous value
1310        testFail("", pre + "ku5 -ext KU=d");
1311        // cRLSign cannot be cs
1312        testFail("", pre + "ku6 -ext KU=cs");
1313        testOK("", pre + "ku11 -ext KU=nr");
1314        // ke also means keyAgreement
1315        testFail("", pre + "ku12 -ext KU=ke");
1316        testOK("", pre + "ku12 -ext KU=keyE");
1317        // de also means decipherOnly
1318        testFail("", pre + "ku13 -ext KU=de");
1319        testOK("", pre + "ku13 -ext KU=dataE");
1320        testOK("", pre + "ku14 -ext KU=ka");
1321        testOK("", pre + "ku15 -ext KU=kcs");
1322        testOK("", pre + "ku16 -ext KU=crls");
1323        testOK("", pre + "ku17 -ext KU=eo");
1324        testOK("", pre + "ku18 -ext KU=do");
1325        testOK("", pre + "ku19 -ext KU=cc");
1326
1327        testOK("", pre + "ku017 -ext KU=ds,cc,eo");
1328        testOK("", pre + "ku135 -ext KU=nr,dataEncipherment,keyCertSign");
1329        testOK("", pre + "ku246 -ext KU=keyEnc,cRL,keyA");
1330        testOK("", pre + "ku1234 -ext KU=ka,da,keyE,nonR");
1331
1332        ks = loadStore("x.jks", "changeit", "JKS");
1333        class CheckKU {
1334            void check(KeyStore ks, String alias, int... pos) throws Exception {
1335                System.err.print("x");
1336                boolean[] bs = ((X509Certificate)ks.getCertificate(alias))
1337                        .getKeyUsage();
1338                bs = Arrays.copyOf(bs, 9);
1339                for (int i=0; i<bs.length; i++) {
1340                    boolean found = false;
1341                    for (int p: pos) {
1342                        if (p == i) found = true;
1343                    }
1344                    if (!found ^ bs[i]) {
1345                        // OK
1346                    } else {
1347                        throw new RuntimeException("KU not match at " + i +
1348                                ": " + found + " vs " + bs[i]);
1349                    }
1350                }
1351            }
1352        }
1353        CheckKU c = new CheckKU();
1354        assertTrue(((X509CertImpl)ks.getCertificate("ku1"))
1355                .getExtension(PKIXExtensions.KeyUsage_Id).isCritical());
1356        assertTrue(!((X509CertImpl)ks.getCertificate("ku2"))
1357                .getExtension(PKIXExtensions.KeyUsage_Id).isCritical());
1358        c.check(ks, "ku1", 0);
1359        c.check(ks, "ku2", 0);
1360        c.check(ks, "ku3", 0);
1361        c.check(ks, "ku4", 0);
1362        c.check(ks, "ku11", 1);
1363        c.check(ks, "ku12", 2);
1364        c.check(ks, "ku13", 3);
1365        c.check(ks, "ku14", 4);
1366        c.check(ks, "ku15", 5);
1367        c.check(ks, "ku16", 6);
1368        c.check(ks, "ku17", 7);
1369        c.check(ks, "ku18", 8);
1370        c.check(ks, "ku19", 1);
1371        c.check(ks, "ku11", 1);
1372        c.check(ks, "ku11", 1);
1373        c.check(ks, "ku11", 1);
1374        c.check(ks, "ku017", 0, 1, 7);
1375        c.check(ks, "ku135", 1, 3, 5);
1376        c.check(ks, "ku246", 6, 2, 4);
1377        c.check(ks, "ku1234", 1, 2, 3, 4);
1378
1379        // EKU
1380        testOK("", pre + "eku1 -ext EKU:critical=sa");
1381        testOK("", pre + "eku2 -ext ExtendedKeyUsage=ca");
1382        testOK("", pre + "eku3 -ext EKU=cs");
1383        testOK("", pre + "eku4 -ext EKU=ep");
1384        testOK("", pre + "eku8 -ext EKU=ts");
1385        testFail("", pre + "eku9 -ext EKU=os");
1386        testOK("", pre + "eku9 -ext EKU=ocsps");
1387        testOK("", pre + "eku10 -ext EKU=any");
1388        testOK("", pre + "eku11 -ext EKU=1.2.3.4,1.3.5.7,ep");
1389        testFail("", pre + "eku12 -ext EKU=c");
1390        testFail("", pre + "eku12 -ext EKU=nothing");
1391
1392        ks = loadStore("x.jks", "changeit", "JKS");
1393        class CheckEKU {
1394            void check(KeyStore ks, String alias, String... pos) throws Exception {
1395                System.err.print("x");
1396                List<String> bs = ((X509Certificate)ks.getCertificate(alias))
1397                        .getExtendedKeyUsage();
1398                int found = 0;
1399                for (String p: pos) {
1400                    if (bs.contains(p)) {
1401                        found++;
1402                    } else {
1403                        throw new RuntimeException("EKU: not included " + p);
1404                    }
1405                }
1406                if (found != bs.size()) {
1407                    throw new RuntimeException("EKU: more items than expected");
1408                }
1409            }
1410        }
1411        CheckEKU cx = new CheckEKU();
1412        assertTrue(((X509CertImpl)ks.getCertificate("eku1"))
1413                .getExtension(PKIXExtensions.ExtendedKeyUsage_Id).isCritical());
1414        assertTrue(!((X509CertImpl)ks.getCertificate("eku2"))
1415                .getExtension(PKIXExtensions.ExtendedKeyUsage_Id).isCritical());
1416        cx.check(ks, "eku1", "1.3.6.1.5.5.7.3.1");
1417        cx.check(ks, "eku2", "1.3.6.1.5.5.7.3.2");
1418        cx.check(ks, "eku3", "1.3.6.1.5.5.7.3.3");
1419        cx.check(ks, "eku4", "1.3.6.1.5.5.7.3.4");
1420        cx.check(ks, "eku8", "1.3.6.1.5.5.7.3.8");
1421        cx.check(ks, "eku9", "1.3.6.1.5.5.7.3.9");
1422        cx.check(ks, "eku10", "2.5.29.37.0");
1423        cx.check(ks, "eku11", "1.3.6.1.5.5.7.3.4", "1.2.3.4", "1.3.5.7");
1424
1425        // SAN
1426        testOK("", pre+"san1 -ext san:critical=email:me@me.org");
1427        testOK("", pre+"san2 -ext san=uri:http://me.org");
1428        testOK("", pre+"san3 -ext san=dns:me.org");
1429        testOK("", pre+"san4 -ext san=ip:192.168.0.1");
1430        testOK("", pre+"san5 -ext san=oid:1.2.3.4");
1431        testOK("", pre+"san235 -ext san=uri:http://me.org,dns:me.org,oid:1.2.3.4");
1432
1433        ks = loadStore("x.jks", "changeit", "JKS");
1434        class CheckSAN {
1435            // Please sort items with name type
1436            void check(KeyStore ks, String alias, int type, Object... items)
1437                    throws Exception {
1438                int pos = 0;
1439                System.err.print("x");
1440                Object[] names = null;
1441                if (type == 0) names = ((X509Certificate)ks.getCertificate(alias))
1442                        .getSubjectAlternativeNames().toArray();
1443                else names = ((X509Certificate)ks.getCertificate(alias))
1444                        .getIssuerAlternativeNames().toArray();
1445                Arrays.sort(names, new Comparator() {
1446                    public int compare(Object o1, Object o2) {
1447                        int i1 = (Integer)((List)o1).get(0);
1448                        int i2 = (Integer)((List)o2).get(0);
1449                        return i1 - i2;
1450                    }
1451                });
1452                for (Object o: names) {
1453                    List l = (List)o;
1454                    for (Object o2: l) {
1455                        if (!items[pos++].equals(o2)) {
1456                            throw new RuntimeException("Not equals at " + pos
1457                                    + ": " + items[pos-1] + " vs " + o2);
1458                        }
1459                    }
1460                }
1461                if (pos != items.length) {
1462                    throw new RuntimeException("Extra items, pos is " + pos);
1463                }
1464            }
1465        }
1466        CheckSAN csan = new CheckSAN();
1467        assertTrue(((X509CertImpl)ks.getCertificate("san1"))
1468                .getSubjectAlternativeNameExtension().isCritical());
1469        assertTrue(!((X509CertImpl)ks.getCertificate("san2"))
1470                .getSubjectAlternativeNameExtension().isCritical());
1471        csan.check(ks, "san1", 0, 1, "me@me.org");
1472        csan.check(ks, "san2", 0, 6, "http://me.org");
1473        csan.check(ks, "san3", 0, 2, "me.org");
1474        csan.check(ks, "san4", 0, 7, "192.168.0.1");
1475        csan.check(ks, "san5", 0, 8, "1.2.3.4");
1476        csan.check(ks, "san235", 0, 2, "me.org", 6, "http://me.org", 8, "1.2.3.4");
1477
1478        // IAN
1479        testOK("", pre+"ian1 -ext ian:critical=email:me@me.org");
1480        testOK("", pre+"ian2 -ext ian=uri:http://me.org");
1481        testOK("", pre+"ian3 -ext ian=dns:me.org");
1482        testOK("", pre+"ian4 -ext ian=ip:192.168.0.1");
1483        testOK("", pre+"ian5 -ext ian=oid:1.2.3.4");
1484        testOK("", pre+"ian235 -ext ian=uri:http://me.org,dns:me.org,oid:1.2.3.4");
1485
1486        ks = loadStore("x.jks", "changeit", "JKS");
1487        assertTrue(((X509CertImpl)ks.getCertificate("ian1"))
1488                .getIssuerAlternativeNameExtension().isCritical());
1489        assertTrue(!((X509CertImpl)ks.getCertificate("ian2"))
1490                .getIssuerAlternativeNameExtension().isCritical());
1491        csan.check(ks, "ian1", 1, 1, "me@me.org");
1492        csan.check(ks, "ian2", 1, 6, "http://me.org");
1493        csan.check(ks, "ian3", 1, 2, "me.org");
1494        csan.check(ks, "ian4", 1, 7, "192.168.0.1");
1495        csan.check(ks, "ian5", 1, 8, "1.2.3.4");
1496        csan.check(ks, "ian235", 1, 2, "me.org", 6, "http://me.org", 8, "1.2.3.4");
1497
1498        // SIA
1499        testOK("", pre+"sia1 -ext sia=care:uri:ldap://ca.com/cn=CA");
1500        testOK("", pre+"sia2 -ext sia=ts:email:ts@ca.com");
1501        testFail("SIA never critical", pre +
1502                "sia3 -ext sia:critical=ts:email:ts@ca.com");
1503
1504        ks = loadStore("x.jks", "changeit", "JKS");
1505        class CheckSia {
1506            void check(KeyStore ks, String alias, int type, Object... items)
1507                    throws Exception {
1508                int pos = 0;
1509                System.err.print("x");
1510                AccessDescription[] ads = null;
1511                if (type == 0) {
1512                    SubjectInfoAccessExtension siae = (SubjectInfoAccessExtension)
1513                            ((X509CertImpl)ks.getCertificate(alias))
1514                            .getExtension(PKIXExtensions.SubjectInfoAccess_Id);
1515                    ads = siae.getAccessDescriptions()
1516                            .toArray(new AccessDescription[0]);
1517                } else {
1518                    AuthorityInfoAccessExtension aiae =
1519                            (AuthorityInfoAccessExtension)
1520                            ((X509CertImpl)ks.getCertificate(alias))
1521                            .getExtension(PKIXExtensions.AuthInfoAccess_Id);
1522                    ads = aiae.getAccessDescriptions()
1523                            .toArray(new AccessDescription[0]);
1524                }
1525                Arrays.sort(ads, new Comparator<AccessDescription>() {
1526                    @Override
1527                    public int compare(AccessDescription o1,
1528                                       AccessDescription o2) {
1529                        return o1.getAccessMethod().toString()
1530                                .compareTo(o2.getAccessMethod().toString());
1531                    }
1532                });
1533                for (AccessDescription ad: ads) {
1534                    if (!ad.getAccessMethod().equals(items[pos++]) ||
1535                            !new Integer(ad.getAccessLocation().getType())
1536                                    .equals(items[pos++])) {
1537                        throw new RuntimeException("Not same type at " + pos);
1538                    }
1539                    String name = null;
1540                    switch (ad.getAccessLocation().getType()) {
1541                        case 1:
1542                            name = ((RFC822Name)ad.getAccessLocation()
1543                                    .getName()).getName();
1544                            break;
1545                        case 6:
1546                            name = ((URIName)ad.getAccessLocation()
1547                                    .getName()).getURI().toString();
1548                            break;
1549                        default:
1550                            throw new RuntimeException("Not implemented: " + ad);
1551                    }
1552                    if (!name.equals(items[pos++])) {
1553                        throw new Exception("Name not same for " + ad +
1554                                " at pos " + pos);
1555                    }
1556                }
1557            }
1558        }
1559        CheckSia csia = new CheckSia();
1560        assertTrue(!((X509CertImpl)ks.getCertificate("sia1"))
1561                .getExtension(PKIXExtensions.SubjectInfoAccess_Id).isCritical());
1562        csia.check(ks, "sia1", 0,
1563                AccessDescription.Ad_CAREPOSITORY_Id, 6, "ldap://ca.com/cn=CA");
1564        csia.check(ks, "sia2",
1565                0, AccessDescription.Ad_TIMESTAMPING_Id, 1, "ts@ca.com");
1566
1567        // AIA
1568        testOK("", pre+"aia1 -ext aia=cai:uri:ldap://ca.com/cn=CA");
1569        testOK("", pre+"aia2 -ext aia=ocsp:email:ocsp@ca.com");
1570        testFail("AIA never critical", pre +
1571                "aia3 -ext aia:critical=ts:email:ts@ca.com");
1572
1573        ks = loadStore("x.jks", "changeit", "JKS");
1574        assertTrue(!((X509CertImpl)ks.getCertificate("aia1"))
1575                .getExtension(PKIXExtensions.AuthInfoAccess_Id).isCritical());
1576        csia.check(ks, "aia1", 1,
1577                AccessDescription.Ad_CAISSUERS_Id, 6, "ldap://ca.com/cn=CA");
1578        csia.check(ks, "aia2", 1,
1579                AccessDescription.Ad_OCSP_Id, 1, "ocsp@ca.com");
1580
1581        // OID
1582        testOK("", pre+"oid1 -ext 1.2.3:critical=0102");
1583        testOK("", pre+"oid2 -ext 1.2.3");
1584        testOK("", pre+"oid12 -ext 1.2.3 -ext 1.2.4=01:02:03");
1585
1586        ks = loadStore("x.jks", "changeit", "JKS");
1587        class CheckOid {
1588            void check(KeyStore ks, String alias, String oid, byte[] value)
1589                    throws Exception {
1590                int pos = 0;
1591                System.err.print("x");
1592                Extension ex = ((X509CertImpl)ks.getCertificate(alias))
1593                        .getExtension(new ObjectIdentifier(oid));
1594                if (!Arrays.equals(value, ex.getValue())) {
1595                    throw new RuntimeException("Not same content in " +
1596                            alias + " for " + oid);
1597                }
1598            }
1599        }
1600        CheckOid coid = new CheckOid();
1601        assertTrue(((X509CertImpl)ks.getCertificate("oid1"))
1602                .getExtension(new ObjectIdentifier("1.2.3")).isCritical());
1603        assertTrue(!((X509CertImpl)ks.getCertificate("oid2"))
1604                .getExtension(new ObjectIdentifier("1.2.3")).isCritical());
1605        coid.check(ks, "oid1", "1.2.3", new byte[]{1,2});
1606        coid.check(ks, "oid2", "1.2.3", new byte[]{});
1607        coid.check(ks, "oid12", "1.2.3", new byte[]{});
1608        coid.check(ks, "oid12", "1.2.4", new byte[]{1,2,3});
1609
1610        // honored
1611        testOK("", pre+"ca");
1612        testOK("", pre+"a");
1613        // request: BC,KU,1.2.3,1.2.4,1.2.5
1614        testOK("", simple+"-alias a -certreq " +
1615                "-ext BC=1 -ext KU=crl " +
1616                "-ext 1.2.3=01 -ext 1.2.4:critical=0102 -ext 1.2.5=010203 " +
1617                "-rfc -file test.req");
1618        // printcertreq
1619        testOK("", "-printcertreq -file test.req");
1620        checkPem("test.req");
1621        // issue: deny KU, change criticality of 1.2.3 and 1.2.4,
1622        // change content of BC, add 2.3.4
1623        testOK("", simple+"-gencert -alias ca -infile test.req -ext " +
1624                "honored=all,-KU,1.2.3:critical,1.2.4:non-critical " +
1625                "-ext BC=2 -ext 2.3.4=01020304 " +
1626                "-debug -rfc -outfile test.cert");
1627        checkPem("test.cert");
1628        testOK("", simple+"-importcert -file test.cert -alias a");
1629        ks = loadStore("x.jks", "changeit", "JKS");
1630        X509CertImpl a = (X509CertImpl)ks.getCertificate("a");
1631        assertTrue(a.getAuthorityKeyIdentifierExtension() != null);
1632        assertTrue(a.getSubjectKeyIdentifierExtension() != null);
1633        assertTrue(a.getKeyUsage() == null);
1634        assertTrue(a.getExtension(new ObjectIdentifier("1.2.3")).isCritical());
1635        assertTrue(!a.getExtension(new ObjectIdentifier("1.2.4")).isCritical());
1636        assertTrue(!a.getExtension(new ObjectIdentifier("1.2.5")).isCritical());
1637        assertTrue(a.getExtensionValue("1.2.3").length == 3);
1638        assertTrue(a.getExtensionValue("1.2.4").length == 4);
1639        assertTrue(a.getExtensionValue("1.2.5").length == 5);
1640        assertTrue(a.getBasicConstraints() == 2);
1641        assertTrue(!a.getExtension(new ObjectIdentifier("2.3.4")).isCritical());
1642        assertTrue(a.getExtensionValue("2.3.4").length == 6);
1643
1644        // 8073181: keytool -ext honored not working correctly
1645        testOK("", simple+"-gencert -alias ca -infile test.req -ext " +
1646                "honored=1.2.3,KU,1.2.4:critical " +
1647                "-debug -rfc -outfile test2.cert");
1648        testOK("", simple+"-importcert -file test2.cert -alias b");
1649        ks = loadStore("x.jks", "changeit", "JKS");
1650        X509CertImpl b = (X509CertImpl)ks.getCertificate("b");
1651        assertTrue(!b.getExtension(new ObjectIdentifier("1.2.3")).isCritical());
1652        assertTrue(b.getExtension(new ObjectIdentifier("1.2.4")).isCritical());
1653
1654        // 8073182: keytool may generate duplicate extensions
1655        testOK("", pre+"dup -ext bc=2 -ext 2.5.29.19=30030101FF -ext bc=3");
1656        ks = loadStore("x.jks", "changeit", "JKS");
1657        X509CertImpl dup = (X509CertImpl)ks.getCertificate("dup");
1658        assertTrue(dup.getBasicConstraints() == 3);
1659
1660        remove("x.jks");
1661        remove("test.req");
1662        remove("test.cert");
1663    }
1664
1665    void i18nTest() throws Exception {
1666        //   1.  keytool -help
1667        remove("x.jks");
1668        testOK("", "-help");
1669
1670        //   2. keytool -genkey -v -keysize 512 Enter "a" for the keystore
1671        // password. Check error (password too short). Enter "password" for
1672        // the keystore password. Hit 'return' for "first and last name",
1673        // "organizational unit", "City", "State", and "Country Code".
1674        // Type "yes" when they ask you if everything is correct.
1675        // Type 'return' for new key password.
1676        testOK("a\npassword\npassword\nMe\nHere\nNow\nPlace\nPlace\nUS\nyes\n\n",
1677                "-genkey -v -keysize 512 -keystore x.jks -storetype JKS");
1678        //   3. keytool -list -v -storepass password
1679        testOK("", "-list -v -storepass password -keystore x.jks -storetype JKS");
1680        //   4. keytool -list -v Type "a" for the keystore password.
1681        // Check error (wrong keystore password).
1682        testFail("a\n", "-list -v -keystore x.jks -storetype JKS");
1683        assertTrue(ex.indexOf("password was incorrect") != -1);
1684        //   5. keytool -genkey -v -keysize 512 Enter "password" as the password.
1685        // Check error (alias 'mykey' already exists).
1686        testFail("password\n", "-genkey -v -keysize 512" +
1687                " -keystore x.jks -storetype JKS");
1688        assertTrue(ex.indexOf("alias <mykey> already exists") != -1);
1689        //   6. keytool -genkey -v -keysize 512 -alias mykey2 -storepass password
1690        // Hit 'return' for "first and last name", "organizational unit", "City",
1691        // "State", and "Country Code". Type "yes" when they ask you if
1692        // everything is correct. Type 'return' for new key password.
1693        testOK("\n\n\n\n\n\nyes\n\n", "-genkey -v -keysize 512 -alias mykey2" +
1694                " -storepass password -keystore x.jks -storetype JKS");
1695        //   7. keytool -list -v Type 'password' for the store password.
1696        testOK("password\n", "-list -v -keystore x.jks -storetype JKS");
1697        //   8. keytool -keypasswd -v -alias mykey2 -storepass password
1698        // Type "a" for the new key password. Type "aaaaaa" for the new key
1699        // password. Type "bbbbbb" when re-entering the new key password.
1700        // Type "a" for the new key password. Check Error (too many failures).
1701        testFail("a\naaaaaa\nbbbbbb\na\n", "-keypasswd -v -alias mykey2" +
1702                " -storepass password -keystore x.jks -storetype JKS");
1703        assertTrue(ex.indexOf("Too many failures - try later") != -1);
1704        //   9. keytool -keypasswd -v -alias mykey2 -storepass password
1705        // Type "aaaaaa" for the new key password. Type "aaaaaa"
1706        // when re-entering the new key password.
1707        testOK("aaaaaa\naaaaaa\n", "-keypasswd -v -alias mykey2 " +
1708                "-storepass password -keystore x.jks -storetype JKS");
1709        //  10. keytool -selfcert -v -alias mykey -storepass password
1710        testOK("", "-selfcert -v -alias mykey -storepass password " +
1711                "-keystore x.jks -storetype JKS");
1712        //  11. keytool -list -v -storepass password
1713        testOK("", "-list -v -storepass password -keystore x.jks -storetype JKS");
1714        //  12. keytool -export -v -alias mykey -file cert -storepass password
1715        remove("cert");
1716        testOK("", "-export -v -alias mykey -file cert -storepass password " +
1717                "-keystore x.jks -storetype JKS");
1718        //  13. keytool -import -v -file cert -storepass password
1719        // Check error (Certificate reply and cert are the same)
1720        testFail("", "-import -v -file cert -storepass password" +
1721                " -keystore x.jks -storetype JKS");
1722        assertTrue(ex.indexOf("Certificate reply and certificate" +
1723                " in keystore are identical") != -1);
1724        //  14. keytool -printcert -file cert
1725        testOK("", "-printcert -file cert -keystore x.jks -storetype JKS");
1726        remove("cert");
1727        //  15. keytool -list -storepass password -addprovider SUN
1728        testOK("", "-list -storepass password" +
1729                " -addprovider SUN" +
1730                " -keystore x.jks -storetype JKS");
1731
1732        //Error tests
1733
1734        //   1. keytool -storepasswd -storepass password -new abc
1735        // Check error (password too short)
1736        testFail("", "-storepasswd -storepass password -new abc");
1737        assertTrue(ex.indexOf("New password must be at least 6 characters") != -1);
1738        // Changed, no NONE needed now
1739        //   2. keytool -list -storetype PKCS11 Check error (-keystore must be NONE)
1740        //testFail("", "-list -storetype PKCS11");
1741        //assertTrue(err.indexOf("keystore must be NONE") != -1);
1742        //   3. keytool -storepasswd -storetype PKCS11 -keystore NONE
1743        // Check error (unsupported operation)
1744        testFail("", "-storepasswd -storetype PKCS11 -keystore NONE");
1745        assertTrue(ex.indexOf("UnsupportedOperationException") != -1);
1746        //   4. keytool -keypasswd -storetype PKCS11 -keystore NONE
1747        // Check error (unsupported operation)
1748        testFail("", "-keypasswd -storetype PKCS11 -keystore NONE");
1749        assertTrue(ex.indexOf("UnsupportedOperationException") != -1);
1750        //   5. keytool -list -protected -storepass password
1751        // Check error (password can not be specified with -protected)
1752        testFail("", "-list -protected -storepass password " +
1753                "-keystore x.jks -storetype JKS");
1754        assertTrue(ex.indexOf("if -protected is specified, then") != -1);
1755        //   6. keytool -keypasswd -protected -keypass password
1756        // Check error (password can not be specified with -protected)
1757        testFail("", "-keypasswd -protected -keypass password " +
1758                "-keystore x.jks -storetype JKS");
1759        assertTrue(ex.indexOf("if -protected is specified, then") != -1);
1760        //   7. keytool -keypasswd -protected -new password
1761        // Check error (password can not be specified with -protected)
1762        testFail("", "-keypasswd -protected -new password " +
1763                "-keystore x.jks -storetype JKS");
1764        assertTrue(ex.indexOf("if -protected is specified, then") != -1);
1765        remove("x.jks");
1766    }
1767
1768    void i18nPKCS11Test() throws Exception {
1769        //PKCS#11 tests
1770
1771        //   1. sccs edit cert8.db key3.db
1772        //Runtime.getRuntime().exec("/usr/bin/sccs edit cert8.db key3.db");
1773        testOK("", p11Arg + ("-storepass test12 -genkey -alias genkey" +
1774                " -dname cn=genkey -keysize 512 -keyalg rsa"));
1775        testOK("", p11Arg + "-storepass test12 -list");
1776        testOK("", p11Arg + "-storepass test12 -list -alias genkey");
1777        testOK("", p11Arg +
1778                "-storepass test12 -certreq -alias genkey -file genkey.certreq");
1779        testOK("", p11Arg +
1780                "-storepass test12 -export -alias genkey -file genkey.cert");
1781        testOK("", "-printcert -file genkey.cert");
1782        testOK("", p11Arg +
1783                "-storepass test12 -selfcert -alias genkey -dname cn=selfCert");
1784        testOK("", p11Arg +
1785                "-storepass test12 -list -alias genkey -v");
1786        assertTrue(out.indexOf("Owner: CN=selfCert") != -1);
1787        //(check that cert subject DN is [cn=selfCert])
1788        testOK("", p11Arg + "-storepass test12 -delete -alias genkey");
1789        testOK("", p11Arg + "-storepass test12 -list");
1790        assertTrue(out.indexOf("Your keystore contains 0 entries") != -1);
1791        //(check for empty database listing)
1792        //Runtime.getRuntime().exec("/usr/bin/sccs unedit cert8.db key3.db");
1793        remove("genkey.cert");
1794        remove("genkey.certreq");
1795        //  12. sccs unedit cert8.db key3.db
1796    }
1797
1798    // tesing new option -srcProviderName
1799    void sszzTest() throws Exception {
1800        testAnyway("", NSS_P11_ARG+"-delete -alias nss -storepass test12");
1801        testAnyway("", NZZ_P11_ARG+"-delete -alias nss -storepass test12");
1802        testOK("", NSS_P11_ARG+"-genkeypair -dname CN=NSS " +
1803                "-alias nss -storepass test12");
1804        testOK("", NSS_SRC_P11_ARG + NZZ_P11_ARG +
1805                "-importkeystore -srcstorepass test12 -deststorepass test12");
1806        testAnyway("", NSS_P11_ARG+"-delete -alias nss -storepass test12");
1807        testAnyway("", NZZ_P11_ARG+"-delete -alias nss -storepass test12");
1808    }
1809
1810    public static void main(String[] args) throws Exception {
1811        Locale reservedLocale = Locale.getDefault();
1812        try {
1813            // first test if HumanInputStream really acts like a human being
1814            HumanInputStream.test();
1815            KeyToolTest t = new KeyToolTest();
1816
1817            if (System.getProperty("file") != null) {
1818                t.sqeTest();
1819                t.testAll();
1820                t.i18nTest();
1821                t.v3extTest("RSA");
1822                t.v3extTest("DSA");
1823                boolean testEC = true;
1824                try {
1825                    KeyPairGenerator.getInstance("EC");
1826                } catch (NoSuchAlgorithmException nae) {
1827                    testEC = false;
1828                }
1829                if (testEC) t.v3extTest("EC");
1830            }
1831
1832            if (System.getProperty("nss") != null) {
1833                t.srcP11Arg = NSS_SRC_P11_ARG;
1834                t.p11Arg = NSS_P11_ARG;
1835
1836                t.testPKCS11();
1837
1838                // FAIL:
1839                // 1. we still don't have srcprovidername yet
1840                // 2. cannot store privatekey into NSS keystore
1841                //    java.security.KeyStoreException: sun.security.pkcs11
1842                //      .wrapper.PKCS11Exception: CKR_TEMPLATE_INCOMPLETE.
1843                //t.testPKCS11ImportKeyStore();
1844
1845                t.i18nPKCS11Test();
1846                //FAIL: currently PKCS11-NSS does not support
1847                // 2 NSS KeyStores to be loaded at the same time
1848                //t.sszzTest();
1849            }
1850
1851            if (System.getProperty("solaris") != null) {
1852                // For Solaris Cryptography Framework
1853                t.srcP11Arg = SUN_SRC_P11_ARG;
1854                t.p11Arg = SUN_P11_ARG;
1855                t.testPKCS11();
1856                t.testPKCS11ImportKeyStore();
1857                t.i18nPKCS11Test();
1858            }
1859
1860            System.out.println("Test pass!!!");
1861        } finally {
1862            // restore the reserved locale
1863            Locale.setDefault(reservedLocale);
1864        }
1865    }
1866}
1867
1868class TestException extends Exception {
1869    public TestException(String e) {
1870        super(e);
1871    }
1872}
1873
1874/**
1875 * HumanInputStream tries to act like a human sitting in front of a computer
1876 * terminal typing on the keyboard while the keytool program is running.
1877 *
1878 * keytool has called InputStream.read() and BufferedReader.readLine() in
1879 * various places. a call to B.readLine() will try to buffer as much input as
1880 * possible. Thus, a trivial InputStream will find it impossible to feed
1881 * anything to I.read() after a B.readLine() call.
1882 *
1883 * This is why i create HumanInputStream, which will only send a single line
1884 * to B.readLine(), no more, no less, and the next I.read() can have a chance
1885 * to read the exact character right after "\n".
1886 *
1887 * I don't know why HumanInputStream works.
1888 */
1889class HumanInputStream extends InputStream {
1890    byte[] src;
1891    int pos;
1892    int length;
1893    boolean inLine;
1894    int stopIt;
1895
1896    public HumanInputStream(String input) {
1897        src = input.getBytes();
1898        pos = 0;
1899        length = src.length;
1900        stopIt = 0;
1901        inLine = false;
1902    }
1903
1904    // the trick: when called through read(byte[], int, int),
1905    // return -1 twice after "\n"
1906
1907    @Override public int read() throws IOException {
1908        int re;
1909        if(pos < length) {
1910            re = src[pos];
1911            if(inLine) {
1912                if(stopIt > 0) {
1913                    stopIt--;
1914                    re = -1;
1915                } else {
1916                    if(re == '\n') {
1917                        stopIt = 2;
1918                    }
1919                    pos++;
1920                }
1921            } else {
1922                pos++;
1923            }
1924        } else {
1925            re = -1;//throw new IOException("NO MORE TO READ");
1926        }
1927        //if (re < 32) System.err.printf("[%02d]", re);
1928        //else System.err.printf("[%c]", (char)re);
1929        return re;
1930    }
1931    @Override public int read(byte[] buffer, int offset, int len) {
1932        inLine = true;
1933        try {
1934            int re = super.read(buffer, offset, len);
1935            return re;
1936        } catch(Exception e) {
1937            throw new RuntimeException("HumanInputStream error");
1938        } finally {
1939            inLine = false;
1940        }
1941    }
1942    @Override public int available() {
1943        if(pos < length) return 1;
1944        return 0;
1945    }
1946
1947    // test part
1948    static void assertTrue(boolean bool) {
1949        if(!bool)
1950            throw new RuntimeException();
1951    }
1952
1953    public static void test() throws Exception {
1954
1955        class Tester {
1956            HumanInputStream is;
1957            BufferedReader reader;
1958            Tester(String s) {
1959                is = new HumanInputStream(s);
1960                reader = new BufferedReader(new InputStreamReader(is));
1961            }
1962
1963            // three kinds of test method
1964            // 1. read byte by byte from InputStream
1965            void testStreamReadOnce(int expection) throws Exception {
1966                assertTrue(is.read() == expection);
1967            }
1968            void testStreamReadMany(String expection) throws Exception {
1969                char[] keys = expection.toCharArray();
1970                for(int i=0; i<keys.length; i++) {
1971                    assertTrue(is.read() == keys[i]);
1972                }
1973            }
1974            // 2. read a line with a newly created Reader
1975            void testReaderReadline(String expection) throws Exception {
1976                String s = new BufferedReader(new InputStreamReader(is)).readLine();
1977                if(s == null) assertTrue(expection == null);
1978                else assertTrue(s.equals(expection));
1979            }
1980            // 3. read a line with the old Reader
1981            void testReaderReadline2(String expection) throws Exception  {
1982                String s = reader.readLine();
1983                if(s == null) assertTrue(expection == null);
1984                else assertTrue(s.equals(expection));
1985            }
1986        }
1987
1988        Tester test;
1989
1990        test = new Tester("111\n222\n\n444\n\n");
1991        test.testReaderReadline("111");
1992        test.testReaderReadline("222");
1993        test.testReaderReadline("");
1994        test.testReaderReadline("444");
1995        test.testReaderReadline("");
1996        test.testReaderReadline(null);
1997
1998        test = new Tester("111\n222\n\n444\n\n");
1999        test.testReaderReadline2("111");
2000        test.testReaderReadline2("222");
2001        test.testReaderReadline2("");
2002        test.testReaderReadline2("444");
2003        test.testReaderReadline2("");
2004        test.testReaderReadline2(null);
2005
2006        test = new Tester("111\n222\n\n444\n\n");
2007        test.testReaderReadline2("111");
2008        test.testReaderReadline("222");
2009        test.testReaderReadline2("");
2010        test.testReaderReadline2("444");
2011        test.testReaderReadline("");
2012        test.testReaderReadline2(null);
2013
2014        test = new Tester("1\n2");
2015        test.testStreamReadMany("1\n2");
2016        test.testStreamReadOnce(-1);
2017
2018        test = new Tester("12\n234");
2019        test.testStreamReadOnce('1');
2020        test.testReaderReadline("2");
2021        test.testStreamReadOnce('2');
2022        test.testReaderReadline2("34");
2023        test.testReaderReadline2(null);
2024
2025        test = new Tester("changeit\n");
2026        test.testStreamReadMany("changeit\n");
2027        test.testReaderReadline(null);
2028
2029        test = new Tester("changeit\nName\nCountry\nYes\n");
2030        test.testStreamReadMany("changeit\n");
2031        test.testReaderReadline("Name");
2032        test.testReaderReadline("Country");
2033        test.testReaderReadline("Yes");
2034        test.testReaderReadline(null);
2035
2036        test = new Tester("Me\nHere\n");
2037        test.testReaderReadline2("Me");
2038        test.testReaderReadline2("Here");
2039    }
2040}
2041