Path: blob/master/test/jdk/sun/security/tools/keytool/StorePasswords.java
41152 views
/*1* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 800829626* @summary Store and retrieve user passwords using PKCS#12 keystore27* @library /test/lib28*/2930import jdk.test.lib.SecurityTools;31import jdk.test.lib.process.OutputAnalyzer;3233import java.io.*;34import java.security.*;35import java.util.*;36import javax.crypto.*;37import javax.crypto.spec.*;3839/*40* Store and retrieve passwords protected by a selection of PBE algorithms,41* using a PKCS#12 keystore.42*/43public class StorePasswords {4445private static final String[] PBE_ALGORITHMS = new String[] {46"default PBE algorithm",47"PBEWithMD5AndDES",48"PBEWithSHA1AndDESede",49"PBEWithSHA1AndRC2_40",50"PBEWithSHA1AndRC2_128",51"PBEWithSHA1AndRC4_40",52"PBEWithSHA1AndRC4_128",53"PBEWithHmacSHA1AndAES_128",54"PBEWithHmacSHA224AndAES_128",55"PBEWithHmacSHA256AndAES_128",56"PBEWithHmacSHA384AndAES_128",57"PBEWithHmacSHA512AndAES_128",58"PBEWithHmacSHA1AndAES_256",59"PBEWithHmacSHA224AndAES_256",60"PBEWithHmacSHA256AndAES_256",61"PBEWithHmacSHA384AndAES_256",62"PBEWithHmacSHA512AndAES_256"63};6465private static final String KEYSTORE = "mykeystore.p12";66private static final char[] KEYSTORE_PWD = "changeit".toCharArray();67private static final char[] ENTRY_PWD = "protectit".toCharArray();68private static final char[] USER_PWD = "hello1".toCharArray();6970public static void main(String[] args) throws Exception {7172new File(KEYSTORE).delete();7374int storeCount = store();75int recoverCount = recover();7677if (recoverCount != storeCount) {78throw new Exception("Stored " + storeCount + " user passwords, " +79"recovered " + recoverCount + " user passwords");80}81System.out.println("\nStored " + storeCount + " user passwords, " +82"recovered " + recoverCount + " user passwords");8384new File(KEYSTORE).delete();8586storeCount = storeByShell();87recoverCount = recoverByShell();8889if (recoverCount != storeCount || storeCount < 11) {90throw new Exception("Stored " + storeCount + " user passwords, " +91"recovered " + recoverCount + " user passwords");92}93System.out.println("\nStored " + storeCount + " user passwords, " +94"recovered " + recoverCount + " user passwords");9596new File(KEYSTORE).delete();97}9899private static int store() throws Exception {100int count = 0;101// Load an empty PKCS#12 keystore102KeyStore keystore = KeyStore.getInstance("PKCS12");103System.out.println("\nLoading PKCS#12 keystore...");104keystore.load(null, null);105106// Derive a PBE key from the password107PBEKeySpec keySpec = new PBEKeySpec(USER_PWD);108SecretKeyFactory factory = SecretKeyFactory.getInstance("PBE");109SecretKey key = factory.generateSecret(keySpec);110PBEParameterSpec specWithEightByteSalt =111new PBEParameterSpec("NaClNaCl".getBytes(), 1024);112113// Store the user password in a keystore entry (for each algorithm)114for (String algorithm : PBE_ALGORITHMS) {115116try {117System.out.println("Storing user password '" +118new String(USER_PWD) + "' (protected by " + algorithm +119")");120121if (algorithm.equals("default PBE algorithm")) {122keystore.setKeyEntry(123"this entry is protected by " + algorithm, key,124ENTRY_PWD, null);125} else {126keystore.setEntry(127"this entry is protected by " + algorithm,128new KeyStore.SecretKeyEntry(key),129new KeyStore.PasswordProtection(ENTRY_PWD, algorithm,130null));131}132count++;133134} catch (KeyStoreException e) {135Throwable inner = e.getCause();136if (inner instanceof UnrecoverableKeyException) {137Throwable inner2 = inner.getCause();138if (inner2 instanceof InvalidAlgorithmParameterException) {139System.out.println("...re-trying due to: " +140inner2.getMessage());141142// Some PBE algorithms demand an 8-byte salt143keystore.setEntry(144"this entry is protected by " + algorithm,145new KeyStore.SecretKeyEntry(key),146new KeyStore.PasswordProtection(ENTRY_PWD,147algorithm, specWithEightByteSalt));148count++;149150} else if (inner2 instanceof InvalidKeyException) {151System.out.println("...skipping due to: " +152inner2.getMessage());153// Unsupported crypto keysize154continue;155}156} else {157throw e;158}159}160}161162// Store the PKCS#12 keystore163System.out.println("Storing PKCS#12 keystore to: " + KEYSTORE);164try (FileOutputStream out = new FileOutputStream(KEYSTORE)) {165keystore.store(out, KEYSTORE_PWD);166}167168return count;169}170171private static int recover() throws Exception {172int count = 0;173// Load the PKCS#12 keystore174KeyStore keystore = KeyStore.getInstance("PKCS12");175System.out.println("\nLoading PKCS#12 keystore from: " + KEYSTORE);176try (FileInputStream in = new FileInputStream(KEYSTORE)) {177keystore.load(in, KEYSTORE_PWD);178}179180SecretKey key;181SecretKeyFactory factory;182PBEKeySpec keySpec;183184// Retrieve each user password from the keystore185for (String algorithm : PBE_ALGORITHMS) {186key = (SecretKey) keystore.getKey("this entry is protected by " +187algorithm, ENTRY_PWD);188189if (key != null) {190count++;191factory = SecretKeyFactory.getInstance(key.getAlgorithm());192keySpec =193(PBEKeySpec) factory.getKeySpec(key, PBEKeySpec.class);194char[] pwd = keySpec.getPassword();195System.out.println("Recovered user password '" +196new String(pwd) + "' (protected by " + algorithm + ")");197198if (!Arrays.equals(USER_PWD, pwd)) {199throw new Exception("Failed to recover the user password " +200"protected by " + algorithm);201}202}203}204205return count;206}207208private static int storeByShell() throws Exception {209int count = 0;210for (String algorithm : PBE_ALGORITHMS) {211System.out.println("Storing user password (protected by " + algorithm + " )");212String importCmd = count < 5 ? "-importpassword" : "-importpass";213String keyAlg = algorithm.equals("default PBE algorithm")214? "" : (" -keyalg " + algorithm);215SecurityTools.setResponse("hello1");216OutputAnalyzer oa = SecurityTools.keytool(importCmd217+ " -storetype pkcs12 -keystore mykeystore.p12"218+ " -storepass changeit -alias `this entry is protected by "219+ algorithm + "`" + keyAlg);220if (oa.getExitValue() == 0) {221System.out.println("OK");222count++;223} else {224System.out.println("ERROR");225}226}227return count;228}229230private static int recoverByShell() throws Exception {231return (int)SecurityTools.keytool("-list -storetype pkcs12"232+ " -keystore mykeystore.p12 -storepass changeit")233.shouldHaveExitValue(0)234.asLines().stream()235.filter(s -> s.contains("this entry is protected by"))236.count();237}238}239240241