8172404: Tools should warn if weak algorithms are used before restricting them

Reviewed-by: mullan, weijun
This commit is contained in:
Hai-May Chao 2020-04-17 20:11:39 +08:00 committed by Weijun Wang
parent 9735678c26
commit f04a7e5cb4
14 changed files with 713 additions and 228 deletions

View File

@ -194,6 +194,10 @@ public final class Main {
new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
private static final DisabledAlgorithmConstraints LEGACY_CHECK =
new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_SECURITY_LEGACY_ALGS);
private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
private boolean isPasswordlessKeyStore = false;
@ -3320,9 +3324,13 @@ public final class Main {
private String withWeak(String alg) {
if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, alg, null)) {
return alg;
if (LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, alg, null)) {
return alg;
} else {
return String.format(rb.getString("with.weak"), alg);
}
} else {
return String.format(rb.getString("with.weak"), alg);
return String.format(rb.getString("with.disabled"), alg);
}
}
@ -3341,13 +3349,17 @@ public final class Main {
int kLen = KeyUtil.getKeySize(key);
String displayAlg = fullDisplayAlgName(key);
if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
if (kLen >= 0) {
return String.format(rb.getString("key.bit"), kLen, displayAlg);
if (LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
if (kLen >= 0) {
return String.format(rb.getString("key.bit"), kLen, displayAlg);
} else {
return String.format(rb.getString("unknown.size.1"), displayAlg);
}
} else {
return String.format(rb.getString("unknown.size.1"), displayAlg);
return String.format(rb.getString("key.bit.weak"), kLen, displayAlg);
}
} else {
return String.format(rb.getString("key.bit.weak"), kLen, displayAlg);
return String.format(rb.getString("key.bit.disabled"), kLen, displayAlg);
}
}
@ -4651,18 +4663,28 @@ public final class Main {
}
private void checkWeak(String label, String sigAlg, Key key) {
if (sigAlg != null && !DISABLED_CHECK.permits(
SIG_PRIMITIVE_SET, sigAlg, null)) {
weakWarnings.add(String.format(
rb.getString("whose.sigalg.risk"), label, sigAlg));
if (sigAlg != null) {
if (!DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, sigAlg, null)) {
weakWarnings.add(String.format(
rb.getString("whose.sigalg.disabled"), label, sigAlg));
} else if (!LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, sigAlg, null)) {
weakWarnings.add(String.format(
rb.getString("whose.sigalg.weak"), label, sigAlg));
}
}
if (key != null && !DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
weakWarnings.add(String.format(
rb.getString("whose.key.risk"),
label,
if (key != null) {
if (!DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
weakWarnings.add(String.format(
rb.getString("whose.key.disabled"), label,
String.format(rb.getString("key.bit"),
KeyUtil.getKeySize(key), fullDisplayAlgName(key))));
KeyUtil.getKeySize(key), fullDisplayAlgName(key))));
} else if (!LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
weakWarnings.add(String.format(
rb.getString("whose.key.weak"), label,
String.format(rb.getString("key.bit"),
KeyUtil.getKeySize(key), fullDisplayAlgName(key))));
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -459,8 +459,10 @@ public class Resources extends java.util.ListResourceBundle {
{"alias.in.cacerts", "Issuer <%s> in cacerts"},
{"alias.in.keystore", "Issuer <%s>"},
{"with.weak", "%s (weak)"},
{"with.disabled", "%s (disabled)"},
{"key.bit", "%1$d-bit %2$s key"},
{"key.bit.weak", "%1$d-bit %2$s key (weak)"},
{"key.bit.disabled", "%1$d-bit %2$s key (disabled)"},
{"unknown.size.1", "%s key of unknown size"},
{".PATTERN.printX509Cert.with.weak",
"Owner: {0}\nIssuer: {1}\nSerial number: {2}\nValid from: {3} until: {4}\nCertificate fingerprints:\n\t SHA1: {5}\n\t SHA256: {6}\nSignature algorithm name: {7}\nSubject Public Key Algorithm: {8}\nVersion: {9}"},
@ -468,8 +470,10 @@ public class Resources extends java.util.ListResourceBundle {
"PKCS #10 Certificate Request (Version 1.0)\n" +
"Subject: %1$s\nFormat: %2$s\nPublic Key: %3$s\nSignature algorithm: %4$s\n"},
{"verified.by.s.in.s.weak", "Verified by %1$s in %2$s with a %3$s"},
{"whose.sigalg.risk", "%1$s uses the %2$s signature algorithm which is considered a security risk."},
{"whose.key.risk", "%1$s uses a %2$s which is considered a security risk."},
{"whose.sigalg.disabled", "%1$s uses the %2$s signature algorithm which is considered a security risk and is disabled."},
{"whose.sigalg.weak", "%1$s uses the %2$s signature algorithm which is considered a security risk. This algorithm will be disabled in a future update."},
{"whose.key.disabled", "%1$s uses a %2$s which is considered a security risk and is disabled."},
{"whose.key.weak", "%1$s uses a %2$s which is considered a security risk. This key size will be disabled in a future update."},
{"jks.storetype.warning", "The %1$s keystore uses a proprietary format. It is recommended to migrate to PKCS12 which is an industry standard format using \"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12\"."},
{"migrate.keystore.warning", "Migrated \"%1$s\" to %4$s. The %2$s keystore is backed up as \"%3$s\"."},
{"backup.keystore.warning", "The original keystore \"%1$s\" is backed up as \"%3$s\"..."},

View File

@ -63,6 +63,10 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
public static final String PROPERTY_CERTPATH_DISABLED_ALGS =
"jdk.certpath.disabledAlgorithms";
// Legacy algorithm security property for certificate path and jar
public static final String PROPERTY_SECURITY_LEGACY_ALGS =
"jdk.security.legacyAlgorithms";
// Disabled algorithm security property for TLS
public static final String PROPERTY_TLS_DISABLED_ALGS =
"jdk.tls.disabledAlgorithms";
@ -948,4 +952,3 @@ public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
}
}
}

View File

@ -659,6 +659,26 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, SHA1 jdkCA & usage TLSServer, \
RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224, \
include jdk.disabled.namedCurves
#
# Legacy algorithms for certification path (CertPath) processing and
# signed JAR files.
#
# In some environments, a certain algorithm or key length may be undesirable
# but is not yet disabled.
#
# Tools such as keytool and jarsigner may emit warnings when these legacy
# algorithms are used. See the man pages for those tools for more information.
#
# The syntax is the same as the "jdk.certpath.disabledAlgorithms" and
# "jdk.jar.disabledAlgorithms" security properties.
#
# Note: This property is currently used by the JDK Reference
# implementation. It is not guaranteed to be examined and used by other
# implementations.
jdk.security.legacyAlgorithms=SHA1, \
RSA keySize < 2048, DSA keySize < 2048
#
# Algorithm restrictions for signed JAR files
#

View File

@ -99,6 +99,10 @@ public class Main {
new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
private static final DisabledAlgorithmConstraints LEGACY_CHECK =
new DisabledAlgorithmConstraints(
DisabledAlgorithmConstraints.PROPERTY_SECURITY_LEGACY_ALGS);
private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET = Collections
.unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
@ -172,6 +176,11 @@ public class Main {
// If there is a time stamp block inside the PKCS7 block file
boolean hasTimestampBlock = false;
private PublicKey weakPublicKey = null;
private boolean disabledAlgFound = false;
private String legacyDigestAlg = null;
private String legacyTsaDigestAlg = null;
private String legacySigAlg = null;
// Severe warnings.
@ -182,7 +191,8 @@ public class Main {
// only tsaChainNotValidated is set, i.e. has no affect on hasExpiredCert,
// notYetValidCert, or any badXyzUsage.
private int weakAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg
private int legacyAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg, 8. key
private int disabledAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg, 8. key
private boolean hasExpiredCert = false;
private boolean hasExpiredTsaCert = false;
private boolean notYetValidCert = false;
@ -199,8 +209,6 @@ public class Main {
private Throwable chainNotValidatedReason = null;
private Throwable tsaChainNotValidatedReason = null;
private boolean seeWeak = false;
PKIXBuilderParameters pkixParameters;
Set<X509Certificate> trustedCerts = new HashSet<>();
@ -289,7 +297,7 @@ public class Main {
if (strict) {
int exitCode = 0;
if (weakAlg != 0 || chainNotValidated || hasExpiredCert
if (disabledAlg != 0 || chainNotValidated || hasExpiredCert
|| hasExpiredTsaCert || notYetValidCert || signerSelfSigned) {
exitCode |= 4;
}
@ -910,7 +918,7 @@ public class Main {
}
// Even if the verbose option is not specified, all out strings
// must be generated so seeWeak can be updated.
// must be generated so disabledAlgFound can be updated.
if (!digestMap.isEmpty()
|| !sigMap.isEmpty()
|| !unparsableSignatures.isEmpty()) {
@ -954,21 +962,21 @@ public class Main {
history = String.format(
rb.getString("history.with.ts"),
signer.getSubjectX500Principal(),
withWeak(digestAlg, DIGEST_PRIMITIVE_SET),
withWeak(sigAlg, SIG_PRIMITIVE_SET),
withWeak(key),
verifyWithWeak(digestAlg, DIGEST_PRIMITIVE_SET, false),
verifyWithWeak(sigAlg, SIG_PRIMITIVE_SET, false),
verifyWithWeak(key),
c,
tsSigner.getSubjectX500Principal(),
withWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET),
withWeak(tsSigAlg, SIG_PRIMITIVE_SET),
withWeak(tsKey));
verifyWithWeak(tsDigestAlg, DIGEST_PRIMITIVE_SET, true),
verifyWithWeak(tsSigAlg, SIG_PRIMITIVE_SET, true),
verifyWithWeak(tsKey));
} else {
history = String.format(
rb.getString("history.without.ts"),
signer.getSubjectX500Principal(),
withWeak(digestAlg, DIGEST_PRIMITIVE_SET),
withWeak(sigAlg, SIG_PRIMITIVE_SET),
withWeak(key));
verifyWithWeak(digestAlg, DIGEST_PRIMITIVE_SET, false),
verifyWithWeak(sigAlg, SIG_PRIMITIVE_SET, false),
verifyWithWeak(key));
}
} catch (Exception e) {
// The only usage of sigNameMap, remember the name
@ -992,8 +1000,9 @@ public class Main {
}
}
System.out.println();
if (!anySigned) {
if (seeWeak) {
if (disabledAlgFound) {
if (verbose != null) {
System.out.println(rb.getString("jar.treated.unsigned.see.weak.verbose"));
System.out.println("\n " +
@ -1036,8 +1045,8 @@ public class Main {
if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
notYetValidCert || chainNotValidated || hasExpiredCert ||
hasUnsignedEntry || signerSelfSigned || (weakAlg != 0) ||
aliasNotInStore || notSignedByAlias ||
hasUnsignedEntry || signerSelfSigned || (legacyAlg != 0) ||
(disabledAlg != 0) || aliasNotInStore || notSignedByAlias ||
tsaChainNotValidated ||
(hasExpiredTsaCert && !signerNotExpired)) {
@ -1119,28 +1128,75 @@ public class Main {
: rb.getString("This.jar.contains.entries.whose.signer.certificate.is.self.signed."));
}
// weakAlg only detected in signing. The jar file is
// now simply treated unsigned in verifying.
if ((weakAlg & 1) == 1) {
errors.add(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
digestalg, "-digestalg"));
}
if (isSigning) {
if ((legacyAlg & 1) == 1) {
warnings.add(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update."),
digestalg, "-digestalg"));
}
if ((weakAlg & 2) == 2) {
errors.add(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
sigalg, "-sigalg"));
}
if ((weakAlg & 4) == 4) {
errors.add(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
tSADigestAlg, "-tsadigestalg"));
}
if ((weakAlg & 8) == 8) {
errors.add(String.format(
rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk."),
privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey)));
if ((disabledAlg & 1) == 1) {
errors.add(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.and.is.disabled."),
digestalg, "-digestalg"));
}
if ((legacyAlg & 2) == 2) {
warnings.add(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update."),
sigalg, "-sigalg"));
}
if ((disabledAlg & 2) == 2) {
errors.add(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.and.is.disabled."),
sigalg, "-sigalg"));
}
if ((legacyAlg & 4) == 4) {
warnings.add(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update."),
tSADigestAlg, "-tsadigestalg"));
}
if ((disabledAlg & 4) == 4) {
errors.add(String.format(
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.and.is.disabled."),
tSADigestAlg, "-tsadigestalg"));
}
if ((legacyAlg & 8) == 8) {
warnings.add(String.format(
rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk..This.key.size.will.be.disabled.in.a.future.update."),
privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey)));
}
if ((disabledAlg & 8) == 8) {
errors.add(String.format(
rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.and.is.disabled."),
privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey)));
}
} else {
if ((legacyAlg & 1) != 0) {
warnings.add(String.format(
rb.getString("The.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update."),
legacyDigestAlg));
}
if ((legacyAlg & 2) == 2) {
warnings.add(String.format(
rb.getString("The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update."),
legacySigAlg));
}
if ((legacyAlg & 4) != 0) {
warnings.add(String.format(
rb.getString("The.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update."),
legacyTsaDigestAlg));
}
if ((legacyAlg & 8) == 8) {
warnings.add(String.format(
rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk..This.key.size.will.be.disabled.in.a.future.update."),
weakPublicKey.getAlgorithm(), KeyUtil.getKeySize(weakPublicKey)));
}
}
} else {
result = isSigning ? rb.getString("jar.signed.") : rb.getString("jar.verified.");
@ -1249,27 +1305,84 @@ public class Main {
}
}
private String withWeak(String alg, Set<CryptoPrimitive> primitiveSet) {
private String verifyWithWeak(String alg, Set<CryptoPrimitive> primitiveSet, boolean tsa) {
if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
return alg;
if (LEGACY_CHECK.permits(primitiveSet, alg, null)) {
return alg;
} else {
if (primitiveSet == SIG_PRIMITIVE_SET) {
legacyAlg |= 2;
legacySigAlg = alg;
} else {
if (tsa) {
legacyAlg |= 4;
legacyTsaDigestAlg = alg;
} else {
legacyAlg |= 1;
legacyDigestAlg = alg;
}
}
return String.format(rb.getString("with.weak"), alg);
}
} else {
seeWeak = true;
return String.format(rb.getString("with.weak"), alg);
disabledAlgFound = true;
return String.format(rb.getString("with.disabled"), alg);
}
}
private String withWeak(PublicKey key) {
private String verifyWithWeak(PublicKey key) {
int kLen = KeyUtil.getKeySize(key);
if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
int kLen = KeyUtil.getKeySize(key);
if (kLen >= 0) {
return String.format(rb.getString("key.bit"), kLen);
if (LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
if (kLen >= 0) {
return String.format(rb.getString("key.bit"), kLen);
} else {
return rb.getString("unknown.size");
}
} else {
return rb.getString("unknown.size");
weakPublicKey = key;
legacyAlg |= 8;
return String.format(rb.getString("key.bit.weak"), kLen);
}
} else {
seeWeak = true;
return String.format(
rb.getString("key.bit.weak"), KeyUtil.getKeySize(key));
disabledAlgFound = true;
return String.format(rb.getString("key.bit.disabled"), kLen);
}
}
private void checkWeakSign(String alg, Set<CryptoPrimitive> primitiveSet, boolean tsa) {
if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
if (!LEGACY_CHECK.permits(primitiveSet, alg, null)) {
if (primitiveSet == SIG_PRIMITIVE_SET) {
legacyAlg |= 2;
} else {
if (tsa) {
legacyAlg |= 4;
} else {
legacyAlg |= 1;
}
}
}
} else {
if (primitiveSet == SIG_PRIMITIVE_SET) {
disabledAlg |= 2;
} else {
if (tsa) {
disabledAlg |= 4;
} else {
disabledAlg |= 1;
}
}
}
}
private void checkWeakSign(PrivateKey key) {
if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
if (!LEGACY_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
legacyAlg |= 8;
}
} else {
disabledAlg |= 8;
}
}
@ -1496,22 +1609,22 @@ public class Main {
void signJar(String jarName, String alias)
throws Exception {
if (digestalg != null && !DISABLED_CHECK.permits(
DIGEST_PRIMITIVE_SET, digestalg, null)) {
weakAlg |= 1;
if (digestalg == null) {
digestalg = JarSigner.Builder.getDefaultDigestAlgorithm();
}
if (tSADigestAlg != null && !DISABLED_CHECK.permits(
DIGEST_PRIMITIVE_SET, tSADigestAlg, null)) {
weakAlg |= 4;
checkWeakSign(digestalg, DIGEST_PRIMITIVE_SET, false);
if (tSADigestAlg == null) {
tSADigestAlg = JarSigner.Builder.getDefaultDigestAlgorithm();
}
if (sigalg != null && !DISABLED_CHECK.permits(
SIG_PRIMITIVE_SET , sigalg, null)) {
weakAlg |= 2;
}
if (!DISABLED_CHECK.permits(
SIG_PRIMITIVE_SET, privateKey)) {
weakAlg |= 8;
checkWeakSign(tSADigestAlg, DIGEST_PRIMITIVE_SET, true);
if (sigalg == null) {
sigalg = JarSigner.Builder.getDefaultSignatureAlgorithm(privateKey);
}
checkWeakSign(sigalg, SIG_PRIMITIVE_SET, false);
checkWeakSign(privateKey);
boolean aliasUsed = false;
X509Certificate tsaCert = null;
@ -1748,7 +1861,6 @@ public class Main {
}
}
}
displayMessagesAndResult(true);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -163,8 +163,10 @@ public class Resources extends java.util.ListResourceBundle {
{"history.nobk", "- Missing block file for signature-related file META-INF/%s.SF"},
{"with.weak", "%s (weak)"},
{"with.disabled", "%s (disabled)"},
{"key.bit", "%d-bit key"},
{"key.bit.weak", "%d-bit key (weak)"},
{"key.bit.disabled", "%d-bit key (disabled)"},
{"unknown.size", "unknown size"},
{"jarsigner.", "jarsigner: "},
@ -274,10 +276,18 @@ public class Resources extends java.util.ListResourceBundle {
"The TSA certificate chain is invalid. Reason: %s"},
{"The.signer.s.certificate.is.self.signed.",
"The signer's certificate is self-signed."},
{"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.",
"The %1$s algorithm specified for the %2$s option is considered a security risk."},
{"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.",
"The %1$s signing key has a keysize of %2$d which is considered a security risk."},
{"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.",
"The %1$s algorithm specified for the %2$s option is considered a security risk. This algorithm will be disabled in a future update."},
{"The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.and.is.disabled.",
"The %1$s algorithm specified for the %2$s option is considered a security risk and is disabled."},
{"The.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.",
"The %1$s digest algorithm is considered a security risk. This algorithm will be disabled in a future update."},
{"The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.",
"The %1$s signature algorithm is considered a security risk. This algorithm will be disabled in a future update."},
{"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk..This.key.size.will.be.disabled.in.a.future.update.",
"The %1$s signing key has a keysize of %2$d which is considered a security risk. This key size will be disabled in a future update."},
{"The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk.and.is.disabled.",
"The %1$s signing key has a keysize of %2$d which is considered a security risk and is disabled."},
{"This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1",
"This jar contains entries whose certificate chain is invalid. Reason: %s"},
{"This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1",

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -41,10 +41,10 @@ import java.util.List;
public class ConciseJarsigner {
static OutputAnalyzer kt(String cmd) throws Exception {
// Choose 1024-bit RSA to make sure it runs fine and fast. In
// Choose 2048-bit RSA to make sure it runs fine and fast. In
// fact, every keyalg/keysize combination is OK for this test.
return SecurityTools.keytool("-storepass changeit -keypass changeit "
+ "-keystore ks -keyalg rsa -keysize 1024 " + cmd);
+ "-keystore ks -keyalg rsa -keysize 2048 " + cmd);
}
static void gencert(String owner, String cmd) throws Exception {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -68,7 +68,7 @@ public class DefaultOptions {
Files.write(Path.of("js.conf"), List.of(
"jarsigner.all = -keystore ${user.dir}/ks -storepass:env PASS "
+ "-debug -strict",
"jarsigner.sign = -digestalg SHA1",
"jarsigner.sign = -digestalg SHA-512",
"jarsigner.verify = -verbose:summary"));
JarUtils.createJarFile(Path.of("a.jar"), Path.of("."),
@ -81,7 +81,7 @@ public class DefaultOptions {
try (JarFile jf = new JarFile("a.jar")) {
Asserts.assertTrue(jf.getManifest().getAttributes("ks").keySet()
.stream()
.anyMatch(s -> s.toString().contains("SHA1-Digest")));
.anyMatch(s -> s.toString().contains("SHA-512-Digest")));
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -79,7 +79,7 @@ public class EC {
gencert("x", "-alias ca -validity 300");
js("a.jar a -debug -strict").shouldHaveExitValue(0);
js("a.jar b -debug -strict -sigalg SHA1withECDSA").shouldHaveExitValue(0);
js("a.jar b -debug -strict -sigalg SHA256withECDSA").shouldHaveExitValue(0);
js("a.jar c -debug -strict -sigalg SHA512withECDSA").shouldHaveExitValue(0);
js("-verify a.jar a -debug -strict").shouldHaveExitValue(0);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -47,9 +47,9 @@ public class NameClash {
Files.write(Path.of("A"), List.of("A"));
JarUtils.createJarFile(Path.of("a.jar"), Path.of("."), Path.of("A"));
SecurityTools.jarsigner(common + "a.jar a -digestalg SHA1")
SecurityTools.jarsigner(common + "a.jar a -digestalg SHA-256")
.shouldHaveExitValue(0);
SecurityTools.jarsigner(common + "a.jar b -digestalg SHA-1")
SecurityTools.jarsigner(common + "a.jar b -digestalg SHA-256")
.shouldHaveExitValue(0);
SecurityTools.jarsigner(common + "-verify -debug -strict a.jar")

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -62,7 +62,7 @@ import sun.security.x509.X500Name;
/*
* @test
* @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8180289
* @bug 6543842 6543440 6939248 8009636 8024302 8163304 8169911 8180289 8172404
* @summary checking response of timestamp
* @modules java.base/sun.security.pkcs
* java.base/sun.security.timestamp
@ -224,7 +224,8 @@ public class TimestampCheck {
// Always use the same algorithm at timestamp signing
// so it is different from the hash algorithm.
Signature sig = Signature.getInstance("SHA1withRSA");
String sigAlg = "SHA256withRSA";
Signature sig = Signature.getInstance(sigAlg);
sig.initSign((PrivateKey)(ks.getKey(
alias, "changeit".toCharArray())));
sig.update(tstInfo.toByteArray());
@ -241,7 +242,9 @@ public class TimestampCheck {
SignerInfo signerInfo = new SignerInfo(
new X500Name(signer.getIssuerX500Principal().getName()),
signer.getSerialNumber(),
AlgorithmId.get("SHA-1"), AlgorithmId.get("RSA"), sig.sign());
AlgorithmId.get(AlgorithmId.getDigAlgFromSigAlg(sigAlg)),
AlgorithmId.get(AlgorithmId.getEncAlgFromSigAlg(sigAlg)),
sig.sign());
SignerInfo[] signerInfos = {signerInfo};
PKCS7 p7 = new PKCS7(algorithms, contentInfo,
@ -417,47 +420,108 @@ public class TimestampCheck {
.shouldContain("TSAPolicyID changed in timestamp token")
.shouldHaveExitValue(1);
sign("sha1alg", "-tsadigestalg", "SHA")
sign("sha384alg", "-tsadigestalg", "SHA-384")
.shouldHaveExitValue(0);
checkTimestamp("sha1alg.jar", defaultPolicyId, "SHA-1");
checkTimestamp("sha384alg.jar", defaultPolicyId, "SHA-384");
sign("tsweak", "-digestalg", "MD5",
// Legacy algorithms
signVerbose(null, "unsigned.jar", "sha1alg.jar", "signer",
"-strict", "-digestalg", "SHA-1")
.shouldHaveExitValue(0)
.shouldContain("jar signed, with signer errors")
.shouldMatch("SHA-1.*-digestalg.*will be disabled");
verify("sha1alg.jar", "-strict")
.shouldHaveExitValue(0)
.shouldContain("jar verified, with signer errors")
.shouldContain("SHA-1 digest algorithm is considered a security risk")
.shouldContain("This algorithm will be disabled in a future update")
.shouldNotContain("is disabled");
sign("sha1tsaalg", "-tsadigestalg", "SHA-1", "-strict")
.shouldHaveExitValue(0)
.shouldContain("jar signed, with signer errors")
.shouldMatch("SHA-1.*-tsadigestalg.*will be disabled")
.shouldNotContain("is disabled");
verify("sha1tsaalg.jar", "-strict")
.shouldHaveExitValue(0)
.shouldContain("jar verified, with signer errors")
.shouldContain("SHA-1 digest algorithm is considered a security risk")
.shouldNotContain("is disabled");
// Disabled algorithms
sign("tsdisabled", "-digestalg", "MD5",
"-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
.shouldHaveExitValue(68)
.shouldContain("The timestamp is invalid. Without a valid timestamp")
.shouldMatch("MD5.*-digestalg.*risk")
.shouldMatch("MD5.*-tsadigestalg.*risk")
.shouldMatch("MD5withRSA.*-sigalg.*risk");
checkWeak("tsweak.jar");
.shouldMatch("MD5.*-digestalg.*is disabled")
.shouldMatch("MD5.*-tsadigestalg.*is disabled")
.shouldMatch("MD5withRSA.*-sigalg.*is disabled");
checkDisabled("tsdisabled.jar");
signVerbose("tsweak", "unsigned.jar", "tsweak2.jar", "signer")
signVerbose("tsdisabled", "unsigned.jar", "tsdisabled2.jar", "signer")
.shouldHaveExitValue(64)
.shouldContain("The timestamp is invalid. Without a valid timestamp")
.shouldContain("TSA certificate chain is invalid");
// Weak timestamp is an error and jar treated unsigned
verify("tsweak2.jar", "-verbose")
// Disabled timestamp is an error and jar treated unsigned
verify("tsdisabled2.jar", "-verbose")
.shouldHaveExitValue(16)
.shouldContain("treated as unsigned")
.shouldMatch("Timestamp.*512.*weak");
.shouldMatch("Timestamp.*512.*(disabled)");
// Algorithm used in signing is weak
signVerbose("normal", "unsigned.jar", "halfWeak.jar", "signer",
// Algorithm used in signing is disabled
signVerbose("normal", "unsigned.jar", "halfDisabled.jar", "signer",
"-digestalg", "MD5")
.shouldContain("-digestalg option is considered a security risk")
.shouldContain("-digestalg option is considered a security risk and is disabled")
.shouldHaveExitValue(4);
checkHalfWeak("halfWeak.jar");
checkHalfDisabled("halfDisabled.jar");
// sign with DSA key
signVerbose("normal", "unsigned.jar", "sign1.jar", "dsakey")
.shouldHaveExitValue(0);
// sign with RSAkeysize < 1024
signVerbose("normal", "sign1.jar", "sign2.jar", "weakkeysize")
signVerbose("normal", "sign1.jar", "sign2.jar", "disabledkeysize")
.shouldContain("Algorithm constraints check failed on keysize")
.shouldHaveExitValue(4);
checkMultiple("sign2.jar");
// Legacy algorithms
sign("tsweak", "-digestalg", "SHA1",
"-sigalg", "SHA1withRSA", "-tsadigestalg", "SHA1")
.shouldHaveExitValue(0)
.shouldMatch("SHA1.*-digestalg.*will be disabled")
.shouldMatch("SHA1.*-tsadigestalg.*will be disabled")
.shouldMatch("SHA1withRSA.*-sigalg.*will be disabled");
checkWeak("tsweak.jar");
signVerbose("tsweak", "unsigned.jar", "tsweak2.jar", "signer")
.shouldHaveExitValue(0);
verify("tsweak2.jar", "-verbose")
.shouldHaveExitValue(0)
.shouldContain("jar verified")
.shouldMatch("Timestamp.*1024.*(weak)");
// Algorithm used in signing is weak
signVerbose("normal", "unsigned.jar", "halfWeak.jar", "signer",
"-digestalg", "SHA1")
.shouldContain("-digestalg option is considered a security risk.")
.shouldContain("This algorithm will be disabled in a future update.")
.shouldHaveExitValue(0);
checkHalfWeak("halfWeak.jar");
// sign with DSA key
signVerbose("normal", "unsigned.jar", "sign1.jar", "dsakey")
.shouldHaveExitValue(0);
// sign with RSAkeysize < 2048
signVerbose("normal", "sign1.jar", "sign2.jar", "weakkeysize")
.shouldNotContain("Algorithm constraints check failed on keysize")
.shouldHaveExitValue(0);
checkMultipleWeak("sign2.jar");
// 8191438: jarsigner should print when a timestamp will expire
checkExpiration();
@ -691,7 +755,7 @@ public class TimestampCheck {
.shouldContain("re-run jarsigner with debug enabled");
}
static void checkWeak(String file) throws Exception {
static void checkDisabled(String file) throws Exception {
verify(file)
.shouldHaveExitValue(16)
.shouldContain("treated as unsigned")
@ -701,29 +765,29 @@ public class TimestampCheck {
.shouldHaveExitValue(16)
.shouldContain("treated as unsigned")
.shouldMatch("weak algorithm that is now disabled by")
.shouldMatch("Digest algorithm: .*weak")
.shouldMatch("Signature algorithm: .*weak")
.shouldMatch("Timestamp digest algorithm: .*weak")
.shouldNotMatch("Timestamp signature algorithm: .*weak.*weak")
.shouldMatch("Timestamp signature algorithm: .*key.*weak");
.shouldMatch("Digest algorithm: .*(disabled)")
.shouldMatch("Signature algorithm: .*(disabled)")
.shouldMatch("Timestamp digest algorithm: .*(disabled)")
.shouldNotMatch("Timestamp signature algorithm: .*(weak).*(weak)")
.shouldMatch("Timestamp signature algorithm: .*key.*(disabled)");
verify(file, "-J-Djava.security.debug=jar")
.shouldHaveExitValue(16)
.shouldMatch("SignatureException:.*disabled");
// For 8171319: keytool should print out warnings when reading or
// generating cert/cert req using weak algorithms.
// generating cert/cert req using disabled algorithms.
// Must call keytool the command, otherwise doPrintCert() might not
// be able to reset "jdk.certpath.disabledAlgorithms".
String sout = SecurityTools.keytool("-printcert -jarfile " + file)
.stderrShouldContain("The TSA certificate uses a 512-bit RSA key" +
" which is considered a security risk.")
" which is considered a security risk and is disabled.")
.getStdout();
if (sout.indexOf("weak", sout.indexOf("Timestamp:")) < 0) {
throw new RuntimeException("timestamp not weak: " + sout);
if (sout.indexOf("disabled", sout.indexOf("Timestamp:")) < 0) {
throw new RuntimeException("timestamp not disabled: " + sout);
}
}
static void checkHalfWeak(String file) throws Exception {
static void checkHalfDisabled(String file) throws Exception {
verify(file)
.shouldHaveExitValue(16)
.shouldContain("treated as unsigned")
@ -733,11 +797,14 @@ public class TimestampCheck {
.shouldHaveExitValue(16)
.shouldContain("treated as unsigned")
.shouldMatch("weak algorithm that is now disabled by")
.shouldMatch("Digest algorithm: .*weak")
.shouldNotMatch("Signature algorithm: .*weak")
.shouldNotMatch("Timestamp digest algorithm: .*weak")
.shouldNotMatch("Timestamp signature algorithm: .*weak.*weak")
.shouldNotMatch("Timestamp signature algorithm: .*key.*weak");
.shouldMatch("Digest algorithm: .*(disabled)")
.shouldNotMatch("Signature algorithm: .*(weak)")
.shouldNotMatch("Signature algorithm: .*(disabled)")
.shouldNotMatch("Timestamp digest algorithm: .*(disabled)")
.shouldNotMatch("Timestamp signature algorithm: .*(weak).*(weak)")
.shouldNotMatch("Timestamp signature algorithm: .*(disabled).*(disabled)")
.shouldNotMatch("Timestamp signature algorithm: .*key.*(weak)")
.shouldNotMatch("Timestamp signature algorithm: .*key.*(disabled)");
}
static void checkMultiple(String file) throws Exception {
@ -748,11 +815,70 @@ public class TimestampCheck {
.shouldHaveExitValue(0)
.shouldContain("jar verified")
.shouldMatch("X.509.*CN=dsakey")
.shouldNotMatch("X.509.*CN=weakkeysize")
.shouldNotMatch("X.509.*CN=disabledkeysize")
.shouldMatch("Signed by .*CN=dsakey")
.shouldMatch("Signed by .*CN=disabledkeysize")
.shouldMatch("Signature algorithm: .*key.*(disabled)");
}
static void checkWeak(String file) throws Exception {
verify(file)
.shouldHaveExitValue(0)
.shouldNotContain("treated as unsigned");
verify(file, "-verbose")
.shouldHaveExitValue(0)
.shouldNotContain("treated as unsigned")
.shouldMatch("Digest algorithm: .*(weak)")
.shouldMatch("Signature algorithm: .*(weak)")
.shouldMatch("Timestamp digest algorithm: .*(weak)")
.shouldNotMatch("Timestamp signature algorithm: .*(weak).*(weak)")
.shouldMatch("Timestamp signature algorithm: .*key.*(weak)");
verify(file, "-J-Djava.security.debug=jar")
.shouldHaveExitValue(0)
.shouldNotMatch("SignatureException:.*disabled");
// keytool should print out warnings when reading or
// generating cert/cert req using legacy algorithms.
String sout = SecurityTools.keytool("-printcert -jarfile " + file)
.stderrShouldContain("The TSA certificate uses a 1024-bit RSA key" +
" which is considered a security risk." +
" This key size will be disabled in a future update.")
.getStdout();
if (sout.indexOf("weak", sout.indexOf("Timestamp:")) < 0) {
throw new RuntimeException("timestamp not weak: " + sout);
}
}
static void checkHalfWeak(String file) throws Exception {
verify(file)
.shouldHaveExitValue(0)
.shouldNotContain("treated as unsigned");
verify(file, "-verbose")
.shouldHaveExitValue(0)
.shouldNotContain("treated as unsigned")
.shouldMatch("Digest algorithm: .*(weak)")
.shouldNotMatch("Signature algorithm: .*(weak)")
.shouldNotMatch("Signature algorithm: .*(disabled)")
.shouldNotMatch("Timestamp digest algorithm: .*(weak)")
.shouldNotMatch("Timestamp signature algorithm: .*(weak).*(weak)")
.shouldNotMatch("Timestamp signature algorithm: .*(disabled).*(disabled)")
.shouldNotMatch("Timestamp signature algorithm: .*key.*(weak)")
.shouldNotMatch("Timestamp signature algorithm: .*key.*(disabled)");
}
static void checkMultipleWeak(String file) throws Exception {
verify(file)
.shouldHaveExitValue(0)
.shouldContain("jar verified");
verify(file, "-verbose", "-certs")
.shouldHaveExitValue(0)
.shouldContain("jar verified")
.shouldMatch("X.509.*CN=dsakey")
.shouldMatch("X.509.*CN=weakkeysize")
.shouldMatch("Signed by .*CN=dsakey")
.shouldMatch("Signed by .*CN=weakkeysize")
.shouldMatch("Signature algorithm: .*key.*weak");
}
.shouldMatch("Signature algorithm: .*key.*(weak)");
}
static void checkTimestamp(String file, String policyId, String digestAlg)
throws Exception {
@ -822,11 +948,13 @@ public class TimestampCheck {
keytool("-alias signer -genkeypair -ext bc -dname CN=signer");
keytool("-alias oldsigner -genkeypair -dname CN=oldsigner");
keytool("-alias dsakey -genkeypair -keyalg DSA -dname CN=dsakey");
keytool("-alias weakkeysize -genkeypair -keysize 512 -dname CN=weakkeysize");
keytool("-alias weakkeysize -genkeypair -keysize 1024 -dname CN=weakkeysize");
keytool("-alias disabledkeysize -genkeypair -keysize 512 -dname CN=disabledkeysize");
keytool("-alias badku -genkeypair -dname CN=badku");
keytool("-alias ts -genkeypair -dname CN=ts");
keytool("-alias tsold -genkeypair -dname CN=tsold");
keytool("-alias tsweak -genkeypair -keysize 512 -dname CN=tsweak");
keytool("-alias tsweak -genkeypair -keysize 1024 -dname CN=tsweak");
keytool("-alias tsdisabled -genkeypair -keysize 512 -dname CN=tsdisabled");
keytool("-alias tsbad1 -genkeypair -dname CN=tsbad1");
keytool("-alias tsbad2 -genkeypair -dname CN=tsbad2");
keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3");
@ -850,6 +978,7 @@ public class TimestampCheck {
gencert("oldsigner", "-startdate -30d -validity 20");
gencert("dsakey");
gencert("weakkeysize");
gencert("disabledkeysize");
gencert("badku", "-ext ku:critical=keyAgreement");
gencert("ts", "-ext eku:critical=ts -validity 500");
@ -882,6 +1011,7 @@ public class TimestampCheck {
gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 500");
gencert("tsweak", "-ext eku:critical=ts");
gencert("tsdisabled", "-ext eku:critical=ts");
gencert("tsbad1");
gencert("tsbad2", "-ext eku=ts");
gencert("tsbad3", "-ext eku:critical=cs");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -139,7 +139,7 @@ public class TsacertOptionTest extends Test {
// sign jar file
// specify -tsadigestalg option because
// TSA server uses SHA-1 digest algorithm
// TSA server uses SHA-512 digest algorithm
OutputAnalyzer analyzer = jarsigner(
"-J-Dhttp.proxyHost=",
"-J-Dhttp.proxyPort=",
@ -150,7 +150,7 @@ public class TsacertOptionTest extends Test {
"-keypass", PASSWORD,
"-signedjar", SIGNED_JARFILE,
"-tsacert", TSA_KEY_ALIAS,
"-tsadigestalg", "SHA-1",
"-tsadigestalg", "SHA-512",
UNSIGNED_JARFILE,
SIGNING_KEY_ALIAS);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -74,12 +74,12 @@ public class Warning {
.shouldNotContain("is self-signed");
run("jarsigner", "a.jar b -digestalg MD5")
.shouldContain("-digestalg option is considered a security risk.");
.shouldContain("-digestalg option is considered a security risk and is disabled.");
run("jarsigner", "a.jar b -digestalg MD5 -strict")
.shouldHaveExitValue(4)
.shouldContain("-digestalg option is considered a security risk.");
.shouldContain("-digestalg option is considered a security risk and is disabled.");
run("jarsigner", "a.jar b -sigalg MD5withRSA")
.shouldContain("-sigalg option is considered a security risk");
.shouldContain("-sigalg option is considered a security risk and is disabled.");
issueCert("b", "-sigalg MD5withRSA");
run("jarsigner", "a.jar b")

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
/*
* @test
* @bug 8171319 8177569 8182879
* @bug 8171319 8177569 8182879 8172404
* @summary keytool should print out warnings when reading or generating
* cert/cert req using weak algorithms
* @library /test/lib
@ -70,62 +70,63 @@ public class WeakAlg {
rm("ks");
// Tests for "disabled" algorithms
// -genkeypair, and -printcert, -list -alias, -exportcert
// (w/ different formats)
checkGenKeyPair("a", "-keyalg RSA -sigalg MD5withRSA", "MD5withRSA");
checkGenKeyPair("b", "-keyalg RSA -keysize 512", "512-bit RSA key");
checkGenKeyPair("c", "-keyalg RSA", null);
checkDisabledGenKeyPair("a", "-keyalg RSA -sigalg MD5withRSA", "MD5withRSA");
checkDisabledGenKeyPair("b", "-keyalg RSA -keysize 512", "512-bit RSA key");
checkDisabledGenKeyPair("c", "-keyalg RSA", null);
kt("-list")
.shouldContain("Warning:")
.shouldMatch("<a>.*MD5withRSA.*risk")
.shouldMatch("<b>.*512-bit RSA key.*risk");
.shouldMatch("<a>.*MD5withRSA.*is disabled")
.shouldMatch("<b>.*512-bit RSA key.*is disabled");
kt("-list -v")
.shouldContain("Warning:")
.shouldMatch("<a>.*MD5withRSA.*risk")
.shouldContain("MD5withRSA (weak)")
.shouldMatch("<b>.*512-bit RSA key.*risk")
.shouldContain("512-bit RSA key (weak)");
.shouldMatch("<a>.*MD5withRSA.*is disabled")
.shouldContain("MD5withRSA (disabled)")
.shouldMatch("<b>.*512-bit RSA key.*is disabled")
.shouldContain("512-bit RSA key (disabled)");
// Multiple warnings for multiple cert in -printcert
// or -list or -exportcert
// -certreq, -printcertreq, -gencert
checkCertReq("a", "", null);
checkDisabledCertReq("a", "", null);
gencert("c-a", "")
.shouldNotContain("Warning"); // new sigalg is not weak
gencert("c-a", "-sigalg MD2withRSA")
.shouldContain("Warning:")
.shouldMatch("The generated certificate.*MD2withRSA.*risk");
.shouldMatch("The generated certificate.*MD2withRSA.*is disabled");
checkCertReq("a", "-sigalg MD5withRSA", "MD5withRSA");
checkDisabledCertReq("a", "-sigalg MD5withRSA", "MD5withRSA");
gencert("c-a", "")
.shouldContain("Warning:")
.shouldMatch("The certificate request.*MD5withRSA.*risk");
.shouldMatch("The certificate request.*MD5withRSA.*is disabled");
gencert("c-a", "-sigalg MD2withRSA")
.shouldContain("Warning:")
.shouldMatch("The certificate request.*MD5withRSA.*risk")
.shouldMatch("The generated certificate.*MD2withRSA.*risk");
.shouldMatch("The certificate request.*MD5withRSA.*is disabled")
.shouldMatch("The generated certificate.*MD2withRSA.*is disabled");
checkCertReq("b", "", "512-bit RSA key");
checkDisabledCertReq("b", "", "512-bit RSA key");
gencert("c-b", "")
.shouldContain("Warning:")
.shouldMatch("The certificate request.*512-bit RSA key.*risk")
.shouldMatch("The generated certificate.*512-bit RSA key.*risk");
.shouldMatch("The certificate request.*512-bit RSA key.*is disabled")
.shouldMatch("The generated certificate.*512-bit RSA key.*is disabled");
checkCertReq("c", "", null);
checkDisabledCertReq("c", "", null);
gencert("a-c", "")
.shouldContain("Warning:")
.shouldMatch("The issuer.*MD5withRSA.*risk");
.shouldMatch("The issuer.*MD5withRSA.*is disabled");
// but the new cert is not weak
kt("-printcert -file a-c.cert")
.shouldNotContain("Warning")
.shouldNotContain("weak");
.shouldNotContain("(disabled)");
gencert("b-c", "")
.shouldContain("Warning:")
.shouldMatch("The issuer.*512-bit RSA key.*risk");
.shouldMatch("The issuer.*512-bit RSA key.*is disabled");
// -importcert
checkImport();
@ -135,10 +136,10 @@ public class WeakAlg {
// -gencrl, -printcrl
checkGenCRL("a", "", null);
checkGenCRL("a", "-sigalg MD5withRSA", "MD5withRSA");
checkGenCRL("b", "", "512-bit RSA key");
checkGenCRL("c", "", null);
checkDisabledGenCRL("a", "", null);
checkDisabledGenCRL("a", "-sigalg MD5withRSA", "MD5withRSA");
checkDisabledGenCRL("b", "", "512-bit RSA key");
checkDisabledGenCRL("c", "", null);
kt("-delete -alias b");
kt("-printcrl -file b.crl")
@ -147,13 +148,85 @@ public class WeakAlg {
jksTypeCheck();
checkInplaceImportKeyStore();
rm("ks");
// Tests for "legacy" algorithms
// -genkeypair, and -printcert, -list -alias, -exportcert
// (w/ different formats)
checkWeakGenKeyPair("x", "-keyalg RSA -sigalg SHA1withRSA", "SHA1withRSA");
checkWeakGenKeyPair("y", "-keyalg RSA -keysize 1024", "1024-bit RSA key");
checkWeakGenKeyPair("z", "-keyalg RSA", null);
kt("-list")
.shouldContain("Warning:")
.shouldMatch("<x>.*SHA1withRSA.*will be disabled")
.shouldMatch("<y>.*1024-bit RSA key.*will be disabled");
kt("-list -v")
.shouldContain("Warning:")
.shouldMatch("<x>.*SHA1withRSA.*will be disabled")
.shouldContain("SHA1withRSA (weak)")
.shouldMatch("<y>.*1024-bit RSA key.*will be disabled")
.shouldContain("1024-bit RSA key (weak)");
// Multiple warnings for multiple cert in -printcert
// or -list or -exportcert
// -certreq, -printcertreq, -gencert
checkWeakCertReq("x", "", null);
gencert("z-x", "")
.shouldNotContain("Warning"); // new sigalg is not weak
gencert("z-x", "-sigalg SHA1withRSA")
.shouldContain("Warning:")
.shouldMatch("The generated certificate.*SHA1withRSA.*will be disabled");
checkWeakCertReq("x", "-sigalg SHA1withRSA", "SHA1withRSA");
gencert("z-x", "")
.shouldContain("Warning:")
.shouldMatch("The certificate request.*SHA1withRSA.*will be disabled");
gencert("z-x", "-sigalg SHA1withRSA")
.shouldContain("Warning:")
.shouldMatch("The certificate request.*SHA1withRSA.*will be disabled")
.shouldMatch("The generated certificate.*SHA1withRSA.*will be disabled");
checkWeakCertReq("y", "", "1024-bit RSA key");
gencert("z-y", "")
.shouldContain("Warning:")
.shouldMatch("The certificate request.*1024-bit RSA key.*will be disabled")
.shouldMatch("The generated certificate.*1024-bit RSA key.*will be disabled");
checkWeakCertReq("z", "", null);
gencert("x-z", "")
.shouldContain("Warning:")
.shouldMatch("The issuer.*SHA1withRSA.*will be disabled");
// but the new cert is not weak
kt("-printcert -file x-z.cert")
.shouldNotContain("Warning")
.shouldNotContain("weak");
gencert("y-z", "")
.shouldContain("Warning:")
.shouldMatch("The issuer.*1024-bit RSA key.*will be disabled");
// -gencrl, -printcrl
checkWeakGenCRL("x", "", null);
checkWeakGenCRL("x", "-sigalg SHA1withRSA", "SHA1withRSA");
checkWeakGenCRL("y", "", "1024-bit RSA key");
checkWeakGenCRL("z", "", null);
kt("-delete -alias y");
kt("-printcrl -file y.crl")
.shouldContain("WARNING: not verified");
jksTypeCheck();
}
static void jksTypeCheck() throws Exception {
// No warning for cacerts, all certs
kt0("-cacerts -list -storepass changeit")
.shouldNotContain("Warning:");
.shouldNotContain("proprietary format");
rm("ks");
rm("ks2");
@ -228,12 +301,12 @@ public class WeakAlg {
importkeystore("ks", "ks2", "")
.shouldContain("3 entries successfully imported")
.shouldContain("Warning")
.shouldMatch("<b>.*512-bit RSA key.*risk")
.shouldMatch("<a>.*MD5withRSA.*risk");
.shouldMatch("<b>.*512-bit RSA key.*is disabled")
.shouldMatch("<a>.*MD5withRSA.*is disabled");
importkeystore("ks", "ks3", "-srcalias a")
.shouldContain("Warning")
.shouldMatch("<a>.*MD5withRSA.*risk");
.shouldMatch("<a>.*MD5withRSA.*is disabled");
}
static void checkInplaceImportKeyStore() throws Exception {
@ -313,11 +386,11 @@ public class WeakAlg {
kt("-importcert -alias d -file a.cert", "no")
.shouldContain("Certificate already exists in keystore")
.shouldContain("Warning")
.shouldMatch("The input.*MD5withRSA.*risk")
.shouldMatch("The input.*MD5withRSA.*is disabled")
.shouldContain("Do you still want to add it?");
kt("-importcert -alias d -file a.cert -noprompt")
.shouldContain("Warning")
.shouldMatch("The input.*MD5withRSA.*risk")
.shouldMatch("The input.*MD5withRSA.*is disabled")
.shouldNotContain("[no]");
// cert is self-signed
@ -325,12 +398,12 @@ public class WeakAlg {
kt("-delete -alias d");
kt("-importcert -alias d -file a.cert", "no")
.shouldContain("Warning")
.shouldContain("MD5withRSA (weak)")
.shouldMatch("The input.*MD5withRSA.*risk")
.shouldContain("MD5withRSA (disabled)")
.shouldMatch("The input.*MD5withRSA.*is disabled")
.shouldContain("Trust this certificate?");
kt("-importcert -alias d -file a.cert -noprompt")
.shouldContain("Warning")
.shouldMatch("The input.*MD5withRSA.*risk")
.shouldMatch("The input.*MD5withRSA.*is disabled")
.shouldNotContain("[no]");
// JDK-8177569: no warning for sigalg of trusted cert
@ -366,13 +439,13 @@ public class WeakAlg {
// -printcert will always show warnings
kt("-printcert -file ca.cert")
.shouldContain("name: " + weakSigAlgCA + " (weak)")
.shouldContain("name: " + weakSigAlgCA + " (disabled)")
.shouldContain("Warning")
.shouldMatch("The certificate.*" + weakSigAlgCA + ".*risk");
.shouldMatch("The certificate.*" + weakSigAlgCA + ".*is disabled");
kt("-printcert -file ca.cert -trustcacerts") // -trustcacerts useless
.shouldContain("name: " + weakSigAlgCA + " (weak)")
.shouldContain("name: " + weakSigAlgCA + " (disabled)")
.shouldContain("Warning")
.shouldMatch("The certificate.*" + weakSigAlgCA + ".*risk");
.shouldMatch("The certificate.*" + weakSigAlgCA + ".*is disabled");
// Importing with -trustcacerts ignore CA cert's sig alg
kt("-delete -alias d");
@ -387,13 +460,13 @@ public class WeakAlg {
// but not without -trustcacerts
kt("-delete -alias d");
kt("-importcert -alias d -file ca.cert", "no")
.shouldContain("name: " + weakSigAlgCA + " (weak)")
.shouldContain("name: " + weakSigAlgCA + " (disabled)")
.shouldContain("Warning")
.shouldMatch("The input.*" + weakSigAlgCA + ".*risk")
.shouldMatch("The input.*" + weakSigAlgCA + ".*is disabled")
.shouldContain("Trust this certificate?");
kt("-importcert -alias d -file ca.cert -noprompt")
.shouldContain("Warning")
.shouldMatch("The input.*" + weakSigAlgCA + ".*risk")
.shouldMatch("The input.*" + weakSigAlgCA + ".*is disabled")
.shouldNotContain("[no]");
}
@ -403,8 +476,8 @@ public class WeakAlg {
gencert("c-b", "");
kt("-importcert -alias d -file c-b.cert") // weak only, no prompt
.shouldContain("Warning")
.shouldNotContain("512-bit RSA key (weak)")
.shouldMatch("The input.*512-bit RSA key.*risk")
.shouldNotContain("512-bit RSA key (disabled)")
.shouldMatch("The input.*512-bit RSA key.*is disabled")
.shouldNotContain("[no]");
kt("-delete -alias b");
@ -413,12 +486,12 @@ public class WeakAlg {
kt("-importcert -alias d -file c-b.cert", "no") // weak and not trusted
.shouldContain("Warning")
.shouldContain("512-bit RSA key (weak)")
.shouldMatch("The input.*512-bit RSA key.*risk")
.shouldContain("512-bit RSA key (disabled)")
.shouldMatch("The input.*512-bit RSA key.*is disabled")
.shouldContain("Trust this certificate?");
kt("-importcert -alias d -file c-b.cert -noprompt")
.shouldContain("Warning")
.shouldMatch("The input.*512-bit RSA key.*risk")
.shouldMatch("The input.*512-bit RSA key.*is disabled")
.shouldNotContain("[no]");
// a non self-signed strong cert
@ -447,7 +520,7 @@ public class WeakAlg {
gencert("a-c", "");
kt("-importcert -alias c -file a-c.cert")
.shouldContain("Warning")
.shouldMatch("Issuer <a>.*MD5withRSA.*risk");
.shouldMatch("Issuer <a>.*MD5withRSA.*is disabled");
// JDK-8177569: no warning for sigalg of trusted cert
reStore();
@ -456,7 +529,7 @@ public class WeakAlg {
kt("-delete -alias a");
kt("-importcert -alias a -file a.cert -noprompt");
kt("-list -alias a -v")
.shouldNotContain("weak")
.shouldNotContain("disabled")
.shouldNotContain("Warning");
// This time a is trusted and no warning on its weak sig alg
kt("-importcert -alias c -file a-c.cert")
@ -471,16 +544,16 @@ public class WeakAlg {
cat("a-a-b-c.cert", "b-c.cert", "a-b.cert", "a.cert");
kt("-importcert -alias c -file a-a-b-c.cert") // only weak
.shouldContain("Warning")
.shouldMatch("Reply #2 of 3.*512-bit RSA key.*risk")
.shouldMatch("Reply #3 of 3.*MD5withRSA.*risk")
.shouldMatch("Reply #2 of 3.*512-bit RSA key.*is disabled")
.shouldMatch("Reply #3 of 3.*MD5withRSA.*is disabled")
.shouldNotContain("[no]");
// Without root
cat("a-b-c.cert", "b-c.cert", "a-b.cert");
kt("-importcert -alias c -file a-b-c.cert") // only weak
.shouldContain("Warning")
.shouldMatch("Reply #2 of 2.*512-bit RSA key.*risk")
.shouldMatch("Issuer <a>.*MD5withRSA.*risk")
.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")
.shouldMatch("Issuer <a>.*MD5withRSA.*is disabled")
.shouldNotContain("[no]");
reStore();
@ -488,7 +561,7 @@ public class WeakAlg {
kt("-importcert -alias a -file b-a.cert")
.shouldContain("Warning")
.shouldMatch("Issuer <b>.*512-bit RSA key.*risk")
.shouldMatch("Issuer <b>.*512-bit RSA key.*is disabled")
.shouldNotContain("[no]");
kt("-importcert -alias a -file c-a.cert")
@ -496,7 +569,7 @@ public class WeakAlg {
kt("-importcert -alias b -file c-b.cert")
.shouldContain("Warning")
.shouldMatch("The input.*512-bit RSA key.*risk")
.shouldMatch("The input.*512-bit RSA key.*is disabled")
.shouldNotContain("[no]");
reStore();
@ -506,25 +579,25 @@ public class WeakAlg {
kt("-printcert -file c-b-a.cert")
.shouldContain("Warning")
.shouldMatch("The certificate #2 of 2.*512-bit RSA key.*risk");
.shouldMatch("The certificate #2 of 2.*512-bit RSA key.*is disabled");
kt("-delete -alias b");
kt("-importcert -alias a -file c-b-a.cert")
.shouldContain("Warning")
.shouldMatch("Reply #2 of 2.*512-bit RSA key.*risk")
.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")
.shouldNotContain("[no]");
kt("-delete -alias c");
kt("-importcert -alias a -file c-b-a.cert", "no")
.shouldContain("Top-level certificate in reply:")
.shouldContain("512-bit RSA key (weak)")
.shouldContain("512-bit RSA key (disabled)")
.shouldContain("Warning")
.shouldMatch("Reply #2 of 2.*512-bit RSA key.*risk")
.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")
.shouldContain("Install reply anyway?");
kt("-importcert -alias a -file c-b-a.cert -noprompt")
.shouldContain("Warning")
.shouldMatch("Reply #2 of 2.*512-bit RSA key.*risk")
.shouldMatch("Reply #2 of 2.*512-bit RSA key.*is disabled")
.shouldNotContain("[no]");
reStore();
@ -543,7 +616,7 @@ public class WeakAlg {
System.out.println("> " + dest);
}
static void checkGenCRL(String alias, String options, String bad) {
static void checkDisabledGenCRL(String alias, String options, String bad) {
OutputAnalyzer oa = kt("-gencrl -alias " + alias
+ " -id 1 -file " + alias + ".crl " + options);
@ -551,23 +624,23 @@ public class WeakAlg {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The generated CRL.*" + bad + ".*risk");
.shouldMatch("The generated CRL.*" + bad + ".*is disabled");
}
oa = kt("-printcrl -file " + alias + ".crl");
if (bad == null) {
oa.shouldNotContain("Warning")
.shouldContain("Verified by " + alias + " in keystore")
.shouldNotContain("(weak");
.shouldNotContain("(disabled");
} else {
oa.shouldContain("Warning:")
.shouldMatch("The CRL.*" + bad + ".*risk")
.shouldMatch("The CRL.*" + bad + ".*is disabled")
.shouldContain("Verified by " + alias + " in keystore")
.shouldContain(bad + " (weak)");
.shouldContain(bad + " (disabled)");
}
}
static void checkCertReq(
static void checkDisabledCertReq(
String alias, String options, String bad) {
OutputAnalyzer oa = certreq(alias, options);
@ -575,21 +648,21 @@ public class WeakAlg {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The generated certificate request.*" + bad + ".*risk");
.shouldMatch("The generated certificate request.*" + bad + ".*is disabled");
}
oa = kt("-printcertreq -file " + alias + ".req");
if (bad == null) {
oa.shouldNotContain("Warning")
.shouldNotContain("(weak)");
.shouldNotContain("(disabled)");
} else {
oa.shouldContain("Warning")
.shouldMatch("The certificate request.*" + bad + ".*risk")
.shouldContain(bad + " (weak)");
.shouldMatch("The certificate request.*" + bad + ".*is disabled")
.shouldContain(bad + " (disabled)");
}
}
static void checkGenKeyPair(
static void checkDisabledGenKeyPair(
String alias, String options, String bad) {
OutputAnalyzer oa = genkeypair(alias, options);
@ -597,7 +670,7 @@ public class WeakAlg {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The generated certificate.*" + bad + ".*risk");
.shouldMatch("The generated certificate.*" + bad + ".*is disabled");
}
oa = kt("-exportcert -alias " + alias + " -file " + alias + ".cert");
@ -605,7 +678,7 @@ public class WeakAlg {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The certificate.*" + bad + ".*risk");
.shouldMatch("The certificate.*" + bad + ".*is disabled");
}
oa = kt("-exportcert -rfc -alias " + alias + " -file " + alias + ".cert");
@ -613,7 +686,7 @@ public class WeakAlg {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The certificate.*" + bad + ".*risk");
.shouldMatch("The certificate.*" + bad + ".*is disabled");
}
oa = kt("-printcert -rfc -file " + alias + ".cert");
@ -621,7 +694,7 @@ public class WeakAlg {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The certificate.*" + bad + ".*risk");
.shouldMatch("The certificate.*" + bad + ".*is disabled");
}
oa = kt("-list -alias " + alias);
@ -629,7 +702,71 @@ public class WeakAlg {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The certificate.*" + bad + ".*risk");
.shouldMatch("The certificate.*" + bad + ".*is disabled");
}
// With cert content
oa = kt("-printcert -file " + alias + ".cert");
if (bad == null) {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldContain(bad + " (disabled)")
.shouldMatch("The certificate.*" + bad + ".*is disabled");
}
oa = kt("-list -v -alias " + alias);
if (bad == null) {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldContain(bad + " (disabled)")
.shouldMatch("The certificate.*" + bad + ".*is disabled");
}
}
static void checkWeakGenKeyPair(
String alias, String options, String bad) {
OutputAnalyzer oa = genkeypair(alias, options);
if (bad == null) {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The generated certificate.*" + bad + ".*will be disabled");
}
oa = kt("-exportcert -alias " + alias + " -file " + alias + ".cert");
if (bad == null) {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The certificate.*" + bad + ".*will be disabled");
}
oa = kt("-exportcert -rfc -alias " + alias + " -file " + alias + ".cert");
if (bad == null) {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The certificate.*" + bad + ".*will be disabled");
}
oa = kt("-printcert -rfc -file " + alias + ".cert");
if (bad == null) {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The certificate.*" + bad + ".*will be disabled");
}
oa = kt("-list -alias " + alias);
if (bad == null) {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The certificate.*" + bad + ".*will be disabled");
}
// With cert content
@ -640,7 +777,7 @@ public class WeakAlg {
} else {
oa.shouldContain("Warning")
.shouldContain(bad + " (weak)")
.shouldMatch("The certificate.*" + bad + ".*risk");
.shouldMatch("The certificate.*" + bad + ".*will be disabled");
}
oa = kt("-list -v -alias " + alias);
@ -649,7 +786,54 @@ public class WeakAlg {
} else {
oa.shouldContain("Warning")
.shouldContain(bad + " (weak)")
.shouldMatch("The certificate.*" + bad + ".*risk");
.shouldMatch("The certificate.*" + bad + ".*will be disabled");
}
}
static void checkWeakGenCRL(String alias, String options, String bad) {
OutputAnalyzer oa = kt("-gencrl -alias " + alias
+ " -id 1 -file " + alias + ".crl " + options);
if (bad == null) {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The generated CRL.*" + bad + ".*will be disabled");
}
oa = kt("-printcrl -file " + alias + ".crl");
if (bad == null) {
oa.shouldNotContain("Warning")
.shouldContain("Verified by " + alias + " in keystore")
.shouldNotContain("(weak");
} else {
oa.shouldContain("Warning:")
.shouldMatch("The CRL.*" + bad + ".*will be disabled")
.shouldContain("Verified by " + alias + " in keystore")
.shouldContain(bad + " (weak)");
}
}
static void checkWeakCertReq(
String alias, String options, String bad) {
OutputAnalyzer oa = certreq(alias, options);
if (bad == null) {
oa.shouldNotContain("Warning");
} else {
oa.shouldContain("Warning")
.shouldMatch("The generated certificate request.*" + bad + ".*will be disabled");
}
oa = kt("-printcertreq -file " + alias + ".req");
if (bad == null) {
oa.shouldNotContain("Warning")
.shouldNotContain("(weak)");
} else {
oa.shouldContain("Warning")
.shouldMatch("The certificate request.*" + bad + ".*will be disabled")
.shouldContain(bad + " (weak)");
}
}