Path: blob/master/test/jdk/sun/security/tools/keytool/WeakAlg.java
41152 views
/*1* Copyright (c) 2017, 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 8171319 8177569 8182879 817240426* @summary keytool should print out warnings when reading or generating27* cert/cert req using weak algorithms28* @library /test/lib29* @modules java.base/sun.security.tools.keytool30* java.base/sun.security.tools31* java.base/sun.security.util32* @build jdk.test.lib.SecurityTools33* jdk.test.lib.Utils34* jdk.test.lib.Asserts35* jdk.test.lib.JDKToolFinder36* jdk.test.lib.JDKToolLauncher37* jdk.test.lib.Platform38* jdk.test.lib.process.*39* @run main/othervm/timeout=600 -Duser.language=en -Duser.country=US WeakAlg40*/4142import jdk.test.lib.Asserts;43import jdk.test.lib.SecurityTools;44import jdk.test.lib.process.OutputAnalyzer;45import sun.security.tools.KeyStoreUtil;46import sun.security.util.DisabledAlgorithmConstraints;4748import java.io.ByteArrayInputStream;49import java.io.ByteArrayOutputStream;50import java.io.File;51import java.io.IOException;52import java.io.InputStream;53import java.io.PrintStream;54import java.nio.file.Files;55import java.nio.file.Paths;56import java.nio.file.StandardCopyOption;57import java.security.CryptoPrimitive;58import java.security.KeyStore;59import java.security.cert.X509Certificate;60import java.util.Collections;61import java.util.EnumSet;62import java.util.Set;63import java.util.stream.Collectors;64import java.util.stream.Stream;6566public class WeakAlg {6768public static void main(String[] args) throws Throwable {6970rm("ks");7172// Tests for "disabled" algorithms73// -genkeypair, and -printcert, -list -alias, -exportcert74// (w/ different formats)75checkDisabledGenKeyPair("a", "-keyalg RSA -sigalg MD5withRSA", "MD5withRSA");76checkDisabledGenKeyPair("b", "-keyalg RSA -keysize 512", "512-bit RSA key");77checkDisabledGenKeyPair("c", "-keyalg RSA", null);7879kt("-list")80.shouldContain("Warning:")81.shouldMatch("<a>.*MD5withRSA.*is disabled")82.shouldMatch("<b>.*512-bit RSA key.*is disabled");83kt("-list -v")84.shouldContain("Warning:")85.shouldMatch("<a>.*MD5withRSA.*is disabled")86.shouldContain("MD5withRSA (disabled)")87.shouldMatch("<b>.*512-bit RSA key.*is disabled")88.shouldContain("512-bit RSA key (disabled)");8990// Multiple warnings for multiple cert in -printcert91// or -list or -exportcert9293// -certreq, -printcertreq, -gencert94checkDisabledCertReq("a", "", null);95gencert("c-a", "")96.shouldNotContain("Warning"); // new sigalg is not weak97gencert("c-a", "-sigalg MD2withRSA")98.shouldContain("Warning:")99.shouldMatch("The generated certificate.*MD2withRSA.*is disabled");100101checkDisabledCertReq("a", "-sigalg MD5withRSA", "MD5withRSA");102gencert("c-a", "")103.shouldContain("Warning:")104.shouldMatch("The certificate request.*MD5withRSA.*is disabled");105gencert("c-a", "-sigalg MD2withRSA")106.shouldContain("Warning:")107.shouldMatch("The certificate request.*MD5withRSA.*is disabled")108.shouldMatch("The generated certificate.*MD2withRSA.*is disabled");109110checkDisabledCertReq("b", "", "512-bit RSA key");111gencert("c-b", "")112.shouldContain("Warning:")113.shouldMatch("The certificate request.*512-bit RSA key.*is disabled")114.shouldMatch("The generated certificate.*512-bit RSA key.*is disabled");115116checkDisabledCertReq("c", "", null);117gencert("a-c", "")118.shouldContain("Warning:")119.shouldMatch("The issuer.*MD5withRSA.*is disabled");120121// but the new cert is not weak122kt("-printcert -file a-c.cert")123.shouldNotContain("Warning")124.shouldNotContain("(disabled)");125126gencert("b-c", "")127.shouldContain("Warning:")128.shouldMatch("The issuer.*512-bit RSA key.*is disabled");129130// -importcert131checkImport();132133// -importkeystore134checkImportKeyStore();135136// -gencrl, -printcrl137138checkDisabledGenCRL("a", "", null);139checkDisabledGenCRL("a", "-sigalg MD5withRSA", "MD5withRSA");140checkDisabledGenCRL("b", "", "512-bit RSA key");141checkDisabledGenCRL("c", "", null);142143kt("-delete -alias b");144kt("-printcrl -file b.crl")145.shouldContain("WARNING: not verified");146147jksTypeCheck();148149checkInplaceImportKeyStore();150151rm("ks");152153// Tests for "legacy" algorithms154// -genkeypair, and -printcert, -list -alias, -exportcert155// (w/ different formats)156checkWeakGenKeyPair("x", "-keyalg RSA -sigalg SHA1withRSA", "SHA1withRSA");157checkWeakGenKeyPair("y", "-keyalg RSA -keysize 1024", "1024-bit RSA key");158checkWeakGenKeyPair("z", "-keyalg RSA", null);159160kt("-list")161.shouldContain("Warning:")162.shouldMatch("<x>.*SHA1withRSA.*will be disabled")163.shouldMatch("<y>.*1024-bit RSA key.*will be disabled");164kt("-list -v")165.shouldContain("Warning:")166.shouldMatch("<x>.*SHA1withRSA.*will be disabled")167.shouldContain("SHA1withRSA (weak)")168.shouldMatch("<y>.*1024-bit RSA key.*will be disabled")169.shouldContain("1024-bit RSA key (weak)");170171// Multiple warnings for multiple cert in -printcert172// or -list or -exportcert173174// -certreq, -printcertreq, -gencert175checkWeakCertReq("x", "", null);176gencert("z-x", "")177.shouldNotContain("Warning"); // new sigalg is not weak178gencert("z-x", "-sigalg SHA1withRSA")179.shouldContain("Warning:")180.shouldMatch("The generated certificate.*SHA1withRSA.*will be disabled");181182checkWeakCertReq("x", "-sigalg SHA1withRSA", "SHA1withRSA");183gencert("z-x", "")184.shouldContain("Warning:")185.shouldMatch("The certificate request.*SHA1withRSA.*will be disabled");186gencert("z-x", "-sigalg SHA1withRSA")187.shouldContain("Warning:")188.shouldMatch("The certificate request.*SHA1withRSA.*will be disabled")189.shouldMatch("The generated certificate.*SHA1withRSA.*will be disabled");190191checkWeakCertReq("y", "", "1024-bit RSA key");192gencert("z-y", "")193.shouldContain("Warning:")194.shouldMatch("The certificate request.*1024-bit RSA key.*will be disabled")195.shouldMatch("The generated certificate.*1024-bit RSA key.*will be disabled");196197checkWeakCertReq("z", "", null);198gencert("x-z", "")199.shouldContain("Warning:")200.shouldMatch("The issuer.*SHA1withRSA.*will be disabled");201202// but the new cert is not weak203kt("-printcert -file x-z.cert")204.shouldNotContain("Warning")205.shouldNotContain("weak");206207gencert("y-z", "")208.shouldContain("Warning:")209.shouldMatch("The issuer.*1024-bit RSA key.*will be disabled");210211// -gencrl, -printcrl212checkWeakGenCRL("x", "", null);213checkWeakGenCRL("x", "-sigalg SHA1withRSA", "SHA1withRSA");214checkWeakGenCRL("y", "", "1024-bit RSA key");215checkWeakGenCRL("z", "", null);216217kt("-delete -alias y");218kt("-printcrl -file y.crl")219.shouldContain("WARNING: not verified");220221jksTypeCheck();222}223224static void jksTypeCheck() throws Exception {225226// No warning for cacerts, all certs227kt0("-cacerts -list -storepass changeit")228.shouldNotContain("proprietary format");229230rm("ks");231rm("ks2");232233kt("-genkeypair -keyalg DSA -alias a -dname CN=A")234.shouldNotContain("Warning:");235kt("-list")236.shouldNotContain("Warning:");237kt("-list -storetype jks") // no warning if PKCS12 used as JKS238.shouldNotContain("Warning:");239kt("-exportcert -alias a -file a.crt")240.shouldNotContain("Warning:");241242// warn if migrating to JKS243importkeystore("ks", "ks2", "-deststoretype jks")244.shouldContain("JKS keystore uses a proprietary format");245246rm("ks");247rm("ks2");248rm("ks3");249250// no warning if all certs251kt("-importcert -alias b -file a.crt -storetype jks -noprompt")252.shouldNotContain("Warning:");253kt("-genkeypair -keyalg DSA -alias a -dname CN=A")254.shouldContain("JKS keystore uses a proprietary format");255kt("-list")256.shouldContain("JKS keystore uses a proprietary format");257kt("-list -storetype pkcs12") // warn if JKS used as PKCS12258.shouldContain("JKS keystore uses a proprietary format");259kt("-exportcert -alias a -file a.crt")260.shouldContain("JKS keystore uses a proprietary format");261kt("-printcert -file a.crt") // warning since -keystore option is supported262.shouldContain("JKS keystore uses a proprietary format");263kt("-certreq -alias a -file a.req")264.shouldContain("JKS keystore uses a proprietary format");265kt("-printcertreq -file a.req") // no warning if keystore not touched266.shouldNotContain("Warning:");267268// No warning if migrating from JKS269importkeystore("ks", "ks2", "")270.shouldNotContain("Warning:");271272importkeystore("ks", "ks3", "-deststoretype pkcs12")273.shouldNotContain("Warning:");274275rm("ks");276277kt("-genkeypair -keyalg DSA -alias a -dname CN=A -storetype jceks")278.shouldContain("JCEKS keystore uses a proprietary format");279kt("-list")280.shouldContain("JCEKS keystore uses a proprietary format");281kt("-importcert -alias b -file a.crt -noprompt")282.shouldContain("JCEKS keystore uses a proprietary format");283kt("-exportcert -alias a -file a.crt")284.shouldContain("JCEKS keystore uses a proprietary format");285kt("-printcert -file a.crt") // warning since -keystore option is supported286.shouldContain("JCEKS keystore uses a proprietary format");287kt("-certreq -alias a -file a.req")288.shouldContain("JCEKS keystore uses a proprietary format");289kt("-printcertreq -file a.req")290.shouldNotContain("Warning:");291kt("-genseckey -alias c -keyalg AES -keysize 128")292.shouldContain("JCEKS keystore uses a proprietary format");293}294295static void checkImportKeyStore() throws Exception {296297rm("ks2");298rm("ks3");299300importkeystore("ks", "ks2", "")301.shouldContain("3 entries successfully imported")302.shouldContain("Warning")303.shouldMatch("<b>.*512-bit RSA key.*is disabled")304.shouldMatch("<a>.*MD5withRSA.*is disabled");305306importkeystore("ks", "ks3", "-srcalias a")307.shouldContain("Warning")308.shouldMatch("<a>.*MD5withRSA.*is disabled");309}310311static void checkInplaceImportKeyStore() throws Exception {312313rm("ks");314genkeypair("a", "-keyalg DSA");315316// Same type backup317importkeystore("ks", "ks", "")318.shouldContain("Warning:")319.shouldMatch("original.*ks.old");320321importkeystore("ks", "ks", "")322.shouldContain("Warning:")323.shouldMatch("original.*ks.old2");324325importkeystore("ks", "ks", "-srcstoretype jks") // it knows real type326.shouldContain("Warning:")327.shouldMatch("original.*ks.old3");328329String cPath = new File("ks").getCanonicalPath();330331importkeystore("ks", cPath, "")332.shouldContain("Warning:")333.shouldMatch("original.*ks.old4");334335// Migration336importkeystore("ks", "ks", "-deststoretype jks")337.shouldContain("Warning:")338.shouldContain("JKS keystore uses a proprietary format")339.shouldMatch("Migrated.*JKS.*PKCS12.*ks.old5");340341Asserts.assertEQ(342KeyStore.getInstance(343new File("ks"), "changeit".toCharArray()).getType(),344"JKS");345346importkeystore("ks", "ks", "-srcstoretype PKCS12")347.shouldContain("Warning:")348.shouldNotContain("proprietary format")349.shouldMatch("Migrated.*PKCS12.*JKS.*ks.old6");350351Asserts.assertEQ(352KeyStore.getInstance(353new File("ks"), "changeit".toCharArray()).getType(),354"PKCS12");355356Asserts.assertEQ(357KeyStore.getInstance(358new File("ks.old6"), "changeit".toCharArray()).getType(),359"JKS");360361// One password prompt is enough for migration362kt0("-importkeystore -srckeystore ks -destkeystore ks", "changeit")363.shouldMatch("original.*ks.old7");364365// But three if importing to a different keystore366rm("ks2");367kt0("-importkeystore -srckeystore ks -destkeystore ks2",368"changeit")369.shouldContain("Keystore password is too short");370371kt0("-importkeystore -srckeystore ks -destkeystore ks2",372"changeit", "changeit", "changeit")373.shouldContain("Importing keystore ks to ks2...")374.shouldNotContain("original")375.shouldNotContain("Migrated");376}377378static void checkImport() throws Exception {379380saveStore();381382// add trusted cert383384// cert already in385kt("-importcert -alias d -file a.cert", "no")386.shouldContain("Certificate already exists in keystore")387.shouldContain("Warning")388.shouldMatch("The input.*MD5withRSA.*is disabled")389.shouldContain("Do you still want to add it?");390kt("-importcert -alias d -file a.cert -noprompt")391.shouldContain("Warning")392.shouldMatch("The input.*MD5withRSA.*is disabled")393.shouldNotContain("[no]");394395// cert is self-signed396kt("-delete -alias a");397kt("-delete -alias d");398kt("-importcert -alias d -file a.cert", "no")399.shouldContain("Warning")400.shouldContain("MD5withRSA (disabled)")401.shouldMatch("The input.*MD5withRSA.*is disabled")402.shouldContain("Trust this certificate?");403kt("-importcert -alias d -file a.cert -noprompt")404.shouldContain("Warning")405.shouldMatch("The input.*MD5withRSA.*is disabled")406.shouldNotContain("[no]");407408// JDK-8177569: no warning for sigalg of trusted cert409String weakSigAlgCA = null;410KeyStore ks = KeyStoreUtil.getCacertsKeyStore();411if (ks != null) {412DisabledAlgorithmConstraints disabledCheck =413new DisabledAlgorithmConstraints(414DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);415Set<CryptoPrimitive> sigPrimitiveSet = Collections416.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));417418for (String s : Collections.list(ks.aliases())) {419if (ks.isCertificateEntry(s)) {420X509Certificate c = (X509Certificate)ks.getCertificate(s);421String sigAlg = c.getSigAlgName();422if (!disabledCheck.permits(sigPrimitiveSet, sigAlg, null)) {423weakSigAlgCA = sigAlg;424Files.write(Paths.get("ca.cert"),425ks.getCertificate(s).getEncoded());426break;427}428}429}430}431if (weakSigAlgCA != null) {432// The following 2 commands still have a warning on why not using433// the -cacerts option directly.434kt("-list -keystore " + KeyStoreUtil.getCacerts())435.shouldNotMatch("signature algorithm.*risk");436kt("-list -v -keystore " + KeyStoreUtil.getCacerts())437.shouldNotMatch("signature algorithm.*risk");438439// -printcert will always show warnings440kt("-printcert -file ca.cert")441.shouldContain("name: " + weakSigAlgCA + " (disabled)")442.shouldContain("Warning")443.shouldMatch("The certificate.*" + weakSigAlgCA + ".*is disabled");444kt("-printcert -file ca.cert -trustcacerts") // -trustcacerts useless445.shouldContain("name: " + weakSigAlgCA + " (disabled)")446.shouldContain("Warning")447.shouldMatch("The certificate.*" + weakSigAlgCA + ".*is disabled");448449// Importing with -trustcacerts ignore CA cert's sig alg450kt("-delete -alias d");451kt("-importcert -alias d -trustcacerts -file ca.cert", "no")452.shouldContain("Certificate already exists in system-wide CA")453.shouldNotMatch("signature algorithm.*risk")454.shouldContain("Do you still want to add it to your own keystore?");455kt("-importcert -alias d -trustcacerts -file ca.cert -noprompt")456.shouldNotMatch("signature algorithm.*risk")457.shouldNotContain("[no]");458459// but not without -trustcacerts460kt("-delete -alias d");461kt("-importcert -alias d -file ca.cert", "no")462.shouldContain("name: " + weakSigAlgCA + " (disabled)")463.shouldContain("Warning")464.shouldMatch("The input.*" + weakSigAlgCA + ".*is disabled")465.shouldContain("Trust this certificate?");466kt("-importcert -alias d -file ca.cert -noprompt")467.shouldContain("Warning")468.shouldMatch("The input.*" + weakSigAlgCA + ".*is disabled")469.shouldNotContain("[no]");470}471472// a non self-signed weak cert473reStore();474certreq("b", "");475gencert("c-b", "");476kt("-importcert -alias d -file c-b.cert") // weak only, no prompt477.shouldContain("Warning")478.shouldNotContain("512-bit RSA key (disabled)")479.shouldMatch("The input.*512-bit RSA key.*is disabled")480.shouldNotContain("[no]");481482kt("-delete -alias b");483kt("-delete -alias c");484kt("-delete -alias d");485486kt("-importcert -alias d -file c-b.cert", "no") // weak and not trusted487.shouldContain("Warning")488.shouldContain("512-bit RSA key (disabled)")489.shouldMatch("The input.*512-bit RSA key.*is disabled")490.shouldContain("Trust this certificate?");491kt("-importcert -alias d -file c-b.cert -noprompt")492.shouldContain("Warning")493.shouldMatch("The input.*512-bit RSA key.*is disabled")494.shouldNotContain("[no]");495496// a non self-signed strong cert497reStore();498certreq("a", "");499gencert("c-a", "");500kt("-importcert -alias d -file c-a.cert") // trusted501.shouldNotContain("Warning")502.shouldNotContain("[no]");503504kt("-delete -alias a");505kt("-delete -alias c");506kt("-delete -alias d");507508kt("-importcert -alias d -file c-a.cert", "no") // not trusted509.shouldNotContain("Warning")510.shouldContain("Trust this certificate?");511kt("-importcert -alias d -file c-a.cert -noprompt")512.shouldNotContain("Warning")513.shouldNotContain("[no]");514515// install reply516517reStore();518certreq("c", "");519gencert("a-c", "");520kt("-importcert -alias c -file a-c.cert")521.shouldContain("Warning")522.shouldMatch("Issuer <a>.*MD5withRSA.*is disabled");523524// JDK-8177569: no warning for sigalg of trusted cert525reStore();526// Change a into a TrustedCertEntry527kt("-exportcert -alias a -file a.cert");528kt("-delete -alias a");529kt("-importcert -alias a -file a.cert -noprompt");530kt("-list -alias a -v")531.shouldNotContain("disabled")532.shouldNotContain("Warning");533// This time a is trusted and no warning on its weak sig alg534kt("-importcert -alias c -file a-c.cert")535.shouldNotContain("Warning");536537reStore();538539gencert("a-b", "");540gencert("b-c", "");541542// Full chain with root543cat("a-a-b-c.cert", "b-c.cert", "a-b.cert", "a.cert");544kt("-importcert -alias c -file a-a-b-c.cert") // only weak545.shouldContain("Warning")546.shouldMatch("Reply #2 of 3.*512-bit RSA key.*is disabled")547.shouldMatch("Reply #3 of 3.*MD5withRSA.*is disabled")548.shouldNotContain("[no]");549550// Without root551cat("a-b-c.cert", "b-c.cert", "a-b.cert");552kt("-importcert -alias c -file a-b-c.cert") // only weak553.shouldContain("Warning")554.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")555.shouldMatch("Issuer <a>.*MD5withRSA.*is disabled")556.shouldNotContain("[no]");557558reStore();559gencert("b-a", "");560561kt("-importcert -alias a -file b-a.cert")562.shouldContain("Warning")563.shouldMatch("Issuer <b>.*512-bit RSA key.*is disabled")564.shouldNotContain("[no]");565566kt("-importcert -alias a -file c-a.cert")567.shouldNotContain("Warning");568569kt("-importcert -alias b -file c-b.cert")570.shouldContain("Warning")571.shouldMatch("The input.*512-bit RSA key.*is disabled")572.shouldNotContain("[no]");573574reStore();575gencert("b-a", "");576577cat("c-b-a.cert", "b-a.cert", "c-b.cert");578579kt("-printcert -file c-b-a.cert")580.shouldContain("Warning")581.shouldMatch("The certificate #2 of 2.*512-bit RSA key.*is disabled");582583kt("-delete -alias b");584585kt("-importcert -alias a -file c-b-a.cert")586.shouldContain("Warning")587.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")588.shouldNotContain("[no]");589590kt("-delete -alias c");591kt("-importcert -alias a -file c-b-a.cert", "no")592.shouldContain("Top-level certificate in reply:")593.shouldContain("512-bit RSA key (disabled)")594.shouldContain("Warning")595.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")596.shouldContain("Install reply anyway?");597kt("-importcert -alias a -file c-b-a.cert -noprompt")598.shouldContain("Warning")599.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")600.shouldNotContain("[no]");601602reStore();603}604605private static void cat(String dest, String... src) throws IOException {606System.out.println("---------------------------------------------");607System.out.printf("$ cat ");608609ByteArrayOutputStream bout = new ByteArrayOutputStream();610for (String s : src) {611System.out.printf(s + " ");612bout.write(Files.readAllBytes(Paths.get(s)));613}614Files.write(Paths.get(dest), bout.toByteArray());615System.out.println("> " + dest);616}617618static void checkDisabledGenCRL(String alias, String options, String bad) {619620OutputAnalyzer oa = kt("-gencrl -alias " + alias621+ " -id 1 -file " + alias + ".crl " + options);622if (bad == null) {623oa.shouldNotContain("Warning");624} else {625oa.shouldContain("Warning")626.shouldMatch("The generated CRL.*" + bad + ".*is disabled");627}628629oa = kt("-printcrl -file " + alias + ".crl");630if (bad == null) {631oa.shouldNotContain("Warning")632.shouldContain("Verified by " + alias + " in keystore")633.shouldNotContain("(disabled");634} else {635oa.shouldContain("Warning:")636.shouldMatch("The CRL.*" + bad + ".*is disabled")637.shouldContain("Verified by " + alias + " in keystore")638.shouldContain(bad + " (disabled)");639}640}641642static void checkDisabledCertReq(643String alias, String options, String bad) {644645OutputAnalyzer oa = certreq(alias, options);646if (bad == null) {647oa.shouldNotContain("Warning");648} else {649oa.shouldContain("Warning")650.shouldMatch("The generated certificate request.*" + bad + ".*is disabled");651}652653oa = kt("-printcertreq -file " + alias + ".req");654if (bad == null) {655oa.shouldNotContain("Warning")656.shouldNotContain("(disabled)");657} else {658oa.shouldContain("Warning")659.shouldMatch("The certificate request.*" + bad + ".*is disabled")660.shouldContain(bad + " (disabled)");661}662}663664static void checkDisabledGenKeyPair(665String alias, String options, String bad) {666667OutputAnalyzer oa = genkeypair(alias, options);668if (bad == null) {669oa.shouldNotContain("Warning");670} else {671oa.shouldContain("Warning")672.shouldMatch("The generated certificate.*" + bad + ".*is disabled");673}674675oa = kt("-exportcert -alias " + alias + " -file " + alias + ".cert");676if (bad == null) {677oa.shouldNotContain("Warning");678} else {679oa.shouldContain("Warning")680.shouldMatch("The certificate.*" + bad + ".*is disabled");681}682683oa = kt("-exportcert -rfc -alias " + alias + " -file " + alias + ".cert");684if (bad == null) {685oa.shouldNotContain("Warning");686} else {687oa.shouldContain("Warning")688.shouldMatch("The certificate.*" + bad + ".*is disabled");689}690691oa = kt("-printcert -rfc -file " + alias + ".cert");692if (bad == null) {693oa.shouldNotContain("Warning");694} else {695oa.shouldContain("Warning")696.shouldMatch("The certificate.*" + bad + ".*is disabled");697}698699oa = kt("-list -alias " + alias);700if (bad == null) {701oa.shouldNotContain("Warning");702} else {703oa.shouldContain("Warning")704.shouldMatch("The certificate.*" + bad + ".*is disabled");705}706707// With cert content708709oa = kt("-printcert -file " + alias + ".cert");710if (bad == null) {711oa.shouldNotContain("Warning");712} else {713oa.shouldContain("Warning")714.shouldContain(bad + " (disabled)")715.shouldMatch("The certificate.*" + bad + ".*is disabled");716}717718oa = kt("-list -v -alias " + alias);719if (bad == null) {720oa.shouldNotContain("Warning");721} else {722oa.shouldContain("Warning")723.shouldContain(bad + " (disabled)")724.shouldMatch("The certificate.*" + bad + ".*is disabled");725}726}727728static void checkWeakGenKeyPair(729String alias, String options, String bad) {730731OutputAnalyzer oa = genkeypair(alias, options);732if (bad == null) {733oa.shouldNotContain("Warning");734} else {735oa.shouldContain("Warning")736.shouldMatch("The generated certificate.*" + bad + ".*will be disabled");737}738739oa = kt("-exportcert -alias " + alias + " -file " + alias + ".cert");740if (bad == null) {741oa.shouldNotContain("Warning");742} else {743oa.shouldContain("Warning")744.shouldMatch("The certificate.*" + bad + ".*will be disabled");745}746747oa = kt("-exportcert -rfc -alias " + alias + " -file " + alias + ".cert");748if (bad == null) {749oa.shouldNotContain("Warning");750} else {751oa.shouldContain("Warning")752.shouldMatch("The certificate.*" + bad + ".*will be disabled");753}754755oa = kt("-printcert -rfc -file " + alias + ".cert");756if (bad == null) {757oa.shouldNotContain("Warning");758} else {759oa.shouldContain("Warning")760.shouldMatch("The certificate.*" + bad + ".*will be disabled");761}762763oa = kt("-list -alias " + alias);764if (bad == null) {765oa.shouldNotContain("Warning");766} else {767oa.shouldContain("Warning")768.shouldMatch("The certificate.*" + bad + ".*will be disabled");769}770771// With cert content772773oa = kt("-printcert -file " + alias + ".cert");774if (bad == null) {775oa.shouldNotContain("Warning");776} else {777oa.shouldContain("Warning")778.shouldContain(bad + " (weak)")779.shouldMatch("The certificate.*" + bad + ".*will be disabled");780}781782oa = kt("-list -v -alias " + alias);783if (bad == null) {784oa.shouldNotContain("Warning");785} else {786oa.shouldContain("Warning")787.shouldContain(bad + " (weak)")788.shouldMatch("The certificate.*" + bad + ".*will be disabled");789}790}791792793static void checkWeakGenCRL(String alias, String options, String bad) {794795OutputAnalyzer oa = kt("-gencrl -alias " + alias796+ " -id 1 -file " + alias + ".crl " + options);797if (bad == null) {798oa.shouldNotContain("Warning");799} else {800oa.shouldContain("Warning")801.shouldMatch("The generated CRL.*" + bad + ".*will be disabled");802}803804oa = kt("-printcrl -file " + alias + ".crl");805if (bad == null) {806oa.shouldNotContain("Warning")807.shouldContain("Verified by " + alias + " in keystore")808.shouldNotContain("(weak");809} else {810oa.shouldContain("Warning:")811.shouldMatch("The CRL.*" + bad + ".*will be disabled")812.shouldContain("Verified by " + alias + " in keystore")813.shouldContain(bad + " (weak)");814}815}816817static void checkWeakCertReq(818String alias, String options, String bad) {819820OutputAnalyzer oa = certreq(alias, options);821if (bad == null) {822oa.shouldNotContain("Warning");823} else {824oa.shouldContain("Warning")825.shouldMatch("The generated certificate request.*" + bad + ".*will be disabled");826}827828oa = kt("-printcertreq -file " + alias + ".req");829if (bad == null) {830oa.shouldNotContain("Warning")831.shouldNotContain("(weak)");832} else {833oa.shouldContain("Warning")834.shouldMatch("The certificate request.*" + bad + ".*will be disabled")835.shouldContain(bad + " (weak)");836}837}838839// This is slow, but real keytool process is launched.840static OutputAnalyzer kt1(String cmd, String... input) {841cmd = "-keystore ks -storepass changeit " +842"-keypass changeit " + cmd;843System.out.println("---------------------------------------------");844try {845SecurityTools.setResponse(input);846return SecurityTools.keytool(cmd);847} catch (Throwable e) {848throw new RuntimeException(e);849}850}851852static OutputAnalyzer kt(String cmd, String... input) {853return kt0("-keystore ks -storepass changeit " +854"-keypass changeit " + cmd, input);855}856857// Fast keytool execution by directly calling its main() method858static OutputAnalyzer kt0(String cmd, String... input) {859PrintStream out = System.out;860PrintStream err = System.err;861InputStream ins = System.in;862ByteArrayOutputStream bout = new ByteArrayOutputStream();863ByteArrayOutputStream berr = new ByteArrayOutputStream();864boolean succeed = true;865String sout;866String serr;867try {868System.out.println("---------------------------------------------");869System.out.println("$ keytool " + cmd);870System.out.println();871String feed = "";872if (input.length > 0) {873feed = Stream.of(input).collect(Collectors.joining("\n")) + "\n";874}875System.setIn(new ByteArrayInputStream(feed.getBytes()));876System.setOut(new PrintStream(bout));877System.setErr(new PrintStream(berr));878sun.security.tools.keytool.Main.main(879cmd.trim().split("\\s+"));880} catch (Exception e) {881// Might be a normal exception when -debug is on or882// SecurityException (thrown by jtreg) when System.exit() is called883if (!(e instanceof SecurityException)) {884e.printStackTrace();885}886succeed = false;887} finally {888System.setOut(out);889System.setErr(err);890System.setIn(ins);891sout = new String(bout.toByteArray());892serr = new String(berr.toByteArray());893System.out.println("STDOUT:\n" + sout + "\nSTDERR:\n" + serr);894}895if (!succeed) {896throw new RuntimeException();897}898return new OutputAnalyzer(sout, serr);899}900901static OutputAnalyzer importkeystore(String src, String dest,902String options) {903return kt0("-importkeystore "904+ "-srckeystore " + src + " -destkeystore " + dest905+ " -srcstorepass changeit -deststorepass changeit " + options);906}907908static OutputAnalyzer genkeypair(String alias, String options) {909return kt("-genkeypair -alias " + alias + " -dname CN=" + alias910+ " -storetype PKCS12 " + options);911}912913static OutputAnalyzer certreq(String alias, String options) {914return kt("-certreq -alias " + alias915+ " -file " + alias + ".req " + options);916}917918static OutputAnalyzer exportcert(String alias) {919return kt("-exportcert -alias " + alias + " -file " + alias + ".cert");920}921922static OutputAnalyzer gencert(String relation, String options) {923int pos = relation.indexOf("-");924String issuer = relation.substring(0, pos);925String subject = relation.substring(pos + 1);926return kt(" -gencert -alias " + issuer + " -infile " + subject927+ ".req -outfile " + relation + ".cert " + options);928}929930static void saveStore() throws IOException {931System.out.println("---------------------------------------------");932System.out.println("$ cp ks ks2");933Files.copy(Paths.get("ks"), Paths.get("ks2"),934StandardCopyOption.REPLACE_EXISTING);935}936937static void reStore() throws IOException {938System.out.println("---------------------------------------------");939System.out.println("$ cp ks2 ks");940Files.copy(Paths.get("ks2"), Paths.get("ks"),941StandardCopyOption.REPLACE_EXISTING);942}943944static void rm(String s) throws IOException {945System.out.println("---------------------------------------------");946System.out.println("$ rm " + s);947Files.deleteIfExists(Paths.get(s));948}949}950951952