Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/sun/security/tools/keytool/WeakAlg.java
38853 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 /lib/testlibrary29* @run main/othervm/timeout=600 -Duser.language=en -Duser.country=US WeakAlg30*/3132import jdk.testlibrary.Asserts;33import jdk.testlibrary.SecurityTools;34import jdk.testlibrary.OutputAnalyzer;35import sun.security.tools.KeyStoreUtil;36import sun.security.util.DisabledAlgorithmConstraints;3738import java.io.ByteArrayInputStream;39import java.io.ByteArrayOutputStream;40import java.io.File;41import java.io.FileInputStream;42import java.io.IOException;43import java.io.InputStream;44import java.io.PrintStream;45import java.nio.file.Files;46import java.nio.file.Paths;47import java.nio.file.StandardCopyOption;48import java.security.CryptoPrimitive;49import java.security.KeyStore;50import java.security.cert.X509Certificate;51import java.util.Collections;52import java.util.EnumSet;53import java.util.Set;54import java.util.stream.Collectors;55import java.util.stream.Stream;5657public class WeakAlg {5859static String sep = File.separator;60static String cacerts_location = System.getProperty("java.home") +61sep + "lib" + sep + "security" + sep + "cacerts";6263public static void main(String[] args) throws Throwable {6465rm("ks");6667// Tests for "disabled" algorithms68// -genkeypair, and -printcert, -list -alias, -exportcert69// (w/ different formats)70checkDisabledGenKeyPair("a", "-keyalg RSA -sigalg MD5withRSA", "MD5withRSA");71checkDisabledGenKeyPair("b", "-keyalg RSA -keysize 512", "512-bit RSA key");72checkDisabledGenKeyPair("c", "-keyalg RSA", null);7374kt("-list")75.shouldContain("Warning:")76.shouldMatch("<a>.*MD5withRSA.*is disabled")77.shouldMatch("<b>.*512-bit RSA key.*is disabled");78kt("-list -v")79.shouldContain("Warning:")80.shouldMatch("<a>.*MD5withRSA.*is disabled")81.shouldContain("MD5withRSA (disabled)")82.shouldMatch("<b>.*512-bit RSA key.*is disabled")83.shouldContain("512-bit RSA key (disabled)");8485// Multiple warnings for multiple cert in -printcert86// or -list or -exportcert8788// -certreq, -printcertreq, -gencert89checkDisabledCertReq("a", "", null);90gencert("c-a", "")91.shouldNotContain("Warning"); // new sigalg is not weak92gencert("c-a", "-sigalg MD2withRSA")93.shouldContain("Warning:")94.shouldMatch("The generated certificate.*MD2withRSA.*is disabled");9596checkDisabledCertReq("a", "-sigalg MD5withRSA", "MD5withRSA");97gencert("c-a", "")98.shouldContain("Warning:")99.shouldMatch("The certificate request.*MD5withRSA.*is disabled");100gencert("c-a", "-sigalg MD2withRSA")101.shouldContain("Warning:")102.shouldMatch("The certificate request.*MD5withRSA.*is disabled")103.shouldMatch("The generated certificate.*MD2withRSA.*is disabled");104105checkDisabledCertReq("b", "", "512-bit RSA key");106gencert("c-b", "")107.shouldContain("Warning:")108.shouldMatch("The certificate request.*512-bit RSA key.*is disabled")109.shouldMatch("The generated certificate.*512-bit RSA key.*is disabled");110111checkDisabledCertReq("c", "", null);112gencert("a-c", "")113.shouldContain("Warning:")114.shouldMatch("The issuer.*MD5withRSA.*is disabled");115116// but the new cert is not weak117kt("-printcert -file a-c.cert")118.shouldNotContain("Warning")119.shouldNotContain("(disabled)");120121gencert("b-c", "")122.shouldContain("Warning:")123.shouldMatch("The issuer.*512-bit RSA key.*is disabled");124125// -importcert126checkImport();127128// -importkeystore129checkImportKeyStore();130131// -gencrl, -printcrl132133checkDisabledGenCRL("a", "", null);134checkDisabledGenCRL("a", "-sigalg MD5withRSA", "MD5withRSA");135checkDisabledGenCRL("b", "", "512-bit RSA key");136checkDisabledGenCRL("c", "", null);137138kt("-delete -alias b");139kt("-printcrl -file b.crl")140.shouldContain("WARNING: not verified");141142jksTypeCheck();143144checkInplaceImportKeyStore();145146rm("ks");147148// Tests for "legacy" algorithms149// -genkeypair, and -printcert, -list -alias, -exportcert150// (w/ different formats)151checkWeakGenKeyPair("x", "-keyalg RSA -sigalg SHA1withRSA", "SHA1withRSA");152checkWeakGenKeyPair("y", "-keyalg RSA -keysize 1024", "1024-bit RSA key");153checkWeakGenKeyPair("z", "-keyalg RSA", null);154155kt("-list")156.shouldContain("Warning:")157.shouldMatch("<x>.*SHA1withRSA.*will be disabled")158.shouldMatch("<y>.*1024-bit RSA key.*will be disabled");159kt("-list -v")160.shouldContain("Warning:")161.shouldMatch("<x>.*SHA1withRSA.*will be disabled")162.shouldContain("SHA1withRSA (weak)")163.shouldMatch("<y>.*1024-bit RSA key.*will be disabled")164.shouldContain("1024-bit RSA key (weak)");165166// Multiple warnings for multiple cert in -printcert167// or -list or -exportcert168169// -certreq, -printcertreq, -gencert170checkWeakCertReq("x", "", null);171gencert("z-x", "")172.shouldNotContain("Warning"); // new sigalg is not weak173gencert("z-x", "-sigalg SHA1withRSA")174.shouldContain("Warning:")175.shouldMatch("The generated certificate.*SHA1withRSA.*will be disabled");176177checkWeakCertReq("x", "-sigalg SHA1withRSA", "SHA1withRSA");178gencert("z-x", "")179.shouldContain("Warning:")180.shouldMatch("The certificate request.*SHA1withRSA.*will be disabled");181gencert("z-x", "-sigalg SHA1withRSA")182.shouldContain("Warning:")183.shouldMatch("The certificate request.*SHA1withRSA.*will be disabled")184.shouldMatch("The generated certificate.*SHA1withRSA.*will be disabled");185186checkWeakCertReq("y", "", "1024-bit RSA key");187gencert("z-y", "")188.shouldContain("Warning:")189.shouldMatch("The certificate request.*1024-bit RSA key.*will be disabled")190.shouldMatch("The generated certificate.*1024-bit RSA key.*will be disabled");191192checkWeakCertReq("z", "", null);193gencert("x-z", "")194.shouldContain("Warning:")195.shouldMatch("The issuer.*SHA1withRSA.*will be disabled");196197// but the new cert is not weak198kt("-printcert -file x-z.cert")199.shouldNotContain("Warning")200.shouldNotContain("weak");201202gencert("y-z", "")203.shouldContain("Warning:")204.shouldMatch("The issuer.*1024-bit RSA key.*will be disabled");205206// -gencrl, -printcrl207checkWeakGenCRL("x", "", null);208checkWeakGenCRL("x", "-sigalg SHA1withRSA", "SHA1withRSA");209checkWeakGenCRL("y", "", "1024-bit RSA key");210checkWeakGenCRL("z", "", null);211212kt("-delete -alias y");213kt("-printcrl -file y.crl")214.shouldContain("WARNING: not verified");215216jksTypeCheck();217}218219static void jksTypeCheck() throws Exception {220221rm("ks");222rm("ks2");223224kt("-genkeypair -alias a -storetype pkcs12 -dname CN=A")225.shouldNotContain("Warning:");226kt("-list")227.shouldNotContain("Warning:");228kt("-list -storetype jks") // no warning if PKCS12 used as JKS229.shouldNotContain("Warning:");230kt("-exportcert -alias a -file a.crt")231.shouldNotContain("Warning:");232233// warn if migrating to JKS234importkeystore("ks", "ks2", "-deststoretype jks")235.shouldContain("JKS keystore uses a proprietary format");236237rm("ks");238rm("ks2");239rm("ks3");240241// no warning if all certs242kt("-importcert -alias b -file a.crt -storetype jks -noprompt")243.shouldNotContain("Warning:");244kt("-genkeypair -alias a -dname CN=A")245.shouldContain("JKS keystore uses a proprietary format");246kt("-list")247.shouldContain("JKS keystore uses a proprietary format");248kt("-exportcert -alias a -file a.crt")249.shouldContain("JKS keystore uses a proprietary format");250kt("-printcert -file a.crt") // no warning if keystore not touched251.shouldNotContain("Warning:");252kt("-certreq -alias a -file a.req")253.shouldContain("JKS keystore uses a proprietary format");254kt("-printcertreq -file a.req") // no warning if keystore not touched255.shouldNotContain("Warning:");256257// Earlier than JDK 9 defaults to JKS258importkeystore("ks", "ks2", "")259.shouldContain("Warning:");260261importkeystore("ks", "ks3", "-deststoretype pkcs12")262.shouldNotContain("Warning:");263264rm("ks");265266kt("-genkeypair -alias a -dname CN=A -storetype jceks")267.shouldContain("JCEKS keystore uses a proprietary format");268kt("-list -storetype jceks")269.shouldContain("JCEKS keystore uses a proprietary format");270kt("-importcert -alias b -file a.crt -noprompt -storetype jceks")271.shouldContain("JCEKS keystore uses a proprietary format");272kt("-exportcert -alias a -file a.crt -storetype jceks")273.shouldContain("JCEKS keystore uses a proprietary format");274kt("-printcert -file a.crt")275.shouldNotContain("Warning:");276kt("-certreq -alias a -file a.req -storetype jceks")277.shouldContain("JCEKS keystore uses a proprietary format");278kt("-printcertreq -file a.req")279.shouldNotContain("Warning:");280kt("-genseckey -alias c -keyalg AES -keysize 128 -storetype jceks")281.shouldContain("JCEKS keystore uses a proprietary format");282}283284static void checkImportKeyStore() throws Exception {285286rm("ks2");287rm("ks3");288289importkeystore("ks", "ks2", "")290.shouldContain("3 entries successfully imported")291.shouldContain("Warning")292.shouldMatch("<b>.*512-bit RSA key.*is disabled")293.shouldMatch("<a>.*MD5withRSA.*is disabled");294295importkeystore("ks", "ks3", "-srcalias a")296.shouldContain("Warning")297.shouldMatch("<a>.*MD5withRSA.*is disabled");298}299300static void checkInplaceImportKeyStore() throws Exception {301302rm("ks");303genkeypair("a", "");304305// Same type backup306importkeystore("ks", "ks", "")307.shouldContain("Warning:")308.shouldMatch(".*ks.old");309310importkeystore("ks", "ks", "")311.shouldContain("Warning:")312.shouldMatch(".*ks.old2");313314importkeystore("ks", "ks", "-srcstoretype jks") // it knows real type315.shouldContain("Warning:")316.shouldMatch(".*ks.old3");317318String cPath = new File("ks").getCanonicalPath();319320importkeystore("ks", cPath, "")321.shouldContain("Warning:")322.shouldMatch(".*ks.old4");323324// Migration325importkeystore("ks", "ks", "-deststoretype jks")326.shouldContain("Warning:")327.shouldContain("JKS keystore uses a proprietary format")328.shouldMatch("The original.*ks.old5");329330KeyStore test_ks = KeyStore.getInstance("JKS");331test_ks.load(new FileInputStream(new File("ks")),332"changeit".toCharArray());333Asserts.assertEQ(334test_ks.getType(), "JKS");335336importkeystore("ks", "ks", "-deststoretype PKCS12")337.shouldContain("Warning:")338.shouldNotContain("proprietary format")339.shouldMatch("Migrated.*Non.*JKS.*ks.old6");340341test_ks = KeyStore.getInstance("PKCS12");342test_ks.load(new FileInputStream(new File("ks")),343"changeit".toCharArray());344Asserts.assertEQ(345test_ks.getType(), "PKCS12");346347test_ks = KeyStore.getInstance("JKS");348test_ks.load(new FileInputStream(new File("ks.old6")),349"changeit".toCharArray());350Asserts.assertEQ(351test_ks.getType(), "JKS");352353// One password prompt is enough for migration354kt0("-importkeystore -srckeystore ks -destkeystore ks", "changeit")355.shouldMatch("backed.*ks.old7");356357// But three if importing to a different keystore358rm("ks2");359kt0("-importkeystore -srckeystore ks -destkeystore ks2",360"changeit")361.shouldContain("Keystore password is too short");362363kt0("-importkeystore -srckeystore ks -destkeystore ks2",364"changeit", "changeit", "changeit")365.shouldContain("Importing keystore ks to ks2...")366.shouldNotContain("original")367.shouldNotContain("Migrated");368}369370static void checkImport() throws Exception {371372saveStore();373374// add trusted cert375376// cert already in377kt("-importcert -alias d -file a.cert", "no")378.shouldContain("Certificate already exists in keystore")379.shouldContain("Warning")380.shouldMatch("The input.*MD5withRSA.*is disabled")381.shouldContain("Do you still want to add it?");382kt("-importcert -alias d -file a.cert -noprompt")383.shouldContain("Warning")384.shouldMatch("The input.*MD5withRSA.*is disabled")385.shouldNotContain("[no]");386387// cert is self-signed388kt("-delete -alias a");389kt("-delete -alias d");390kt("-importcert -alias d -file a.cert", "no")391.shouldContain("Warning")392.shouldContain("MD5withRSA (disabled)")393.shouldMatch("The input.*MD5withRSA.*is disabled")394.shouldContain("Trust this certificate?");395kt("-importcert -alias d -file a.cert -noprompt")396.shouldContain("Warning")397.shouldMatch("The input.*MD5withRSA.*is disabled")398.shouldNotContain("[no]");399400// JDK-8177569: no warning for sigalg of trusted cert401String weakSigAlgCA = null;402KeyStore ks = KeyStoreUtil.getCacertsKeyStore();403if (ks != null) {404DisabledAlgorithmConstraints disabledCheck =405new DisabledAlgorithmConstraints(406DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);407Set<CryptoPrimitive> sigPrimitiveSet = Collections408.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));409410for (String s : Collections.list(ks.aliases())) {411if (ks.isCertificateEntry(s)) {412X509Certificate c = (X509Certificate)ks.getCertificate(s);413String sigAlg = c.getSigAlgName();414if (!disabledCheck.permits(sigPrimitiveSet, sigAlg, null)) {415weakSigAlgCA = sigAlg;416Files.write(Paths.get("ca.cert"),417ks.getCertificate(s).getEncoded());418break;419}420}421}422}423if (weakSigAlgCA != null) {424// The following 2 commands still have a warning on why not using425// the -cacerts option directly.426kt("-list -keystore " + cacerts_location)427.shouldNotContain("risk");428kt("-list -v -keystore " + cacerts_location)429.shouldNotContain("risk");430431// -printcert will always show warnings432kt("-printcert -file ca.cert")433.shouldContain("name: " + weakSigAlgCA + " (disabled)")434.shouldContain("Warning")435.shouldMatch("The certificate.*" + weakSigAlgCA + ".*is disabled");436kt("-printcert -file ca.cert -trustcacerts") // -trustcacerts useless437.shouldContain("name: " + weakSigAlgCA + " (disabled)")438.shouldContain("Warning")439.shouldMatch("The certificate.*" + weakSigAlgCA + ".*is disabled");440441// Importing with -trustcacerts ignore CA cert's sig alg442kt("-delete -alias d");443kt("-importcert -alias d -trustcacerts -file ca.cert", "no")444.shouldContain("Certificate already exists in system-wide CA")445.shouldNotContain("risk")446.shouldContain("Do you still want to add it to your own keystore?");447kt("-importcert -alias d -trustcacerts -file ca.cert -noprompt")448.shouldNotContain("risk")449.shouldNotContain("[no]");450451// but not without -trustcacerts452kt("-delete -alias d");453kt("-importcert -alias d -file ca.cert", "no")454.shouldContain("name: " + weakSigAlgCA + " (disabled)")455.shouldContain("Warning")456.shouldMatch("The input.*" + weakSigAlgCA + ".*is disabled")457.shouldContain("Trust this certificate?");458kt("-importcert -alias d -file ca.cert -noprompt")459.shouldContain("Warning")460.shouldMatch("The input.*" + weakSigAlgCA + ".*is disabled")461.shouldNotContain("[no]");462}463464// a non self-signed weak cert465reStore();466certreq("b", "");467gencert("c-b", "");468kt("-importcert -alias d -file c-b.cert") // weak only, no prompt469.shouldContain("Warning")470.shouldNotContain("512-bit RSA key (disabled)")471.shouldMatch("The input.*512-bit RSA key.*is disabled")472.shouldNotContain("[no]");473474kt("-delete -alias b");475kt("-delete -alias c");476kt("-delete -alias d");477478kt("-importcert -alias d -file c-b.cert", "no") // weak and not trusted479.shouldContain("Warning")480.shouldContain("512-bit RSA key (disabled)")481.shouldMatch("The input.*512-bit RSA key.*is disabled")482.shouldContain("Trust this certificate?");483kt("-importcert -alias d -file c-b.cert -noprompt")484.shouldContain("Warning")485.shouldMatch("The input.*512-bit RSA key.*is disabled")486.shouldNotContain("[no]");487488// a non self-signed strong cert489reStore();490certreq("a", "");491gencert("c-a", "");492kt("-importcert -alias d -file c-a.cert") // trusted493.shouldNotContain("Warning")494.shouldNotContain("[no]");495496kt("-delete -alias a");497kt("-delete -alias c");498kt("-delete -alias d");499500kt("-importcert -alias d -file c-a.cert", "no") // not trusted501.shouldNotContain("Warning")502.shouldContain("Trust this certificate?");503kt("-importcert -alias d -file c-a.cert -noprompt")504.shouldNotContain("Warning")505.shouldNotContain("[no]");506507// install reply508509reStore();510certreq("c", "");511gencert("a-c", "");512kt("-importcert -alias c -file a-c.cert")513.shouldContain("Warning")514.shouldMatch("Issuer <a>.*MD5withRSA.*is disabled");515516// JDK-8177569: no warning for sigalg of trusted cert517reStore();518// Change a into a TrustedCertEntry519kt("-exportcert -alias a -file a.cert");520kt("-delete -alias a");521kt("-importcert -alias a -file a.cert -noprompt");522kt("-list -alias a -v")523.shouldNotContain("disabled")524.shouldNotContain("Warning");525// This time a is trusted and no warning on its weak sig alg526kt("-importcert -alias c -file a-c.cert")527.shouldNotContain("Warning");528529reStore();530531gencert("a-b", "");532gencert("b-c", "");533534// Full chain with root535cat("a-a-b-c.cert", "b-c.cert", "a-b.cert", "a.cert");536kt("-importcert -alias c -file a-a-b-c.cert") // only weak537.shouldContain("Warning")538.shouldMatch("Reply #2 of 3.*512-bit RSA key.*is disabled")539.shouldMatch("Reply #3 of 3.*MD5withRSA.*is disabled")540.shouldNotContain("[no]");541542// Without root543cat("a-b-c.cert", "b-c.cert", "a-b.cert");544kt("-importcert -alias c -file a-b-c.cert") // only weak545.shouldContain("Warning")546.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")547.shouldMatch("Issuer <a>.*MD5withRSA.*is disabled")548.shouldNotContain("[no]");549550reStore();551gencert("b-a", "");552553kt("-importcert -alias a -file b-a.cert")554.shouldContain("Warning")555.shouldMatch("Issuer <b>.*512-bit RSA key.*is disabled")556.shouldNotContain("[no]");557558kt("-importcert -alias a -file c-a.cert")559.shouldNotContain("Warning");560561kt("-importcert -alias b -file c-b.cert")562.shouldContain("Warning")563.shouldMatch("The input.*512-bit RSA key.*is disabled")564.shouldNotContain("[no]");565566reStore();567gencert("b-a", "");568569cat("c-b-a.cert", "b-a.cert", "c-b.cert");570571kt("-printcert -file c-b-a.cert")572.shouldContain("Warning")573.shouldMatch("The certificate #2 of 2.*512-bit RSA key.*is disabled");574575kt("-delete -alias b");576577kt("-importcert -alias a -file c-b-a.cert")578.shouldContain("Warning")579.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")580.shouldNotContain("[no]");581582kt("-delete -alias c");583kt("-importcert -alias a -file c-b-a.cert", "no")584.shouldContain("Top-level certificate in reply:")585.shouldContain("512-bit RSA key (disabled)")586.shouldContain("Warning")587.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")588.shouldContain("Install reply anyway?");589kt("-importcert -alias a -file c-b-a.cert -noprompt")590.shouldContain("Warning")591.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")592.shouldNotContain("[no]");593594reStore();595}596597private static void cat(String dest, String... src) throws IOException {598System.out.println("---------------------------------------------");599System.out.printf("$ cat ");600601ByteArrayOutputStream bout = new ByteArrayOutputStream();602for (String s : src) {603System.out.printf(s + " ");604bout.write(Files.readAllBytes(Paths.get(s)));605}606Files.write(Paths.get(dest), bout.toByteArray());607System.out.println("> " + dest);608}609610static void checkDisabledGenCRL(String alias, String options, String bad) {611612OutputAnalyzer oa = kt("-gencrl -alias " + alias613+ " -id 1 -file " + alias + ".crl " + options);614if (bad == null) {615oa.shouldNotContain("Warning");616} else {617oa.shouldContain("Warning")618.shouldMatch("The generated CRL.*" + bad + ".*is disabled");619}620621oa = kt("-printcrl -file " + alias + ".crl");622if (bad == null) {623oa.shouldNotContain("Warning")624.shouldContain("Verified by " + alias + " in keystore")625.shouldNotContain("(disabled");626} else {627oa.shouldContain("Warning:")628.shouldMatch("The CRL.*" + bad + ".*is disabled")629.shouldContain("Verified by " + alias + " in keystore")630.shouldContain(bad + " (disabled)");631}632}633634static void checkDisabledCertReq(635String alias, String options, String bad) {636637OutputAnalyzer oa = certreq(alias, options);638if (bad == null) {639oa.shouldNotContain("Warning");640} else {641oa.shouldContain("Warning")642.shouldMatch("The generated certificate request.*" + bad + ".*is disabled");643}644645oa = kt("-printcertreq -file " + alias + ".req");646if (bad == null) {647oa.shouldNotContain("Warning")648.shouldNotContain("(disabled)");649} else {650oa.shouldContain("Warning")651.shouldMatch("The certificate request.*" + bad + ".*is disabled")652.shouldContain(bad + " (disabled)");653}654}655656static void checkDisabledGenKeyPair(657String alias, String options, String bad) {658659OutputAnalyzer oa = genkeypair(alias, options);660if (bad == null) {661oa.shouldNotContain("Warning");662} else {663oa.shouldContain("Warning")664.shouldMatch("The generated certificate.*" + bad + ".*is disabled");665}666667oa = kt("-exportcert -alias " + alias + " -file " + alias + ".cert");668if (bad == null) {669oa.shouldNotContain("Warning");670} else {671oa.shouldContain("Warning")672.shouldMatch("The certificate.*" + bad + ".*is disabled");673}674675oa = kt("-exportcert -rfc -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("-printcert -rfc -file " + alias + ".cert");684if (bad == null) {685oa.shouldNotContain("Warning");686} else {687oa.shouldContain("Warning")688.shouldMatch("The certificate.*" + bad + ".*is disabled");689}690691oa = kt("-list -alias " + alias);692if (bad == null) {693oa.shouldNotContain("Warning");694} else {695oa.shouldContain("Warning")696.shouldMatch("The certificate.*" + bad + ".*is disabled");697}698699// With cert content700701oa = kt("-printcert -file " + alias + ".cert");702if (bad == null) {703oa.shouldNotContain("Warning");704} else {705oa.shouldContain("Warning")706.shouldContain(bad + " (disabled)")707.shouldMatch("The certificate.*" + bad + ".*is disabled");708}709710oa = kt("-list -v -alias " + alias);711if (bad == null) {712oa.shouldNotContain("Warning");713} else {714oa.shouldContain("Warning")715.shouldContain(bad + " (disabled)")716.shouldMatch("The certificate.*" + bad + ".*is disabled");717}718}719720static void checkWeakGenKeyPair(721String alias, String options, String bad) {722723OutputAnalyzer oa = genkeypair(alias, options);724if (bad == null) {725oa.shouldNotContain("Warning");726} else {727oa.shouldContain("Warning")728.shouldMatch("The generated certificate.*" + bad + ".*will be disabled");729}730731oa = kt("-exportcert -alias " + alias + " -file " + alias + ".cert");732if (bad == null) {733oa.shouldNotContain("Warning");734} else {735oa.shouldContain("Warning")736.shouldMatch("The certificate.*" + bad + ".*will be disabled");737}738739oa = kt("-exportcert -rfc -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("-printcert -rfc -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("-list -alias " + alias);756if (bad == null) {757oa.shouldNotContain("Warning");758} else {759oa.shouldContain("Warning")760.shouldMatch("The certificate.*" + bad + ".*will be disabled");761}762763// With cert content764765oa = kt("-printcert -file " + alias + ".cert");766if (bad == null) {767oa.shouldNotContain("Warning");768} else {769oa.shouldContain("Warning")770.shouldContain(bad + " (weak)")771.shouldMatch("The certificate.*" + bad + ".*will be disabled");772}773774oa = kt("-list -v -alias " + alias);775if (bad == null) {776oa.shouldNotContain("Warning");777} else {778oa.shouldContain("Warning")779.shouldContain(bad + " (weak)")780.shouldMatch("The certificate.*" + bad + ".*will be disabled");781}782}783784785static void checkWeakGenCRL(String alias, String options, String bad) {786787OutputAnalyzer oa = kt("-gencrl -alias " + alias788+ " -id 1 -file " + alias + ".crl " + options);789if (bad == null) {790oa.shouldNotContain("Warning");791} else {792oa.shouldContain("Warning")793.shouldMatch("The generated CRL.*" + bad + ".*will be disabled");794}795796oa = kt("-printcrl -file " + alias + ".crl");797if (bad == null) {798oa.shouldNotContain("Warning")799.shouldContain("Verified by " + alias + " in keystore")800.shouldNotContain("(weak");801} else {802oa.shouldContain("Warning:")803.shouldMatch("The CRL.*" + bad + ".*will be disabled")804.shouldContain("Verified by " + alias + " in keystore")805.shouldContain(bad + " (weak)");806}807}808809static void checkWeakCertReq(810String alias, String options, String bad) {811812OutputAnalyzer oa = certreq(alias, options);813if (bad == null) {814oa.shouldNotContain("Warning");815} else {816oa.shouldContain("Warning")817.shouldMatch("The generated certificate request.*" + bad + ".*will be disabled");818}819820oa = kt("-printcertreq -file " + alias + ".req");821if (bad == null) {822oa.shouldNotContain("Warning")823.shouldNotContain("(weak)");824} else {825oa.shouldContain("Warning")826.shouldMatch("The certificate request.*" + bad + ".*will be disabled")827.shouldContain(bad + " (weak)");828}829}830831// This is slow, but real keytool process is launched.832static OutputAnalyzer kt1(String cmd, String... input) {833cmd = "-keystore ks -storepass changeit " +834"-keypass changeit " + cmd;835System.out.println("---------------------------------------------");836try {837SecurityTools.setResponse(input);838return SecurityTools.keytool(cmd);839} catch (Throwable e) {840throw new RuntimeException(e);841}842}843844static OutputAnalyzer kt(String cmd, String... input) {845return kt0("-keystore ks -storepass changeit " +846"-keypass changeit " + cmd, input);847}848849// Fast keytool execution by directly calling its main() method850static OutputAnalyzer kt0(String cmd, String... input) {851PrintStream out = System.out;852PrintStream err = System.err;853InputStream ins = System.in;854ByteArrayOutputStream bout = new ByteArrayOutputStream();855ByteArrayOutputStream berr = new ByteArrayOutputStream();856boolean succeed = true;857String sout;858String serr;859try {860System.out.println("---------------------------------------------");861System.out.println("$ keytool " + cmd);862System.out.println();863String feed = "";864if (input.length > 0) {865feed = Stream.of(input).collect(Collectors.joining("\n")) + "\n";866}867System.setIn(new ByteArrayInputStream(feed.getBytes()));868System.setOut(new PrintStream(bout));869System.setErr(new PrintStream(berr));870sun.security.tools.keytool.Main.main(871cmd.trim().split("\\s+"));872} catch (Exception e) {873// Might be a normal exception when -debug is on or874// SecurityException (thrown by jtreg) when System.exit() is called875if (!(e instanceof SecurityException)) {876e.printStackTrace();877}878succeed = false;879} finally {880System.setOut(out);881System.setErr(err);882System.setIn(ins);883sout = new String(bout.toByteArray());884serr = new String(berr.toByteArray());885System.out.println("STDOUT:\n" + sout + "\nSTDERR:\n" + serr);886}887if (!succeed) {888throw new RuntimeException();889}890return new OutputAnalyzer(sout, serr);891}892893static OutputAnalyzer importkeystore(String src, String dest,894String options) {895return kt0("-importkeystore "896+ "-srckeystore " + src + " -destkeystore " + dest897+ " -srcstorepass changeit -deststorepass changeit " + options);898}899900static OutputAnalyzer genkeypair(String alias, String options) {901return kt("-genkeypair -alias " + alias + " -dname CN=" + alias902+ " -keyalg RSA -storetype PKCS12 " + options);903}904905static OutputAnalyzer certreq(String alias, String options) {906return kt("-certreq -alias " + alias907+ " -file " + alias + ".req " + options);908}909910static OutputAnalyzer exportcert(String alias) {911return kt("-exportcert -alias " + alias + " -file " + alias + ".cert");912}913914static OutputAnalyzer gencert(String relation, String options) {915int pos = relation.indexOf("-");916String issuer = relation.substring(0, pos);917String subject = relation.substring(pos + 1);918return kt(" -gencert -alias " + issuer + " -infile " + subject919+ ".req -outfile " + relation + ".cert " + options);920}921922static void saveStore() throws IOException {923System.out.println("---------------------------------------------");924System.out.println("$ cp ks ks2");925Files.copy(Paths.get("ks"), Paths.get("ks2"),926StandardCopyOption.REPLACE_EXISTING);927}928929static void reStore() throws IOException {930System.out.println("---------------------------------------------");931System.out.println("$ cp ks2 ks");932Files.copy(Paths.get("ks2"), Paths.get("ks"),933StandardCopyOption.REPLACE_EXISTING);934}935936static void rm(String s) throws IOException {937System.out.println("---------------------------------------------");938System.out.println("$ rm " + s);939Files.deleteIfExists(Paths.get(s));940}941}942943944