Path: blob/master/test/jdk/sun/security/pkcs12/ParamsTest.java
41149 views
/*1* Copyright (c) 2018, 2020, 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 8076190 8242151 815300526* @library /test/lib27* @modules java.base/sun.security.pkcs28* java.base/sun.security.util29* @summary Customizing the generation of a PKCS12 keystore30*/3132import jdk.test.lib.Asserts;33import jdk.test.lib.SecurityTools;34import jdk.test.lib.process.OutputAnalyzer;3536import java.io.File;37import java.io.FileInputStream;38import java.io.FileOutputStream;39import java.io.IOException;40import java.io.InputStream;41import java.io.OutputStream;42import java.io.UncheckedIOException;43import java.nio.file.DirectoryStream;44import java.nio.file.Files;45import java.nio.file.Path;46import java.security.KeyStore;47import java.util.Base64;48import java.util.Objects;4950import static jdk.test.lib.security.DerUtils.*;51import static sun.security.util.KnownOIDs.*;52import static sun.security.pkcs.ContentInfo.*;5354public class ParamsTest {5556public static void main(String[] args) throws Throwable {5758// De-BASE64 textual files in ./params to `pwd`59try (DirectoryStream<Path> stream = Files.newDirectoryStream(60Path.of(System.getProperty("test.src"), "params"),61p -> !p.getFileName().toString().equals("README"))) {62stream.forEach(p -> {63try (InputStream is = Files.newInputStream(p);64OutputStream os = Files.newOutputStream(p.getFileName())) {65Base64.getMimeDecoder().wrap(is).transferTo(os);66} catch (IOException e) {67throw new UncheckedIOException(e);68}69});70}7172byte[] data;7374// openssl -> keytool interop check7576// os2. no cert pbe, no mac.77check("os2", "a", null, "changeit", true, true, true);78check("os2", "a", "changeit", "changeit", true, true, true);79// You can even load it with a wrong storepass, controversial80check("os2", "a", "wrongpass", "changeit", true, true, true);8182// os3. no cert pbe, has mac. just like JKS83check("os3", "a", null, "changeit", true, true, true);84check("os3", "a", "changeit", "changeit", true, true, true);85// Cannot load with a wrong storepass, same as JKS86check("os3", "a", "wrongpass", "-", IOException.class, "-", "-");8788// os4. non default algs89check("os4", "a", "changeit", "changeit", true, true, true);90check("os4", "a", "wrongpass", "-", IOException.class, "-", "-");91// no storepass no cert92check("os4", "a", null, "changeit", true, false, true);9394// os5. strong non default algs95check("os5", "a", "changeit", "changeit", true, true, true);96check("os5", "a", "wrongpass", "-", IOException.class, "-", "-");97// no storepass no cert98check("os5", "a", null, "changeit", true, false, true);99100// keytool101102// Current default pkcs12 setting103keytool("-importkeystore -srckeystore ks -srcstorepass changeit "104+ "-destkeystore ksnormal -deststorepass changeit");105106data = Files.readAllBytes(Path.of("ksnormal"));107checkInt(data, "22", 10000); // Mac ic108checkAlg(data, "2000", SHA_256); // Mac alg109checkAlg(data, "110c010c01000", PBES2); // key alg110checkInt(data, "110c010c01001011", 10000); // key ic111checkAlg(data, "110c10", ENCRYPTED_DATA_OID);112checkAlg(data, "110c110110", PBES2); // cert alg113check("ksnormal", "a", "changeit", "changeit", true, true, true);114check("ksnormal", "a", null, "changeit", true, false, true);115check("ksnormal", "a", "wrongpass", "-", IOException.class, "-", "-");116117// Import it into a new keystore with legacy algorithms118keytool("-importkeystore -srckeystore ksnormal -srcstorepass changeit "119+ "-destkeystore kslegacyimp -deststorepass changeit "120+ "-J-Dkeystore.pkcs12.legacy");121data = Files.readAllBytes(Path.of("kslegacyimp"));122checkInt(data, "22", 100000); // Mac ic123checkAlg(data, "2000", SHA_1); // Mac alg124checkAlg(data, "110c010c01000", PBEWithSHA1AndDESede); // key alg125checkInt(data, "110c010c010011", 50000); // key ic126checkAlg(data, "110c110110", PBEWithSHA1AndRC2_40); // cert alg127checkInt(data, "110c1101111", 50000); // cert ic128129// Add a new entry with password-less settings, still has a storepass130keytool("-keystore ksnormal -genkeypair -keyalg DSA "131+ "-storepass changeit -alias b -dname CN=b "132+ "-J-Dkeystore.pkcs12.certProtectionAlgorithm=NONE "133+ "-J-Dkeystore.pkcs12.macAlgorithm=NONE");134data = Files.readAllBytes(Path.of("ksnormal"));135checkInt(data, "22", 10000); // Mac ic136checkAlg(data, "2000", SHA_256); // Mac alg137checkAlg(data, "110c010c01000", PBES2); // key alg138checkInt(data, "110c010c01001011", 10000); // key ic139checkAlg(data, "110c010c11000", PBES2); // new key alg140checkInt(data, "110c010c11001011", 10000); // new key ic141checkAlg(data, "110c10", ENCRYPTED_DATA_OID);142checkAlg(data, "110c110110", PBES2); // cert alg143check("ksnormal", "b", null, "changeit", true, false, true);144check("ksnormal", "b", "changeit", "changeit", true, true, true);145146// Different keypbe alg, no cert pbe and no mac147keytool("-importkeystore -srckeystore ks -srcstorepass changeit "148+ "-destkeystore ksnopass -deststorepass changeit "149+ "-J-Dkeystore.pkcs12.keyProtectionAlgorithm=PBEWithSHA1AndRC4_128 "150+ "-J-Dkeystore.pkcs12.certProtectionAlgorithm=NONE "151+ "-J-Dkeystore.pkcs12.macAlgorithm=NONE");152data = Files.readAllBytes(Path.of("ksnopass"));153shouldNotExist(data, "2"); // no Mac154checkAlg(data, "110c010c01000", PBEWithSHA1AndRC4_128);155checkInt(data, "110c010c010011", 10000);156checkAlg(data, "110c10", DATA_OID);157check("ksnopass", "a", null, "changeit", true, true, true);158check("ksnopass", "a", "changeit", "changeit", true, true, true);159check("ksnopass", "a", "wrongpass", "changeit", true, true, true);160161// Add a new entry with normal settings, still password-less162keytool("-keystore ksnopass -genkeypair -keyalg DSA "163+ "-storepass changeit -alias b -dname CN=B");164data = Files.readAllBytes(Path.of("ksnopass"));165shouldNotExist(data, "2"); // no Mac166checkAlg(data, "110c010c01000", PBEWithSHA1AndRC4_128);167checkInt(data, "110c010c010011", 10000);168checkAlg(data, "110c010c11000", PBES2);169checkInt(data, "110c010c11001011", 10000);170checkAlg(data, "110c10", DATA_OID);171check("ksnopass", "a", null, "changeit", true, true, true);172check("ksnopass", "b", null, "changeit", true, true, true);173174keytool("-importkeystore -srckeystore ks -srcstorepass changeit "175+ "-destkeystore ksnewic -deststorepass changeit "176+ "-J-Dkeystore.pkcs12.macIterationCount=5555 "177+ "-J-Dkeystore.pkcs12.certPbeIterationCount=6666 "178+ "-J-Dkeystore.pkcs12.keyPbeIterationCount=7777");179data = Files.readAllBytes(Path.of("ksnewic"));180checkInt(data, "22", 5555); // Mac ic181checkAlg(data, "2000", SHA_256); // Mac alg182checkAlg(data, "110c010c01000", PBES2); // key alg183checkInt(data, "110c010c01001011", 7777); // key ic184checkAlg(data, "110c110110", PBES2); // cert alg185checkInt(data, "110c110111011", 6666); // cert ic186187// keypbe alg cannot be NONE188keytool("-keystore ksnewic -genkeypair -keyalg DSA "189+ "-storepass changeit -alias b -dname CN=B "190+ "-J-Dkeystore.pkcs12.keyProtectionAlgorithm=NONE")191.shouldContain("NONE AlgorithmParameters not available")192.shouldHaveExitValue(1);193194// new entry new keypbe alg (and default ic), else unchanged195keytool("-keystore ksnewic -genkeypair -keyalg DSA "196+ "-storepass changeit -alias b -dname CN=B "197+ "-J-Dkeystore.pkcs12.keyProtectionAlgorithm=PBEWithSHA1AndRC4_128");198data = Files.readAllBytes(Path.of("ksnewic"));199checkInt(data, "22", 5555); // Mac ic200checkAlg(data, "2000", SHA_256); // Mac alg201checkAlg(data, "110c010c01000", PBES2); // key alg202checkInt(data, "110c010c01001011", 7777); // key ic203checkAlg(data, "110c010c11000", PBEWithSHA1AndRC4_128); // new key alg204checkInt(data, "110c010c110011", 10000); // new key ic205checkAlg(data, "110c110110", PBES2); // cert alg206checkInt(data, "110c110111011", 6666); // cert ic207208// Check KeyStore loading multiple keystores209KeyStore ks = KeyStore.getInstance("pkcs12");210try (FileInputStream fis = new FileInputStream("ksnormal");211FileOutputStream fos = new FileOutputStream("ksnormaldup")) {212ks.load(fis, "changeit".toCharArray());213ks.store(fos, "changeit".toCharArray());214}215data = Files.readAllBytes(Path.of("ksnormaldup"));216checkInt(data, "22", 10000); // Mac ic217checkAlg(data, "2000", SHA_256); // Mac alg218checkAlg(data, "110c010c01000", PBES2); // key alg219checkInt(data, "110c010c01001011", 10000); // key ic220checkAlg(data, "110c010c11000", PBES2); // new key alg221checkInt(data, "110c010c11001011", 10000); // new key ic222checkAlg(data, "110c10", ENCRYPTED_DATA_OID);223checkAlg(data, "110c110110", PBES2); // cert alg224checkInt(data, "110c110111011", 10000); // cert ic225226try (FileInputStream fis = new FileInputStream("ksnopass");227FileOutputStream fos = new FileOutputStream("ksnopassdup")) {228ks.load(fis, "changeit".toCharArray());229ks.store(fos, "changeit".toCharArray());230}231data = Files.readAllBytes(Path.of("ksnopassdup"));232shouldNotExist(data, "2"); // no Mac233checkAlg(data, "110c010c01000", PBEWithSHA1AndRC4_128);234checkInt(data, "110c010c010011", 10000);235checkAlg(data, "110c010c11000", PBES2);236checkInt(data, "110c010c11001011", 10000);237checkAlg(data, "110c10", DATA_OID);238239try (FileInputStream fis = new FileInputStream("ksnewic");240FileOutputStream fos = new FileOutputStream("ksnewicdup")) {241ks.load(fis, "changeit".toCharArray());242ks.store(fos, "changeit".toCharArray());243}244data = Files.readAllBytes(Path.of("ksnewicdup"));245checkInt(data, "22", 5555); // Mac ic246checkAlg(data, "2000", SHA_256); // Mac alg247checkAlg(data, "110c010c01000", PBES2); // key alg248checkInt(data, "110c010c01001011", 7777); // key ic249checkAlg(data, "110c010c11000", PBEWithSHA1AndRC4_128); // new key alg250checkInt(data, "110c010c110011", 10000); // new key ic251checkAlg(data, "110c110110", PBES2); // cert alg252checkInt(data, "110c110111011", 6666); // cert ic253254// Check keytool behavior255256// ksnormal has password257258keytool("-list -keystore ksnormal")259.shouldContain("WARNING WARNING WARNING")260.shouldContain("Certificate chain length: 0");261262SecurityTools.setResponse("changeit");263keytool("-list -keystore ksnormal")264.shouldNotContain("WARNING WARNING WARNING")265.shouldContain("Certificate fingerprint");266267// ksnopass is password-less268269keytool("-list -keystore ksnopass")270.shouldNotContain("WARNING WARNING WARNING")271.shouldContain("Certificate fingerprint");272273// -certreq prompts for keypass274SecurityTools.setResponse("changeit");275keytool("-certreq -alias a -keystore ksnopass")276.shouldContain("Enter key password for <a>")277.shouldContain("-----BEGIN NEW CERTIFICATE REQUEST-----")278.shouldHaveExitValue(0);279280// -certreq -storepass works fine281keytool("-certreq -alias a -keystore ksnopass -storepass changeit")282.shouldNotContain("Enter key password for <a>")283.shouldContain("-----BEGIN NEW CERTIFICATE REQUEST-----")284.shouldHaveExitValue(0);285286// -certreq -keypass also works fine287keytool("-certreq -alias a -keystore ksnopass -keypass changeit")288.shouldNotContain("Enter key password for <a>")289.shouldContain("-----BEGIN NEW CERTIFICATE REQUEST-----")290.shouldHaveExitValue(0);291292// -importkeystore prompts for srckeypass293SecurityTools.setResponse("changeit", "changeit");294keytool("-importkeystore -srckeystore ksnopass "295+ "-destkeystore jks3 -deststorepass changeit")296.shouldContain("Enter key password for <a>")297.shouldContain("Enter key password for <b>")298.shouldContain("2 entries successfully imported");299300// ksnopass2 is ksnopass + 2 cert entries301302ks = KeyStore.getInstance(new File("ksnopass"), (char[])null);303ks.setCertificateEntry("aa", ks.getCertificate("a"));304ks.setCertificateEntry("bb", ks.getCertificate("b"));305try (FileOutputStream fos = new FileOutputStream("ksnopass2")) {306ks.store(fos, null);307}308309// -importkeystore prompts for srckeypass for private keys310// and no prompt for certs311SecurityTools.setResponse("changeit", "changeit");312keytool("-importkeystore -srckeystore ksnopass2 "313+ "-destkeystore jks5 -deststorepass changeit")314.shouldContain("Enter key password for <a>")315.shouldContain("Enter key password for <b>")316.shouldNotContain("Enter key password for <aa>")317.shouldNotContain("Enter key password for <bb>")318.shouldContain("4 entries successfully imported");319320// ksonlycert has only cert entries321322ks.deleteEntry("a");323ks.deleteEntry("b");324try (FileOutputStream fos = new FileOutputStream("ksonlycert")) {325ks.store(fos, null);326}327328// -importkeystore does not prompt at all329keytool("-importkeystore -srckeystore ksonlycert "330+ "-destkeystore jks6 -deststorepass changeit")331.shouldNotContain("Enter key password for <aa>")332.shouldNotContain("Enter key password for <bb>")333.shouldContain("2 entries successfully imported");334335// create a new password-less keystore336keytool("-keystore ksnopass -exportcert -alias a -file a.cert -rfc");337338// Normally storepass is prompted for339keytool("-keystore kscert1 -importcert -alias a -file a.cert -noprompt")340.shouldContain("Enter keystore password:");341keytool("-keystore kscert2 -importcert -alias a -file a.cert -noprompt "342+ "-J-Dkeystore.pkcs12.certProtectionAlgorithm=NONE")343.shouldContain("Enter keystore password:");344keytool("-keystore kscert3 -importcert -alias a -file a.cert -noprompt "345+ "-J-Dkeystore.pkcs12.macAlgorithm=NONE")346.shouldContain("Enter keystore password:");347// ... but not if it's password-less348keytool("-keystore kscert4 -importcert -alias a -file a.cert -noprompt "349+ "-J-Dkeystore.pkcs12.certProtectionAlgorithm=NONE "350+ "-J-Dkeystore.pkcs12.macAlgorithm=NONE")351.shouldNotContain("Enter keystore password:");352353// still prompt for keypass for genkeypair and certreq354SecurityTools.setResponse("changeit", "changeit");355keytool("-keystore ksnopassnew -genkeypair -keyalg DSA "356+ "-alias a -dname CN=A "357+ "-J-Dkeystore.pkcs12.certProtectionAlgorithm=NONE "358+ "-J-Dkeystore.pkcs12.macAlgorithm=NONE")359.shouldNotContain("Enter keystore password:")360.shouldContain("Enter key password for <a>");361keytool("-keystore ksnopassnew -certreq -alias a")362.shouldNotContain("Enter keystore password:")363.shouldContain("Enter key password for <a>");364keytool("-keystore ksnopassnew -list -v -alias a")365.shouldNotContain("Enter keystore password:")366.shouldNotContain("Enter key password for <a>");367368// params only read on demand369370// keyPbeIterationCount is used by -genkeypair371keytool("-keystore ksgenbadkeyic -genkeypair -keyalg DSA "372+ "-alias a -dname CN=A "373+ "-storepass changeit "374+ "-J-Dkeystore.pkcs12.keyPbeIterationCount=abc")375.shouldContain("keyPbeIterationCount is not a number: abc")376.shouldHaveExitValue(1);377378keytool("-keystore ksnopassnew -exportcert -alias a -file a.cert");379380// but not used by -importcert381keytool("-keystore ksimpbadkeyic -importcert -alias a -file a.cert "382+ "-noprompt -storepass changeit "383+ "-J-Dkeystore.pkcs12.keyPbeIterationCount=abc")384.shouldHaveExitValue(0);385386// None is used by -list387keytool("-keystore ksnormal -storepass changeit -list "388+ "-J-Dkeystore.pkcs12.keyPbeIterationCount=abc "389+ "-J-Dkeystore.pkcs12.certPbeIterationCount=abc "390+ "-J-Dkeystore.pkcs12.macIterationCount=abc")391.shouldHaveExitValue(0);392}393394/**395* Check keystore loading and key/cert reading.396*397* @param keystore the file name of keystore398* @param alias the key/cert to read399* @param storePass store pass to try out, can be null400* @param keypass key pass to try, can not be null401* @param expectedLoad expected result of keystore loading, true if non402* null, false if null, exception class if exception403* @param expectedCert expected result of cert reading404* @param expectedKey expected result of key reading405*/406private static void check(407String keystore,408String alias,409String storePass,410String keypass,411Object expectedLoad,412Object expectedCert,413Object expectedKey) {414KeyStore ks = null;415Object actualLoad, actualCert, actualKey;416String label = keystore + "-" + alias + "-" + storePass + "-" + keypass;417try {418ks = KeyStore.getInstance(new File(keystore),419storePass == null ? null : storePass.toCharArray());420actualLoad = ks != null;421} catch (Exception e) {422e.printStackTrace(System.out);423actualLoad = e.getClass();424}425Asserts.assertEQ(expectedLoad, actualLoad, label + "-load");426427// If not loaded correctly, skip cert/key reading428if (!Objects.equals(actualLoad, true)) {429return;430}431432try {433actualCert = (ks.getCertificate(alias) != null);434} catch (Exception e) {435e.printStackTrace(System.out);436actualCert = e.getClass();437}438Asserts.assertEQ(expectedCert, actualCert, label + "-cert");439440try {441actualKey = (ks.getKey(alias, keypass.toCharArray()) != null);442} catch (Exception e) {443e.printStackTrace(System.out);444actualKey = e.getClass();445}446Asserts.assertEQ(expectedKey, actualKey, label + "-key");447}448449static OutputAnalyzer keytool(String s) throws Throwable {450return SecurityTools.keytool(s);451}452}453454455