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