1 /* 2 * Copyright (c) 2017, 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 8192988 27 * @summary keytool should support -storepasswd for pkcs12 keystores 28 * @library /test/lib 29 * @build jdk.test.lib.SecurityTools 30 * jdk.test.lib.Utils 31 * jdk.test.lib.Asserts 32 * jdk.test.lib.JDKToolFinder 33 * jdk.test.lib.JDKToolLauncher 34 * jdk.test.lib.Platform 35 * jdk.test.lib.process.* 36 * @run main PKCS12Passwd 37 */ 38 39 import jdk.test.lib.Asserts; 40 import jdk.test.lib.SecurityTools; 41 import jdk.test.lib.process.OutputAnalyzer; 42 43 import java.io.File; 44 import java.security.KeyStore; 45 import java.util.Collections; 46 47 public class PKCS12Passwd { 48 49 public static void main(String[] args) throws Exception { 50 51 // A PrivateKeyEntry 52 kt("-genkeypair -alias a -dname CN=A") 53 .shouldHaveExitValue(0); 54 55 // A TrustedCertificateEntry (genkeypair, export, delete, import) 56 kt("-genkeypair -alias b -dname CN=B") 57 .shouldHaveExitValue(0); 58 kt("-exportcert -alias b -file b.cert") 59 .shouldHaveExitValue(0); 60 kt("-delete -alias b") 61 .shouldHaveExitValue(0); 62 kt("-list -alias b") 63 .shouldHaveExitValue(1); 64 kt("-importcert -alias b -file b.cert -noprompt") 65 .shouldHaveExitValue(0); 66 67 // A SecretKeyEntry 68 kt("-genseckey -keyalg AES -keysize 256 -alias c") 69 .shouldHaveExitValue(0); 70 71 // Change password 72 73 // 1. Using -importkeystore 74 ktFull("-importkeystore -srckeystore ks -destkeystore ks2 " 75 + "-srcstoretype pkcs12 -deststoretype pkcs12 " 76 + "-srcstorepass changeit -deststorepass newpass") 77 .shouldHaveExitValue(0); 78 79 check("ks2", "newpass", "newpass"); 80 81 // 2. Using -storepasswd 82 kt("-storepasswd -new newpass") 83 .shouldHaveExitValue(0) 84 .shouldNotContain("Ignoring user-specified"); 85 86 check("ks", "newpass", "newpass"); 87 88 // Other facts. Not necessarily the correct thing. 89 90 // A PKCS12 keystore can be loaded as a JKS, and it follows JKS rules 91 // which means the storepass and keypass can be changed separately! 92 93 ktFull("-genkeypair -alias a -dname CN=A -storetype pkcs12 " 94 + "-storepass changeit -keypass changeit -keystore p12") 95 .shouldHaveExitValue(0); 96 97 // Only storepass is changed 98 ktFull("-storepasswd -storepass changeit -new newpass " 99 + "-keystore p12 -storetype jks") 100 .shouldHaveExitValue(0); 101 102 check("p12", "newpass", "changeit"); 103 104 // Only keypass is changed 105 ktFull("-keypasswd -storepass newpass -keypass changeit -new newpass " 106 + "-keystore p12 -storetype jks -alias a") 107 .shouldHaveExitValue(0); 108 109 check("p12", "newpass", "newpass"); 110 111 // Conversely, a JKS keystore can be laoded as a PKCS12, and it follows 112 // PKCS12 rules that both passwords are changed at the same time and 113 // some commands are rejected. 114 115 ktFull("-genkeypair -alias a -dname CN=A -storetype jks " 116 + "-storepass changeit -keypass changeit -keystore jks") 117 .shouldHaveExitValue(0); 118 119 // Both storepass and keypass changed. 120 ktFull("-storepasswd -storepass changeit -new newpass " 121 + "-keystore jks -storetype pkcs12") 122 .shouldHaveExitValue(0); 123 124 check("jks", "newpass", "newpass"); 125 126 // -keypasswd is not available for pkcs12 127 ktFull("-keypasswd -storepass newpass -keypass newpass -new newerpass " 128 + "-keystore jks -storetype pkcs12 -alias a") 129 .shouldHaveExitValue(1); 130 131 // but available for JKS 132 ktFull("-keypasswd -storepass newpass -keypass newpass -new newerpass " 133 + "-keystore jks -alias a") 134 .shouldHaveExitValue(0); 135 136 check("jks", "newpass", "newerpass"); 137 } 138 139 // Makes sure we can load entries in a keystore 140 static void check(String file, String storePass, String keyPass) 141 throws Exception { 142 143 KeyStore ks = KeyStore.getInstance( 144 new File(file), storePass.toCharArray()); 145 146 for (String a : Collections.list(ks.aliases())) { 147 if (ks.isCertificateEntry(a)) { 148 ks.getCertificate(a); 149 } else { 150 ks.getEntry(a, 151 new KeyStore.PasswordProtection(keyPass.toCharArray())); 152 } 153 } 154 } 155 156 static OutputAnalyzer kt(String arg) throws Exception { 157 return ktFull("-keystore ks -storepass changeit " + arg); 158 } 159 160 static OutputAnalyzer ktFull(String arg) throws Exception { 161 return SecurityTools.keytool("-debug " + arg); 162 } 163 }