mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8191438: jarsigner should print when a timestamp will expire
Reviewed-by: mullan
This commit is contained in:
parent
ff6a245d89
commit
06a9e1a72f
18 changed files with 838 additions and 720 deletions
|
@ -30,6 +30,7 @@ import java.net.UnknownHostException;
|
||||||
import java.security.cert.CertPathValidatorException;
|
import java.security.cert.CertPathValidatorException;
|
||||||
import java.security.cert.PKIXBuilderParameters;
|
import java.security.cert.PKIXBuilderParameters;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.zip.*;
|
import java.util.zip.*;
|
||||||
import java.util.jar.*;
|
import java.util.jar.*;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -92,6 +93,7 @@ public class Main {
|
||||||
private static final String P11KEYSTORE = "PKCS11";
|
private static final String P11KEYSTORE = "PKCS11";
|
||||||
|
|
||||||
private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds
|
private static final long SIX_MONTHS = 180*24*60*60*1000L; //milliseconds
|
||||||
|
private static final long ONE_YEAR = 366*24*60*60*1000L;
|
||||||
|
|
||||||
private static final DisabledAlgorithmConstraints DISABLED_CHECK =
|
private static final DisabledAlgorithmConstraints DISABLED_CHECK =
|
||||||
new DisabledAlgorithmConstraints(
|
new DisabledAlgorithmConstraints(
|
||||||
|
@ -102,6 +104,13 @@ public class Main {
|
||||||
private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
|
private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
|
||||||
.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
|
.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
|
||||||
|
|
||||||
|
static final String VERSION = "1.0";
|
||||||
|
|
||||||
|
static final int IN_KEYSTORE = 0x01; // signer is in keystore
|
||||||
|
static final int NOT_ALIAS = 0x04; // alias list is NOT empty and
|
||||||
|
// signer is not in alias list
|
||||||
|
static final int SIGNED_BY_ALIAS = 0x08; // signer is in alias list
|
||||||
|
|
||||||
// Attention:
|
// Attention:
|
||||||
// This is the entry that get launched by the security tool jarsigner.
|
// This is the entry that get launched by the security tool jarsigner.
|
||||||
public static void main(String args[]) throws Exception {
|
public static void main(String args[]) throws Exception {
|
||||||
|
@ -109,13 +118,6 @@ public class Main {
|
||||||
js.run(args);
|
js.run(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final String VERSION = "1.0";
|
|
||||||
|
|
||||||
static final int IN_KEYSTORE = 0x01; // signer is in keystore
|
|
||||||
static final int NOT_ALIAS = 0x04; // alias list is NOT empty and
|
|
||||||
// signer is not in alias list
|
|
||||||
static final int SIGNED_BY_ALIAS = 0x08; // signer is in alias list
|
|
||||||
|
|
||||||
X509Certificate[] certChain; // signer's cert chain (when composing)
|
X509Certificate[] certChain; // signer's cert chain (when composing)
|
||||||
PrivateKey privateKey; // private key
|
PrivateKey privateKey; // private key
|
||||||
KeyStore store; // the keystore specified by -keystore
|
KeyStore store; // the keystore specified by -keystore
|
||||||
|
@ -160,8 +162,16 @@ public class Main {
|
||||||
|
|
||||||
// Informational warnings
|
// Informational warnings
|
||||||
private boolean hasExpiringCert = false;
|
private boolean hasExpiringCert = false;
|
||||||
private boolean noTimestamp = false;
|
private boolean hasExpiringTsaCert = false;
|
||||||
private Date expireDate = new Date(0L); // used in noTimestamp warning
|
private boolean noTimestamp = true;
|
||||||
|
|
||||||
|
// Expiration date. The value could be null if signed by a trusted cert.
|
||||||
|
private Date expireDate = null;
|
||||||
|
private Date tsaExpireDate = null;
|
||||||
|
|
||||||
|
// If there is a time stamp block inside the PKCS7 block file
|
||||||
|
boolean hasTimestampBlock = false;
|
||||||
|
|
||||||
|
|
||||||
// Severe warnings.
|
// Severe warnings.
|
||||||
|
|
||||||
|
@ -174,6 +184,7 @@ public class Main {
|
||||||
|
|
||||||
private int weakAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg
|
private int weakAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg
|
||||||
private boolean hasExpiredCert = false;
|
private boolean hasExpiredCert = false;
|
||||||
|
private boolean hasExpiredTsaCert = false;
|
||||||
private boolean notYetValidCert = false;
|
private boolean notYetValidCert = false;
|
||||||
private boolean chainNotValidated = false;
|
private boolean chainNotValidated = false;
|
||||||
private boolean tsaChainNotValidated = false;
|
private boolean tsaChainNotValidated = false;
|
||||||
|
@ -191,6 +202,7 @@ public class Main {
|
||||||
private boolean seeWeak = false;
|
private boolean seeWeak = false;
|
||||||
|
|
||||||
PKIXBuilderParameters pkixParameters;
|
PKIXBuilderParameters pkixParameters;
|
||||||
|
Set<X509Certificate> trustedCerts = new HashSet<>();
|
||||||
|
|
||||||
public void run(String args[]) {
|
public void run(String args[]) {
|
||||||
try {
|
try {
|
||||||
|
@ -277,8 +289,8 @@ public class Main {
|
||||||
|
|
||||||
if (strict) {
|
if (strict) {
|
||||||
int exitCode = 0;
|
int exitCode = 0;
|
||||||
if (weakAlg != 0 || chainNotValidated
|
if (weakAlg != 0 || chainNotValidated || hasExpiredCert
|
||||||
|| hasExpiredCert || notYetValidCert || signerSelfSigned) {
|
|| hasExpiredTsaCert || notYetValidCert || signerSelfSigned) {
|
||||||
exitCode |= 4;
|
exitCode |= 4;
|
||||||
}
|
}
|
||||||
if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
|
if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
|
||||||
|
@ -879,14 +891,12 @@ public class Main {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If signer is a trusted cert or private entry in user's own
|
// If signer is a trusted cert or private entry in user's own
|
||||||
// keystore, it can be self-signed.
|
// keystore, it can be self-signed. Please note aliasNotInStore
|
||||||
if (!aliasNotInStore) {
|
// is always false when ~/.keystore is used.
|
||||||
|
if (!aliasNotInStore && keystore != null) {
|
||||||
signerSelfSigned = false;
|
signerSelfSigned = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a time stamp block inside the PKCS7 block file
|
|
||||||
boolean hasTimestampBlock = false;
|
|
||||||
|
|
||||||
// Even if the verbose option is not specified, all out strings
|
// Even if the verbose option is not specified, all out strings
|
||||||
// must be generated so seeWeak can be updated.
|
// must be generated so seeWeak can be updated.
|
||||||
if (!digestMap.isEmpty()
|
if (!digestMap.isEmpty()
|
||||||
|
@ -986,118 +996,7 @@ public class Main {
|
||||||
System.out.println(rb.getString("jar.is.unsigned"));
|
System.out.println(rb.getString("jar.is.unsigned"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
boolean warningAppeared = false;
|
displayMessagesAndResult(false);
|
||||||
boolean errorAppeared = false;
|
|
||||||
if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
|
|
||||||
notYetValidCert || chainNotValidated || hasExpiredCert ||
|
|
||||||
hasUnsignedEntry || signerSelfSigned || (weakAlg != 0) ||
|
|
||||||
aliasNotInStore || notSignedByAlias || tsaChainNotValidated) {
|
|
||||||
|
|
||||||
if (strict) {
|
|
||||||
System.out.println(rb.getString("jar.verified.with.signer.errors."));
|
|
||||||
System.out.println();
|
|
||||||
System.out.println(rb.getString("Error."));
|
|
||||||
errorAppeared = true;
|
|
||||||
} else {
|
|
||||||
System.out.println(rb.getString("jar.verified."));
|
|
||||||
System.out.println();
|
|
||||||
System.out.println(rb.getString("Warning."));
|
|
||||||
warningAppeared = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (weakAlg != 0) {
|
|
||||||
// In fact, jarsigner verification did not catch this
|
|
||||||
// since it has not read the JarFile content itself.
|
|
||||||
// Everything is done with JarFile API. The signing
|
|
||||||
// history (digestMap etc) will show these info and
|
|
||||||
// print out proper warnings.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (badKeyUsage) {
|
|
||||||
System.out.println(
|
|
||||||
rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (badExtendedKeyUsage) {
|
|
||||||
System.out.println(
|
|
||||||
rb.getString("This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (badNetscapeCertType) {
|
|
||||||
System.out.println(
|
|
||||||
rb.getString("This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasUnsignedEntry) {
|
|
||||||
System.out.println(rb.getString(
|
|
||||||
"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked."));
|
|
||||||
}
|
|
||||||
if (hasExpiredCert) {
|
|
||||||
System.out.println(rb.getString(
|
|
||||||
"This.jar.contains.entries.whose.signer.certificate.has.expired."));
|
|
||||||
}
|
|
||||||
if (notYetValidCert) {
|
|
||||||
System.out.println(rb.getString(
|
|
||||||
"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chainNotValidated) {
|
|
||||||
System.out.println(String.format(
|
|
||||||
rb.getString("This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1"),
|
|
||||||
chainNotValidatedReason.getLocalizedMessage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsaChainNotValidated) {
|
|
||||||
System.out.println(String.format(
|
|
||||||
rb.getString("This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1"),
|
|
||||||
tsaChainNotValidatedReason.getLocalizedMessage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notSignedByAlias) {
|
|
||||||
System.out.println(
|
|
||||||
rb.getString("This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aliasNotInStore) {
|
|
||||||
System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signerSelfSigned) {
|
|
||||||
System.out.println(rb.getString(
|
|
||||||
"This.jar.contains.entries.whose.signer.certificate.is.self.signed."));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
System.out.println(rb.getString("jar.verified."));
|
|
||||||
}
|
|
||||||
if (hasExpiringCert || noTimestamp) {
|
|
||||||
if (!warningAppeared) {
|
|
||||||
System.out.println();
|
|
||||||
System.out.println(rb.getString("Warning."));
|
|
||||||
warningAppeared = true;
|
|
||||||
}
|
|
||||||
if (hasExpiringCert) {
|
|
||||||
System.out.println(rb.getString(
|
|
||||||
"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
|
|
||||||
}
|
|
||||||
if (noTimestamp) {
|
|
||||||
if (hasTimestampBlock) {
|
|
||||||
// JarSigner API has not seen the timestamp,
|
|
||||||
// might have ignored it due to weak alg, etc.
|
|
||||||
System.out.println(
|
|
||||||
String.format(rb.getString("bad.timestamp.verifying"), expireDate));
|
|
||||||
} else {
|
|
||||||
System.out.println(
|
|
||||||
String.format(rb.getString("no.timestamp.verifying"), expireDate));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (warningAppeared || errorAppeared) {
|
|
||||||
if (! (verbose != null && showcerts)) {
|
|
||||||
System.out.println();
|
|
||||||
System.out.println(rb.getString(
|
|
||||||
"Re.run.with.the.verbose.and.certs.options.for.more.details."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -1114,6 +1013,230 @@ public class Main {
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void displayMessagesAndResult(boolean isSigning) {
|
||||||
|
String result;
|
||||||
|
List<String> errors = new ArrayList<>();
|
||||||
|
List<String> warnings = new ArrayList<>();
|
||||||
|
List<String> info = new ArrayList<>();
|
||||||
|
|
||||||
|
boolean signerNotExpired = expireDate == null
|
||||||
|
|| expireDate.after(new Date());
|
||||||
|
|
||||||
|
if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
|
||||||
|
notYetValidCert || chainNotValidated || hasExpiredCert ||
|
||||||
|
hasUnsignedEntry || signerSelfSigned || (weakAlg != 0) ||
|
||||||
|
aliasNotInStore || notSignedByAlias ||
|
||||||
|
tsaChainNotValidated ||
|
||||||
|
(hasExpiredTsaCert && !signerNotExpired)) {
|
||||||
|
|
||||||
|
if (strict) {
|
||||||
|
result = rb.getString(isSigning
|
||||||
|
? "jar.signed.with.signer.errors."
|
||||||
|
: "jar.verified.with.signer.errors.");
|
||||||
|
} else {
|
||||||
|
result = rb.getString(isSigning
|
||||||
|
? "jar.signed."
|
||||||
|
: "jar.verified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (badKeyUsage) {
|
||||||
|
errors.add(rb.getString(isSigning
|
||||||
|
? "The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."
|
||||||
|
: "This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (badExtendedKeyUsage) {
|
||||||
|
errors.add(rb.getString(isSigning
|
||||||
|
? "The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."
|
||||||
|
: "This.jar.contains.entries.whose.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (badNetscapeCertType) {
|
||||||
|
errors.add(rb.getString(isSigning
|
||||||
|
? "The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."
|
||||||
|
: "This.jar.contains.entries.whose.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// only in verifying
|
||||||
|
if (hasUnsignedEntry) {
|
||||||
|
errors.add(rb.getString(
|
||||||
|
"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked."));
|
||||||
|
}
|
||||||
|
if (hasExpiredCert) {
|
||||||
|
errors.add(rb.getString(isSigning
|
||||||
|
? "The.signer.certificate.has.expired."
|
||||||
|
: "This.jar.contains.entries.whose.signer.certificate.has.expired."));
|
||||||
|
}
|
||||||
|
if (notYetValidCert) {
|
||||||
|
errors.add(rb.getString(isSigning
|
||||||
|
? "The.signer.certificate.is.not.yet.valid."
|
||||||
|
: "This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chainNotValidated) {
|
||||||
|
errors.add(String.format(rb.getString(isSigning
|
||||||
|
? "The.signer.s.certificate.chain.is.invalid.reason.1"
|
||||||
|
: "This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1"),
|
||||||
|
chainNotValidatedReason.getLocalizedMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasExpiredTsaCert) {
|
||||||
|
errors.add(rb.getString("The.timestamp.has.expired."));
|
||||||
|
}
|
||||||
|
if (tsaChainNotValidated) {
|
||||||
|
errors.add(String.format(rb.getString(isSigning
|
||||||
|
? "The.tsa.certificate.chain.is.invalid.reason.1"
|
||||||
|
: "This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1"),
|
||||||
|
tsaChainNotValidatedReason.getLocalizedMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// only in verifying
|
||||||
|
if (notSignedByAlias) {
|
||||||
|
errors.add(
|
||||||
|
rb.getString("This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// only in verifying
|
||||||
|
if (aliasNotInStore) {
|
||||||
|
errors.add(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signerSelfSigned) {
|
||||||
|
errors.add(rb.getString(isSigning
|
||||||
|
? "The.signer.s.certificate.is.self.signed."
|
||||||
|
: "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 ((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)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = rb.getString(isSigning ? "jar.signed." : "jar.verified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasExpiredTsaCert) {
|
||||||
|
// No need to warn about expiring if already expired
|
||||||
|
hasExpiringTsaCert = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasExpiringCert ||
|
||||||
|
(hasExpiringTsaCert && expireDate != null) ||
|
||||||
|
(noTimestamp && expireDate != null) ||
|
||||||
|
(hasExpiredTsaCert && signerNotExpired)) {
|
||||||
|
|
||||||
|
if (hasExpiredTsaCert && signerNotExpired) {
|
||||||
|
if (expireDate != null) {
|
||||||
|
warnings.add(String.format(
|
||||||
|
rb.getString("The.timestamp.expired.1.but.usable.2"),
|
||||||
|
tsaExpireDate,
|
||||||
|
expireDate));
|
||||||
|
}
|
||||||
|
// Reset the flag so exit code is 0
|
||||||
|
hasExpiredTsaCert = false;
|
||||||
|
}
|
||||||
|
if (hasExpiringCert) {
|
||||||
|
warnings.add(rb.getString(isSigning
|
||||||
|
? "The.signer.certificate.will.expire.within.six.months."
|
||||||
|
: "This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
|
||||||
|
}
|
||||||
|
if (hasExpiringTsaCert && expireDate != null) {
|
||||||
|
if (expireDate.after(tsaExpireDate)) {
|
||||||
|
warnings.add(String.format(rb.getString(
|
||||||
|
"The.timestamp.will.expire.within.one.year.on.1.but.2"), tsaExpireDate, expireDate));
|
||||||
|
} else {
|
||||||
|
warnings.add(String.format(rb.getString(
|
||||||
|
"The.timestamp.will.expire.within.one.year.on.1"), tsaExpireDate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (noTimestamp && expireDate != null) {
|
||||||
|
if (hasTimestampBlock) {
|
||||||
|
warnings.add(String.format(rb.getString(isSigning
|
||||||
|
? "invalid.timestamp.signing"
|
||||||
|
: "bad.timestamp.verifying"), expireDate));
|
||||||
|
} else {
|
||||||
|
warnings.add(String.format(rb.getString(isSigning
|
||||||
|
? "no.timestamp.signing"
|
||||||
|
: "no.timestamp.verifying"), expireDate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(result);
|
||||||
|
if (strict) {
|
||||||
|
if (!errors.isEmpty()) {
|
||||||
|
System.out.println();
|
||||||
|
System.out.println(rb.getString("Error."));
|
||||||
|
errors.forEach(System.out::println);
|
||||||
|
}
|
||||||
|
if (!warnings.isEmpty()) {
|
||||||
|
System.out.println();
|
||||||
|
System.out.println(rb.getString("Warning."));
|
||||||
|
warnings.forEach(System.out::println);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!errors.isEmpty() || !warnings.isEmpty()) {
|
||||||
|
System.out.println();
|
||||||
|
System.out.println(rb.getString("Warning."));
|
||||||
|
errors.forEach(System.out::println);
|
||||||
|
warnings.forEach(System.out::println);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isSigning && (!errors.isEmpty() || !warnings.isEmpty())) {
|
||||||
|
if (! (verbose != null && showcerts)) {
|
||||||
|
System.out.println();
|
||||||
|
System.out.println(rb.getString(
|
||||||
|
"Re.run.with.the.verbose.and.certs.options.for.more.details."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSigning || verbose != null) {
|
||||||
|
// Always print out expireDate, unless expired or expiring.
|
||||||
|
if (!hasExpiringCert && !hasExpiredCert
|
||||||
|
&& expireDate != null && signerNotExpired) {
|
||||||
|
info.add(String.format(rb.getString(
|
||||||
|
"The.signer.certificate.will.expire.on.1."), expireDate));
|
||||||
|
}
|
||||||
|
if (!noTimestamp) {
|
||||||
|
if (!hasExpiringTsaCert && !hasExpiredTsaCert && tsaExpireDate != null) {
|
||||||
|
if (signerNotExpired) {
|
||||||
|
info.add(String.format(rb.getString(
|
||||||
|
"The.timestamp.will.expire.on.1."), tsaExpireDate));
|
||||||
|
} else {
|
||||||
|
info.add(String.format(rb.getString(
|
||||||
|
"signer.cert.expired.1.but.timestamp.good.2."),
|
||||||
|
expireDate,
|
||||||
|
tsaExpireDate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.isEmpty()) {
|
||||||
|
System.out.println();
|
||||||
|
info.forEach(System.out::println);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String withWeak(String alg, Set<CryptoPrimitive> primitiveSet) {
|
private String withWeak(String alg, Set<CryptoPrimitive> primitiveSet) {
|
||||||
if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
|
if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
|
||||||
return alg;
|
return alg;
|
||||||
|
@ -1152,8 +1275,9 @@ public class Main {
|
||||||
*
|
*
|
||||||
* Note: no newline character at the end.
|
* Note: no newline character at the end.
|
||||||
*
|
*
|
||||||
* When isTsCert is true, this method sets global flags like hasExpiredCert,
|
* This method sets global flags like hasExpiringCert, hasExpiredCert,
|
||||||
* notYetValidCert, badKeyUsage, badExtendedKeyUsage, badNetscapeCertType.
|
* notYetValidCert, badKeyUsage, badExtendedKeyUsage, badNetscapeCertType,
|
||||||
|
* hasExpiringTsaCert, hasExpiredTsaCert.
|
||||||
*
|
*
|
||||||
* @param isTsCert true if c is in the TSA cert chain, false otherwise.
|
* @param isTsCert true if c is in the TSA cert chain, false otherwise.
|
||||||
* @param checkUsage true to check code signer keyUsage
|
* @param checkUsage true to check code signer keyUsage
|
||||||
|
@ -1182,55 +1306,75 @@ public class Main {
|
||||||
if (x509Cert != null) {
|
if (x509Cert != null) {
|
||||||
|
|
||||||
certStr.append("\n").append(tab).append("[");
|
certStr.append("\n").append(tab).append("[");
|
||||||
Date notAfter = x509Cert.getNotAfter();
|
|
||||||
try {
|
if (trustedCerts.contains(x509Cert)) {
|
||||||
boolean printValidity = true;
|
certStr.append(rb.getString("trusted.certificate"));
|
||||||
if (timestamp == null) {
|
} else {
|
||||||
if (expireDate.getTime() == 0 || expireDate.after(notAfter)) {
|
Date notAfter = x509Cert.getNotAfter();
|
||||||
expireDate = notAfter;
|
try {
|
||||||
}
|
boolean printValidity = true;
|
||||||
x509Cert.checkValidity();
|
if (isTsCert) {
|
||||||
// test if cert will expire within six months
|
if (tsaExpireDate == null || tsaExpireDate.after(notAfter)) {
|
||||||
if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) {
|
tsaExpireDate = notAfter;
|
||||||
if (!isTsCert) hasExpiringCert = true;
|
}
|
||||||
if (expiringTimeForm == null) {
|
} else {
|
||||||
expiringTimeForm = new MessageFormat(
|
if (expireDate == null || expireDate.after(notAfter)) {
|
||||||
rb.getString("certificate.will.expire.on"));
|
expireDate = notAfter;
|
||||||
}
|
}
|
||||||
Object[] source = { notAfter };
|
|
||||||
certStr.append(expiringTimeForm.format(source));
|
|
||||||
printValidity = false;
|
|
||||||
}
|
}
|
||||||
} else {
|
if (timestamp == null) {
|
||||||
x509Cert.checkValidity(timestamp);
|
x509Cert.checkValidity();
|
||||||
}
|
// test if cert will expire within six months (or one year for tsa)
|
||||||
if (printValidity) {
|
long age = isTsCert ? ONE_YEAR : SIX_MONTHS;
|
||||||
if (validityTimeForm == null) {
|
if (notAfter.getTime() < System.currentTimeMillis() + age) {
|
||||||
validityTimeForm = new MessageFormat(
|
if (isTsCert) {
|
||||||
rb.getString("certificate.is.valid.from"));
|
hasExpiringTsaCert = true;
|
||||||
|
} else {
|
||||||
|
hasExpiringCert = true;
|
||||||
|
}
|
||||||
|
if (expiringTimeForm == null) {
|
||||||
|
expiringTimeForm = new MessageFormat(
|
||||||
|
rb.getString("certificate.will.expire.on"));
|
||||||
|
}
|
||||||
|
Object[] source = {notAfter};
|
||||||
|
certStr.append(expiringTimeForm.format(source));
|
||||||
|
printValidity = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
x509Cert.checkValidity(timestamp);
|
||||||
|
}
|
||||||
|
if (printValidity) {
|
||||||
|
if (validityTimeForm == null) {
|
||||||
|
validityTimeForm = new MessageFormat(
|
||||||
|
rb.getString("certificate.is.valid.from"));
|
||||||
|
}
|
||||||
|
Object[] source = {x509Cert.getNotBefore(), notAfter};
|
||||||
|
certStr.append(validityTimeForm.format(source));
|
||||||
|
}
|
||||||
|
} catch (CertificateExpiredException cee) {
|
||||||
|
if (isTsCert) {
|
||||||
|
hasExpiredTsaCert = true;
|
||||||
|
} else {
|
||||||
|
hasExpiredCert = true;
|
||||||
}
|
}
|
||||||
Object[] source = { x509Cert.getNotBefore(), notAfter };
|
|
||||||
certStr.append(validityTimeForm.format(source));
|
|
||||||
}
|
|
||||||
} catch (CertificateExpiredException cee) {
|
|
||||||
if (!isTsCert) hasExpiredCert = true;
|
|
||||||
|
|
||||||
if (expiredTimeForm == null) {
|
if (expiredTimeForm == null) {
|
||||||
expiredTimeForm = new MessageFormat(
|
expiredTimeForm = new MessageFormat(
|
||||||
rb.getString("certificate.expired.on"));
|
rb.getString("certificate.expired.on"));
|
||||||
}
|
}
|
||||||
Object[] source = { notAfter };
|
Object[] source = {notAfter};
|
||||||
certStr.append(expiredTimeForm.format(source));
|
certStr.append(expiredTimeForm.format(source));
|
||||||
|
|
||||||
} catch (CertificateNotYetValidException cnyve) {
|
} catch (CertificateNotYetValidException cnyve) {
|
||||||
if (!isTsCert) notYetValidCert = true;
|
if (!isTsCert) notYetValidCert = true;
|
||||||
|
|
||||||
if (notYetTimeForm == null) {
|
if (notYetTimeForm == null) {
|
||||||
notYetTimeForm = new MessageFormat(
|
notYetTimeForm = new MessageFormat(
|
||||||
rb.getString("certificate.is.not.valid.until"));
|
rb.getString("certificate.is.not.valid.until"));
|
||||||
|
}
|
||||||
|
Object[] source = {x509Cert.getNotBefore()};
|
||||||
|
certStr.append(notYetTimeForm.format(source));
|
||||||
}
|
}
|
||||||
Object[] source = { x509Cert.getNotBefore() };
|
|
||||||
certStr.append(notYetTimeForm.format(source));
|
|
||||||
}
|
}
|
||||||
certStr.append("]");
|
certStr.append("]");
|
||||||
|
|
||||||
|
@ -1446,8 +1590,6 @@ public class Main {
|
||||||
if (tSAPolicyID != null) {
|
if (tSAPolicyID != null) {
|
||||||
builder.setProperty("tsaPolicyId", tSAPolicyID);
|
builder.setProperty("tsaPolicyId", tSAPolicyID);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
noTimestamp = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (altSignerClass != null) {
|
if (altSignerClass != null) {
|
||||||
|
@ -1519,160 +1661,64 @@ public class Main {
|
||||||
error(failedMessage, failedCause);
|
error(failedMessage, failedCause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (verbose != null) {
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
// The JarSigner API always accepts the timestamp received.
|
// The JarSigner API always accepts the timestamp received.
|
||||||
// We need to extract the certs from the signed jar to
|
// We need to extract the certs from the signed jar to
|
||||||
// validate it.
|
// validate it.
|
||||||
if (!noTimestamp) {
|
try (JarFile check = new JarFile(signedJarFile)) {
|
||||||
try (JarFile check = new JarFile(signedJarFile)) {
|
PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry(
|
||||||
PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry(
|
"META-INF/" + sigfile + "." + privateKey.getAlgorithm())));
|
||||||
"META-INF/" + sigfile + "." + privateKey.getAlgorithm())));
|
Timestamp ts = null;
|
||||||
|
try {
|
||||||
SignerInfo si = p7.getSignerInfos()[0];
|
SignerInfo si = p7.getSignerInfos()[0];
|
||||||
PKCS7 tsToken = si.getTsToken();
|
if (si.getTsToken() != null) {
|
||||||
SignerInfo tsSi = tsToken.getSignerInfos()[0];
|
hasTimestampBlock = true;
|
||||||
try {
|
|
||||||
validateCertChain(Validator.VAR_TSA_SERVER,
|
|
||||||
tsSi.getCertificateChain(tsToken), null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
tsaChainNotValidated = true;
|
|
||||||
tsaChainNotValidatedReason = e;
|
|
||||||
}
|
}
|
||||||
|
ts = si.getTimestamp();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (debug) {
|
tsaChainNotValidated = true;
|
||||||
e.printStackTrace();
|
tsaChainNotValidatedReason = e;
|
||||||
|
}
|
||||||
|
// Spaces before the ">>> Signer" and other lines are different
|
||||||
|
String result = certsAndTSInfo("", " ", Arrays.asList(certChain), ts);
|
||||||
|
if (verbose != null) {
|
||||||
|
System.out.println(result);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (debug) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signedjar == null) {
|
||||||
|
// attempt an atomic rename. If that fails,
|
||||||
|
// rename the original jar file, then the signed
|
||||||
|
// one, then delete the original.
|
||||||
|
if (!signedJarFile.renameTo(jarFile)) {
|
||||||
|
File origJar = new File(jarName+".orig");
|
||||||
|
|
||||||
|
if (jarFile.renameTo(origJar)) {
|
||||||
|
if (signedJarFile.renameTo(jarFile)) {
|
||||||
|
origJar.delete();
|
||||||
|
} else {
|
||||||
|
MessageFormat form = new MessageFormat(rb.getString
|
||||||
|
("attempt.to.rename.signedJarFile.to.jarFile.failed"));
|
||||||
|
Object[] source = {signedJarFile, jarFile};
|
||||||
|
error(form.format(source));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MessageFormat form = new MessageFormat(rb.getString
|
||||||
|
("attempt.to.rename.jarFile.to.origJar.failed"));
|
||||||
|
Object[] source = {jarFile, origJar};
|
||||||
|
error(form.format(source));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no IOException thrown in the follow try clause, so disable
|
displayMessagesAndResult(true);
|
||||||
// the try clause.
|
|
||||||
// try {
|
|
||||||
if (signedjar == null) {
|
|
||||||
// attempt an atomic rename. If that fails,
|
|
||||||
// rename the original jar file, then the signed
|
|
||||||
// one, then delete the original.
|
|
||||||
if (!signedJarFile.renameTo(jarFile)) {
|
|
||||||
File origJar = new File(jarName+".orig");
|
|
||||||
|
|
||||||
if (jarFile.renameTo(origJar)) {
|
|
||||||
if (signedJarFile.renameTo(jarFile)) {
|
|
||||||
origJar.delete();
|
|
||||||
} else {
|
|
||||||
MessageFormat form = new MessageFormat(rb.getString
|
|
||||||
("attempt.to.rename.signedJarFile.to.jarFile.failed"));
|
|
||||||
Object[] source = {signedJarFile, jarFile};
|
|
||||||
error(form.format(source));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
MessageFormat form = new MessageFormat(rb.getString
|
|
||||||
("attempt.to.rename.jarFile.to.origJar.failed"));
|
|
||||||
Object[] source = {jarFile, origJar};
|
|
||||||
error(form.format(source));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean warningAppeared = false;
|
|
||||||
if (weakAlg != 0 || badKeyUsage || badExtendedKeyUsage
|
|
||||||
|| badNetscapeCertType || notYetValidCert
|
|
||||||
|| chainNotValidated || tsaChainNotValidated
|
|
||||||
|| hasExpiredCert || signerSelfSigned) {
|
|
||||||
if (strict) {
|
|
||||||
System.out.println(rb.getString("jar.signed.with.signer.errors."));
|
|
||||||
System.out.println();
|
|
||||||
System.out.println(rb.getString("Error."));
|
|
||||||
} else {
|
|
||||||
System.out.println(rb.getString("jar.signed."));
|
|
||||||
System.out.println();
|
|
||||||
System.out.println(rb.getString("Warning."));
|
|
||||||
warningAppeared = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (badKeyUsage) {
|
|
||||||
System.out.println(
|
|
||||||
rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (badExtendedKeyUsage) {
|
|
||||||
System.out.println(
|
|
||||||
rb.getString("The.signer.certificate.s.ExtendedKeyUsage.extension.doesn.t.allow.code.signing."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (badNetscapeCertType) {
|
|
||||||
System.out.println(
|
|
||||||
rb.getString("The.signer.certificate.s.NetscapeCertType.extension.doesn.t.allow.code.signing."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasExpiredCert) {
|
|
||||||
System.out.println(
|
|
||||||
rb.getString("The.signer.certificate.has.expired."));
|
|
||||||
} else if (notYetValidCert) {
|
|
||||||
System.out.println(
|
|
||||||
rb.getString("The.signer.certificate.is.not.yet.valid."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chainNotValidated) {
|
|
||||||
System.out.println(String.format(
|
|
||||||
rb.getString("The.signer.s.certificate.chain.is.invalid.reason.1"),
|
|
||||||
chainNotValidatedReason.getLocalizedMessage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsaChainNotValidated) {
|
|
||||||
System.out.println(String.format(
|
|
||||||
rb.getString("The.tsa.certificate.chain.is.invalid.reason.1"),
|
|
||||||
tsaChainNotValidatedReason.getLocalizedMessage()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (signerSelfSigned) {
|
|
||||||
System.out.println(
|
|
||||||
rb.getString("The.signer.s.certificate.is.self.signed."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((weakAlg & 1) == 1) {
|
|
||||||
System.out.println(String.format(
|
|
||||||
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
|
|
||||||
digestalg, "-digestalg"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((weakAlg & 2) == 2) {
|
|
||||||
System.out.println(String.format(
|
|
||||||
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
|
|
||||||
sigalg, "-sigalg"));
|
|
||||||
}
|
|
||||||
if ((weakAlg & 4) == 4) {
|
|
||||||
System.out.println(String.format(
|
|
||||||
rb.getString("The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk."),
|
|
||||||
tSADigestAlg, "-tsadigestalg"));
|
|
||||||
}
|
|
||||||
if ((weakAlg & 8) == 8) {
|
|
||||||
System.out.println(String.format(
|
|
||||||
rb.getString("The.1.signing.key.has.a.keysize.of.2.which.is.considered.a.security.risk."),
|
|
||||||
privateKey.getAlgorithm(), KeyUtil.getKeySize(privateKey)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
System.out.println(rb.getString("jar.signed."));
|
|
||||||
}
|
|
||||||
if (hasExpiringCert || noTimestamp) {
|
|
||||||
if (!warningAppeared) {
|
|
||||||
System.out.println();
|
|
||||||
System.out.println(rb.getString("Warning."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasExpiringCert) {
|
|
||||||
System.out.println(
|
|
||||||
rb.getString("The.signer.certificate.will.expire.within.six.months."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (noTimestamp) {
|
|
||||||
System.out.println(
|
|
||||||
String.format(rb.getString("no.timestamp.signing"), expireDate));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// no IOException thrown in the above try clause, so disable
|
|
||||||
// the catch clause.
|
|
||||||
// } catch(IOException ioe) {
|
|
||||||
// error(rb.getString("unable.to.sign.jar.")+ioe, ioe);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1691,31 +1737,57 @@ public class Main {
|
||||||
Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>();
|
Map<CodeSigner,String> cacheForSignerInfo = new IdentityHashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string of singer info, with a newline at the end
|
* Returns a string of signer info, with a newline at the end.
|
||||||
|
* Called by verifyJar().
|
||||||
*/
|
*/
|
||||||
private String signerInfo(CodeSigner signer, String tab) throws Exception {
|
private String signerInfo(CodeSigner signer, String tab) throws Exception {
|
||||||
if (cacheForSignerInfo.containsKey(signer)) {
|
if (cacheForSignerInfo.containsKey(signer)) {
|
||||||
return cacheForSignerInfo.get(signer);
|
return cacheForSignerInfo.get(signer);
|
||||||
}
|
}
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
|
List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
|
||||||
// display the signature timestamp, if present
|
// signing time is only displayed on verification
|
||||||
Date timestamp;
|
|
||||||
Timestamp ts = signer.getTimestamp();
|
Timestamp ts = signer.getTimestamp();
|
||||||
|
String tsLine = "";
|
||||||
|
if (ts != null) {
|
||||||
|
tsLine = printTimestamp(tab, ts) + "\n";
|
||||||
|
}
|
||||||
|
// Spaces before the ">>> Signer" and other lines are the same.
|
||||||
|
|
||||||
|
String result = certsAndTSInfo(tab, tab, certs, ts);
|
||||||
|
cacheForSignerInfo.put(signer, tsLine + result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills info on certs and timestamp into a StringBuilder, sets
|
||||||
|
* warning flags (through printCert) and validates cert chains.
|
||||||
|
*
|
||||||
|
* @param tab1 spaces before the ">>> Signer" line
|
||||||
|
* @param tab2 spaces before the other lines
|
||||||
|
* @param certs the signer cert
|
||||||
|
* @param ts the timestamp, can be null
|
||||||
|
* @return the info as a string
|
||||||
|
*/
|
||||||
|
private String certsAndTSInfo(
|
||||||
|
String tab1,
|
||||||
|
String tab2,
|
||||||
|
List<? extends Certificate> certs, Timestamp ts)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
Date timestamp;
|
||||||
if (ts != null) {
|
if (ts != null) {
|
||||||
sb.append(printTimestamp(tab, ts));
|
|
||||||
sb.append('\n');
|
|
||||||
timestamp = ts.getTimestamp();
|
timestamp = ts.getTimestamp();
|
||||||
|
noTimestamp = false;
|
||||||
} else {
|
} else {
|
||||||
timestamp = null;
|
timestamp = null;
|
||||||
noTimestamp = true;
|
|
||||||
}
|
}
|
||||||
// display the certificate(sb). The first one is end-entity cert and
|
// display the certificate(sb). The first one is end-entity cert and
|
||||||
// its KeyUsage should be checked.
|
// its KeyUsage should be checked.
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
sb.append(tab).append(rb.getString("...Signer")).append('\n');
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(tab1).append(rb.getString("...Signer")).append('\n');
|
||||||
for (Certificate c : certs) {
|
for (Certificate c : certs) {
|
||||||
sb.append(printCert(false, tab, c, timestamp, first));
|
sb.append(printCert(false, tab2, c, timestamp, first));
|
||||||
sb.append('\n');
|
sb.append('\n');
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
|
@ -1724,13 +1796,13 @@ public class Main {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
chainNotValidated = true;
|
chainNotValidated = true;
|
||||||
chainNotValidatedReason = e;
|
chainNotValidatedReason = e;
|
||||||
sb.append(tab).append(rb.getString(".Invalid.certificate.chain."))
|
sb.append(tab2).append(rb.getString(".Invalid.certificate.chain."))
|
||||||
.append(e.getLocalizedMessage()).append("]\n");
|
.append(e.getLocalizedMessage()).append("]\n");
|
||||||
}
|
}
|
||||||
if (ts != null) {
|
if (ts != null) {
|
||||||
sb.append(tab).append(rb.getString("...TSA")).append('\n');
|
sb.append(tab1).append(rb.getString("...TSA")).append('\n');
|
||||||
for (Certificate c : ts.getSignerCertPath().getCertificates()) {
|
for (Certificate c : ts.getSignerCertPath().getCertificates()) {
|
||||||
sb.append(printCert(true, tab, c, timestamp, false));
|
sb.append(printCert(true, tab2, c, null, false));
|
||||||
sb.append('\n');
|
sb.append('\n');
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -1739,7 +1811,7 @@ public class Main {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
tsaChainNotValidated = true;
|
tsaChainNotValidated = true;
|
||||||
tsaChainNotValidatedReason = e;
|
tsaChainNotValidatedReason = e;
|
||||||
sb.append(tab).append(rb.getString(".Invalid.TSA.certificate.chain."))
|
sb.append(tab2).append(rb.getString(".Invalid.TSA.certificate.chain."))
|
||||||
.append(e.getLocalizedMessage()).append("]\n");
|
.append(e.getLocalizedMessage()).append("]\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1747,9 +1819,8 @@ public class Main {
|
||||||
&& KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) {
|
&& KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) {
|
||||||
signerSelfSigned = true;
|
signerSelfSigned = true;
|
||||||
}
|
}
|
||||||
String result = sb.toString();
|
|
||||||
cacheForSignerInfo.put(signer, result);
|
return sb.toString();
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadKeyStore(String keyStoreName, boolean prompt) {
|
void loadKeyStore(String keyStoreName, boolean prompt) {
|
||||||
|
@ -1760,7 +1831,6 @@ public class Main {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Set<TrustAnchor> tas = new HashSet<>();
|
|
||||||
try {
|
try {
|
||||||
KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
|
KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
|
||||||
if (caks != null) {
|
if (caks != null) {
|
||||||
|
@ -1768,7 +1838,7 @@ public class Main {
|
||||||
while (aliases.hasMoreElements()) {
|
while (aliases.hasMoreElements()) {
|
||||||
String a = aliases.nextElement();
|
String a = aliases.nextElement();
|
||||||
try {
|
try {
|
||||||
tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null));
|
trustedCerts.add((X509Certificate)caks.getCertificate(a));
|
||||||
} catch (Exception e2) {
|
} catch (Exception e2) {
|
||||||
// ignore, when a SecretkeyEntry does not include a cert
|
// ignore, when a SecretkeyEntry does not include a cert
|
||||||
}
|
}
|
||||||
|
@ -1827,7 +1897,7 @@ public class Main {
|
||||||
// PrivateKeyEntry
|
// PrivateKeyEntry
|
||||||
if (store.isCertificateEntry(a) ||
|
if (store.isCertificateEntry(a) ||
|
||||||
c.getSubjectDN().equals(c.getIssuerDN())) {
|
c.getSubjectDN().equals(c.getIssuerDN())) {
|
||||||
tas.add(new TrustAnchor(c, null));
|
trustedCerts.add(c);
|
||||||
}
|
}
|
||||||
} catch (Exception e2) {
|
} catch (Exception e2) {
|
||||||
// ignore, when a SecretkeyEntry does not include a cert
|
// ignore, when a SecretkeyEntry does not include a cert
|
||||||
|
@ -1835,7 +1905,11 @@ public class Main {
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
pkixParameters = new PKIXBuilderParameters(tas, null);
|
pkixParameters = new PKIXBuilderParameters(
|
||||||
|
trustedCerts.stream()
|
||||||
|
.map(c -> new TrustAnchor(c, null))
|
||||||
|
.collect(Collectors.toSet()),
|
||||||
|
null);
|
||||||
pkixParameters.setRevocationEnabled(false);
|
pkixParameters.setRevocationEnabled(false);
|
||||||
} catch (InvalidAlgorithmParameterException ex) {
|
} catch (InvalidAlgorithmParameterException ex) {
|
||||||
// Only if tas is empty
|
// Only if tas is empty
|
||||||
|
@ -1951,6 +2025,7 @@ public class Main {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called by signJar().
|
||||||
void getAliasInfo(String alias) throws Exception {
|
void getAliasInfo(String alias) throws Exception {
|
||||||
|
|
||||||
Key key = null;
|
Key key = null;
|
||||||
|
@ -1995,22 +2070,6 @@ public class Main {
|
||||||
certChain[i] = (X509Certificate)cs[i];
|
certChain[i] = (X509Certificate)cs[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't meant to print anything, the next call
|
|
||||||
// checks validity and keyUsage etc
|
|
||||||
printCert(false, "", certChain[0], null, true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
validateCertChain(Validator.VAR_CODE_SIGNING,
|
|
||||||
Arrays.asList(certChain), null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
chainNotValidated = true;
|
|
||||||
chainNotValidatedReason = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KeyStoreUtil.isSelfSigned(certChain[0])) {
|
|
||||||
signerSelfSigned = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!token && keypass == null)
|
if (!token && keypass == null)
|
||||||
key = store.getKey(alias, storepass);
|
key = store.getKey(alias, storepass);
|
||||||
|
@ -2066,7 +2125,7 @@ public class Main {
|
||||||
* @param parameter this might be a timestamp
|
* @param parameter this might be a timestamp
|
||||||
*/
|
*/
|
||||||
void validateCertChain(String variant, List<? extends Certificate> certs,
|
void validateCertChain(String variant, List<? extends Certificate> certs,
|
||||||
Object parameter)
|
Timestamp parameter)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
try {
|
try {
|
||||||
Validator.getInstance(Validator.TYPE_PKIX,
|
Validator.getInstance(Validator.TYPE_PKIX,
|
||||||
|
@ -2080,8 +2139,22 @@ public class Main {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exception might be dismissed if another warning flag
|
// Exception might be dismissed if another warning flag
|
||||||
// is already set by printCert. This is only done for
|
// is already set by printCert.
|
||||||
// code signing certs.
|
|
||||||
|
if (variant.equals(Validator.VAR_TSA_SERVER) &&
|
||||||
|
e instanceof ValidatorException) {
|
||||||
|
// Throw cause if it's CertPathValidatorException,
|
||||||
|
if (e.getCause() != null &&
|
||||||
|
e.getCause() instanceof CertPathValidatorException) {
|
||||||
|
e = (Exception) e.getCause();
|
||||||
|
Throwable t = e.getCause();
|
||||||
|
if ((t instanceof CertificateExpiredException &&
|
||||||
|
hasExpiredTsaCert)) {
|
||||||
|
// we already have hasExpiredTsaCert
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (variant.equals(Validator.VAR_CODE_SIGNING) &&
|
if (variant.equals(Validator.VAR_CODE_SIGNING) &&
|
||||||
e instanceof ValidatorException) {
|
e instanceof ValidatorException) {
|
||||||
|
|
|
@ -229,6 +229,7 @@ public class Resources extends java.util.ListResourceBundle {
|
||||||
{"Error.", "Error: "},
|
{"Error.", "Error: "},
|
||||||
{"...Signer", ">>> Signer"},
|
{"...Signer", ">>> Signer"},
|
||||||
{"...TSA", ">>> TSA"},
|
{"...TSA", ">>> TSA"},
|
||||||
|
{"trusted.certificate", "trusted certificate"},
|
||||||
{"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
|
{"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
|
||||||
"This jar contains unsigned entries which have not been integrity-checked. "},
|
"This jar contains unsigned entries which have not been integrity-checked. "},
|
||||||
{"This.jar.contains.entries.whose.signer.certificate.has.expired.",
|
{"This.jar.contains.entries.whose.signer.certificate.has.expired.",
|
||||||
|
@ -245,8 +246,16 @@ public class Resources extends java.util.ListResourceBundle {
|
||||||
"Re-run with the -verbose and -certs options for more details."},
|
"Re-run with the -verbose and -certs options for more details."},
|
||||||
{"The.signer.certificate.has.expired.",
|
{"The.signer.certificate.has.expired.",
|
||||||
"The signer certificate has expired."},
|
"The signer certificate has expired."},
|
||||||
|
{"The.timestamp.expired.1.but.usable.2",
|
||||||
|
"The timestamp expired on %1$tY-%1$tm-%1$td. However, the JAR will be valid until the signer certificate expires on %2$tY-%2$tm-%2$td."},
|
||||||
|
{"The.timestamp.has.expired.",
|
||||||
|
"The timestamp has expired."},
|
||||||
{"The.signer.certificate.will.expire.within.six.months.",
|
{"The.signer.certificate.will.expire.within.six.months.",
|
||||||
"The signer certificate will expire within six months."},
|
"The signer certificate will expire within six months."},
|
||||||
|
{"The.timestamp.will.expire.within.one.year.on.1",
|
||||||
|
"The timestamp will expire within one year on %1$tY-%1$tm-%1$td."},
|
||||||
|
{"The.timestamp.will.expire.within.one.year.on.1.but.2",
|
||||||
|
"The timestamp will expire within one year on %1$tY-%1$tm-%1$td. However, the JAR will be valid until the signer certificate expires on %2$tY-%2$tm-%2$td."},
|
||||||
{"The.signer.certificate.is.not.yet.valid.",
|
{"The.signer.certificate.is.not.yet.valid.",
|
||||||
"The signer certificate is not yet valid."},
|
"The signer certificate is not yet valid."},
|
||||||
{"The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
|
{"The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.",
|
||||||
|
@ -279,10 +288,18 @@ public class Resources extends java.util.ListResourceBundle {
|
||||||
"This jar contains entries whose TSA certificate chain is invalid. Reason: %s"},
|
"This jar contains entries whose TSA certificate chain is invalid. Reason: %s"},
|
||||||
{"no.timestamp.signing",
|
{"no.timestamp.signing",
|
||||||
"No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td)."},
|
"No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td)."},
|
||||||
|
{"invalid.timestamp.signing",
|
||||||
|
"The timestamp is invalid. Without a valid timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td)."},
|
||||||
{"no.timestamp.verifying",
|
{"no.timestamp.verifying",
|
||||||
"This jar contains signatures that do not include a timestamp. Without a timestamp, users may not be able to validate this jar after any of the signer certificates expire (as early as %1$tY-%1$tm-%1$td)."},
|
"This jar contains signatures that do not include a timestamp. Without a timestamp, users may not be able to validate this jar after any of the signer certificates expire (as early as %1$tY-%1$tm-%1$td)."},
|
||||||
{"bad.timestamp.verifying",
|
{"bad.timestamp.verifying",
|
||||||
"This jar contains signatures that include an invalid timestamp. Without a valid timestamp, users may not be able to validate this jar after any of the signer certificates expire (as early as %1$tY-%1$tm-%1$td).\nRerun jarsigner with -J-Djava.security.debug=jar for more information."},
|
"This jar contains signatures that include an invalid timestamp. Without a valid timestamp, users may not be able to validate this jar after any of the signer certificates expire (as early as %1$tY-%1$tm-%1$td).\nRerun jarsigner with -J-Djava.security.debug=jar for more information."},
|
||||||
|
{"The.signer.certificate.will.expire.on.1.",
|
||||||
|
"The signer certificate will expire on %1$tY-%1$tm-%1$td."},
|
||||||
|
{"The.timestamp.will.expire.on.1.",
|
||||||
|
"The timestamp will expire on %1$tY-%1$tm-%1$td."},
|
||||||
|
{"signer.cert.expired.1.but.timestamp.good.2.",
|
||||||
|
"The signer certificate expired on %1$tY-%1$tm-%1$td. However, the JAR will be valid until the timestamp expires on %2$tY-%2$tm-%2$td."},
|
||||||
{"Unknown.password.type.", "Unknown password type: "},
|
{"Unknown.password.type.", "Unknown password type: "},
|
||||||
{"Cannot.find.environment.variable.",
|
{"Cannot.find.environment.variable.",
|
||||||
"Cannot find environment variable: "},
|
"Cannot find environment variable: "},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -79,6 +79,7 @@ import sun.security.x509.X500Name;
|
||||||
* jdk.test.lib.JDKToolLauncher
|
* jdk.test.lib.JDKToolLauncher
|
||||||
* jdk.test.lib.Platform
|
* jdk.test.lib.Platform
|
||||||
* jdk.test.lib.process.*
|
* jdk.test.lib.process.*
|
||||||
|
* @compile -XDignore.symbol.file TimestampCheck.java
|
||||||
* @run main/timeout=600 TimestampCheck
|
* @run main/timeout=600 TimestampCheck
|
||||||
*/
|
*/
|
||||||
public class TimestampCheck {
|
public class TimestampCheck {
|
||||||
|
@ -126,12 +127,12 @@ public class TimestampCheck {
|
||||||
byte[] sign(byte[] input, String path) throws Exception {
|
byte[] sign(byte[] input, String path) throws Exception {
|
||||||
|
|
||||||
DerValue value = new DerValue(input);
|
DerValue value = new DerValue(input);
|
||||||
System.out.println("\nIncoming Request\n===================");
|
System.out.println("#\n# Incoming Request\n===================");
|
||||||
System.out.println("Version: " + value.data.getInteger());
|
System.out.println("# Version: " + value.data.getInteger());
|
||||||
DerValue messageImprint = value.data.getDerValue();
|
DerValue messageImprint = value.data.getDerValue();
|
||||||
AlgorithmId aid = AlgorithmId.parse(
|
AlgorithmId aid = AlgorithmId.parse(
|
||||||
messageImprint.data.getDerValue());
|
messageImprint.data.getDerValue());
|
||||||
System.out.println("AlgorithmId: " + aid);
|
System.out.println("# AlgorithmId: " + aid);
|
||||||
|
|
||||||
ObjectIdentifier policyId = new ObjectIdentifier(defaultPolicyId);
|
ObjectIdentifier policyId = new ObjectIdentifier(defaultPolicyId);
|
||||||
BigInteger nonce = null;
|
BigInteger nonce = null;
|
||||||
|
@ -139,16 +140,16 @@ public class TimestampCheck {
|
||||||
DerValue v = value.data.getDerValue();
|
DerValue v = value.data.getDerValue();
|
||||||
if (v.tag == DerValue.tag_Integer) {
|
if (v.tag == DerValue.tag_Integer) {
|
||||||
nonce = v.getBigInteger();
|
nonce = v.getBigInteger();
|
||||||
System.out.println("nonce: " + nonce);
|
System.out.println("# nonce: " + nonce);
|
||||||
} else if (v.tag == DerValue.tag_Boolean) {
|
} else if (v.tag == DerValue.tag_Boolean) {
|
||||||
System.out.println("certReq: " + v.getBoolean());
|
System.out.println("# certReq: " + v.getBoolean());
|
||||||
} else if (v.tag == DerValue.tag_ObjectId) {
|
} else if (v.tag == DerValue.tag_ObjectId) {
|
||||||
policyId = v.getOID();
|
policyId = v.getOID();
|
||||||
System.out.println("PolicyID: " + policyId);
|
System.out.println("# PolicyID: " + policyId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("\nResponse\n===================");
|
System.out.println("#\n# Response\n===================");
|
||||||
KeyStore ks = KeyStore.getInstance(
|
KeyStore ks = KeyStore.getInstance(
|
||||||
new File(keystore), "changeit".toCharArray());
|
new File(keystore), "changeit".toCharArray());
|
||||||
|
|
||||||
|
@ -232,10 +233,10 @@ public class TimestampCheck {
|
||||||
"1.2.840.113549.1.9.16.1.4"),
|
"1.2.840.113549.1.9.16.1.4"),
|
||||||
new DerValue(tstInfo2.toByteArray()));
|
new DerValue(tstInfo2.toByteArray()));
|
||||||
|
|
||||||
System.out.println("Signing...");
|
System.out.println("# Signing...");
|
||||||
System.out.println(new X500Name(signer
|
System.out.println("# " + new X500Name(signer
|
||||||
.getIssuerX500Principal().getName()));
|
.getIssuerX500Principal().getName()));
|
||||||
System.out.println(signer.getSerialNumber());
|
System.out.println("# " + signer.getSerialNumber());
|
||||||
|
|
||||||
SignerInfo signerInfo = new SignerInfo(
|
SignerInfo signerInfo = new SignerInfo(
|
||||||
new X500Name(signer.getIssuerX500Principal().getName()),
|
new X500Name(signer.getIssuerX500Principal().getName()),
|
||||||
|
@ -306,8 +307,6 @@ public class TimestampCheck {
|
||||||
|
|
||||||
public static void main(String[] args) throws Throwable {
|
public static void main(String[] args) throws Throwable {
|
||||||
|
|
||||||
prepare();
|
|
||||||
|
|
||||||
try (Handler tsa = Handler.init(0, "ks");) {
|
try (Handler tsa = Handler.init(0, "ks");) {
|
||||||
tsa.start();
|
tsa.start();
|
||||||
int port = tsa.getPort();
|
int port = tsa.getPort();
|
||||||
|
@ -315,62 +314,99 @@ public class TimestampCheck {
|
||||||
|
|
||||||
if (args.length == 0) { // Run this test
|
if (args.length == 0) { // Run this test
|
||||||
|
|
||||||
|
prepare();
|
||||||
|
|
||||||
sign("normal")
|
sign("normal")
|
||||||
.shouldNotContain("Warning")
|
.shouldNotContain("Warning")
|
||||||
|
.shouldContain("The signer certificate will expire on")
|
||||||
|
.shouldContain("The timestamp will expire on")
|
||||||
.shouldHaveExitValue(0);
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
verify("normal.jar")
|
verify("normal.jar")
|
||||||
.shouldNotContain("Warning")
|
.shouldNotContain("Warning")
|
||||||
.shouldHaveExitValue(0);
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
verify("normal.jar", "-verbose")
|
||||||
|
.shouldNotContain("Warning")
|
||||||
|
.shouldContain("The signer certificate will expire on")
|
||||||
|
.shouldContain("The timestamp will expire on")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
// Simulate signing at a previous date:
|
// Simulate signing at a previous date:
|
||||||
// 1. tsold will create a timestamp of 20 days ago.
|
// 1. tsold will create a timestamp of 20 days ago.
|
||||||
// 2. oldsigner expired 10 days ago.
|
// 2. oldsigner expired 10 days ago.
|
||||||
// jarsigner will show a warning at signing.
|
|
||||||
signVerbose("tsold", "unsigned.jar", "tsold.jar", "oldsigner")
|
signVerbose("tsold", "unsigned.jar", "tsold.jar", "oldsigner")
|
||||||
.shouldHaveExitValue(4);
|
.shouldNotContain("Warning")
|
||||||
|
.shouldMatch("signer certificate expired on .*. "
|
||||||
|
+ "However, the JAR will be valid")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
// It verifies perfectly.
|
// It verifies perfectly.
|
||||||
verify("tsold.jar", "-verbose", "-certs")
|
verify("tsold.jar", "-verbose", "-certs")
|
||||||
.shouldNotContain("Warning")
|
.shouldNotContain("Warning")
|
||||||
|
.shouldMatch("signer certificate expired on .*. "
|
||||||
|
+ "However, the JAR will be valid")
|
||||||
.shouldHaveExitValue(0);
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
// No timestamp
|
||||||
signVerbose(null, "unsigned.jar", "none.jar", "signer")
|
signVerbose(null, "unsigned.jar", "none.jar", "signer")
|
||||||
.shouldContain("is not timestamped")
|
.shouldContain("is not timestamped")
|
||||||
|
.shouldContain("The signer certificate will expire on")
|
||||||
.shouldHaveExitValue(0);
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
verify("none.jar", "-verbose")
|
||||||
|
.shouldContain("do not include a timestamp")
|
||||||
|
.shouldContain("The signer certificate will expire on")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
// Error cases
|
||||||
|
|
||||||
signVerbose(null, "unsigned.jar", "badku.jar", "badku")
|
signVerbose(null, "unsigned.jar", "badku.jar", "badku")
|
||||||
|
.shouldContain("KeyUsage extension doesn't allow code signing")
|
||||||
.shouldHaveExitValue(8);
|
.shouldHaveExitValue(8);
|
||||||
checkBadKU("badku.jar");
|
checkBadKU("badku.jar");
|
||||||
|
|
||||||
// 8180289: unvalidated TSA cert chain
|
// 8180289: unvalidated TSA cert chain
|
||||||
sign("tsnoca")
|
sign("tsnoca")
|
||||||
.shouldContain("TSA certificate chain is invalid")
|
.shouldContain("The TSA certificate chain is invalid. "
|
||||||
|
+ "Reason: Path does not chain with any of the trust anchors")
|
||||||
.shouldHaveExitValue(64);
|
.shouldHaveExitValue(64);
|
||||||
|
|
||||||
verify("tsnoca.jar", "-verbose", "-certs")
|
verify("tsnoca.jar", "-verbose", "-certs")
|
||||||
.shouldHaveExitValue(64)
|
.shouldHaveExitValue(64)
|
||||||
.shouldContain("jar verified")
|
.shouldContain("jar verified")
|
||||||
.shouldContain("Invalid TSA certificate chain")
|
.shouldContain("Invalid TSA certificate chain: "
|
||||||
.shouldContain("TSA certificate chain is invalid");
|
+ "Path does not chain with any of the trust anchors")
|
||||||
|
.shouldContain("TSA certificate chain is invalid."
|
||||||
|
+ " Reason: Path does not chain with any of the trust anchors");
|
||||||
|
|
||||||
sign("nononce")
|
sign("nononce")
|
||||||
|
.shouldContain("Nonce missing in timestamp token")
|
||||||
.shouldHaveExitValue(1);
|
.shouldHaveExitValue(1);
|
||||||
sign("diffnonce")
|
sign("diffnonce")
|
||||||
|
.shouldContain("Nonce changed in timestamp token")
|
||||||
.shouldHaveExitValue(1);
|
.shouldHaveExitValue(1);
|
||||||
sign("baddigest")
|
sign("baddigest")
|
||||||
|
.shouldContain("Digest octets changed in timestamp token")
|
||||||
.shouldHaveExitValue(1);
|
.shouldHaveExitValue(1);
|
||||||
sign("diffalg")
|
sign("diffalg")
|
||||||
|
.shouldContain("Digest algorithm not")
|
||||||
.shouldHaveExitValue(1);
|
.shouldHaveExitValue(1);
|
||||||
|
|
||||||
sign("fullchain")
|
sign("fullchain")
|
||||||
.shouldHaveExitValue(0); // Success, 6543440 solved.
|
.shouldHaveExitValue(0); // Success, 6543440 solved.
|
||||||
|
|
||||||
sign("tsbad1")
|
sign("tsbad1")
|
||||||
|
.shouldContain("Certificate is not valid for timestamping")
|
||||||
.shouldHaveExitValue(1);
|
.shouldHaveExitValue(1);
|
||||||
sign("tsbad2")
|
sign("tsbad2")
|
||||||
|
.shouldContain("Certificate is not valid for timestamping")
|
||||||
.shouldHaveExitValue(1);
|
.shouldHaveExitValue(1);
|
||||||
sign("tsbad3")
|
sign("tsbad3")
|
||||||
|
.shouldContain("Certificate is not valid for timestamping")
|
||||||
.shouldHaveExitValue(1);
|
.shouldHaveExitValue(1);
|
||||||
sign("nocert")
|
sign("nocert")
|
||||||
|
.shouldContain("Certificate not included in timestamp token")
|
||||||
.shouldHaveExitValue(1);
|
.shouldHaveExitValue(1);
|
||||||
|
|
||||||
sign("policy", "-tsapolicyid", "1.2.3")
|
sign("policy", "-tsapolicyid", "1.2.3")
|
||||||
|
@ -378,6 +414,7 @@ public class TimestampCheck {
|
||||||
checkTimestamp("policy.jar", "1.2.3", "SHA-256");
|
checkTimestamp("policy.jar", "1.2.3", "SHA-256");
|
||||||
|
|
||||||
sign("diffpolicy", "-tsapolicyid", "1.2.3")
|
sign("diffpolicy", "-tsapolicyid", "1.2.3")
|
||||||
|
.shouldContain("TSAPolicyID changed in timestamp token")
|
||||||
.shouldHaveExitValue(1);
|
.shouldHaveExitValue(1);
|
||||||
|
|
||||||
sign("sha1alg", "-tsadigestalg", "SHA")
|
sign("sha1alg", "-tsadigestalg", "SHA")
|
||||||
|
@ -387,6 +424,7 @@ public class TimestampCheck {
|
||||||
sign("tsweak", "-digestalg", "MD5",
|
sign("tsweak", "-digestalg", "MD5",
|
||||||
"-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
|
"-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
|
||||||
.shouldHaveExitValue(68)
|
.shouldHaveExitValue(68)
|
||||||
|
.shouldContain("The timestamp is invalid. Without a valid timestamp")
|
||||||
.shouldMatch("MD5.*-digestalg.*risk")
|
.shouldMatch("MD5.*-digestalg.*risk")
|
||||||
.shouldMatch("MD5.*-tsadigestalg.*risk")
|
.shouldMatch("MD5.*-tsadigestalg.*risk")
|
||||||
.shouldMatch("MD5withRSA.*-sigalg.*risk");
|
.shouldMatch("MD5withRSA.*-sigalg.*risk");
|
||||||
|
@ -394,6 +432,7 @@ public class TimestampCheck {
|
||||||
|
|
||||||
signVerbose("tsweak", "unsigned.jar", "tsweak2.jar", "signer")
|
signVerbose("tsweak", "unsigned.jar", "tsweak2.jar", "signer")
|
||||||
.shouldHaveExitValue(64)
|
.shouldHaveExitValue(64)
|
||||||
|
.shouldContain("The timestamp is invalid. Without a valid timestamp")
|
||||||
.shouldContain("TSA certificate chain is invalid");
|
.shouldContain("TSA certificate chain is invalid");
|
||||||
|
|
||||||
// Weak timestamp is an error and jar treated unsigned
|
// Weak timestamp is an error and jar treated unsigned
|
||||||
|
@ -402,19 +441,26 @@ public class TimestampCheck {
|
||||||
.shouldContain("treated as unsigned")
|
.shouldContain("treated as unsigned")
|
||||||
.shouldMatch("Timestamp.*512.*weak");
|
.shouldMatch("Timestamp.*512.*weak");
|
||||||
|
|
||||||
|
// Algorithm used in signing is weak
|
||||||
signVerbose("normal", "unsigned.jar", "halfWeak.jar", "signer",
|
signVerbose("normal", "unsigned.jar", "halfWeak.jar", "signer",
|
||||||
"-digestalg", "MD5")
|
"-digestalg", "MD5")
|
||||||
|
.shouldContain("-digestalg option is considered a security risk")
|
||||||
.shouldHaveExitValue(4);
|
.shouldHaveExitValue(4);
|
||||||
checkHalfWeak("halfWeak.jar");
|
checkHalfWeak("halfWeak.jar");
|
||||||
|
|
||||||
// sign with DSA key
|
// sign with DSA key
|
||||||
signVerbose("normal", "unsigned.jar", "sign1.jar", "dsakey")
|
signVerbose("normal", "unsigned.jar", "sign1.jar", "dsakey")
|
||||||
.shouldHaveExitValue(0);
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
// sign with RSAkeysize < 1024
|
// sign with RSAkeysize < 1024
|
||||||
signVerbose("normal", "sign1.jar", "sign2.jar", "weakkeysize")
|
signVerbose("normal", "sign1.jar", "sign2.jar", "weakkeysize")
|
||||||
|
.shouldContain("Algorithm constraints check failed on keysize")
|
||||||
.shouldHaveExitValue(4);
|
.shouldHaveExitValue(4);
|
||||||
checkMultiple("sign2.jar");
|
checkMultiple("sign2.jar");
|
||||||
|
|
||||||
|
// 8191438: jarsigner should print when a timestamp will expire
|
||||||
|
checkExpiration();
|
||||||
|
|
||||||
// When .SF or .RSA is missing or invalid
|
// When .SF or .RSA is missing or invalid
|
||||||
checkMissingOrInvalidFiles("normal.jar");
|
checkMissingOrInvalidFiles("normal.jar");
|
||||||
|
|
||||||
|
@ -422,12 +468,118 @@ public class TimestampCheck {
|
||||||
checkInvalidTsaCertKeyUsage();
|
checkInvalidTsaCertKeyUsage();
|
||||||
}
|
}
|
||||||
} else { // Run as a standalone server
|
} else { // Run as a standalone server
|
||||||
System.out.println("Press Enter to quit server");
|
System.out.println("TSA started at " + host
|
||||||
|
+ ". Press Enter to quit server");
|
||||||
System.in.read();
|
System.in.read();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void checkExpiration() throws Exception {
|
||||||
|
|
||||||
|
// Warning when expired or expiring
|
||||||
|
signVerbose(null, "unsigned.jar", "expired.jar", "expired")
|
||||||
|
.shouldContain("signer certificate has expired")
|
||||||
|
.shouldHaveExitValue(4);
|
||||||
|
verify("expired.jar")
|
||||||
|
.shouldContain("signer certificate has expired")
|
||||||
|
.shouldHaveExitValue(4);
|
||||||
|
signVerbose(null, "unsigned.jar", "expiring.jar", "expiring")
|
||||||
|
.shouldContain("signer certificate will expire within")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
verify("expiring.jar")
|
||||||
|
.shouldContain("signer certificate will expire within")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
// Info for long
|
||||||
|
signVerbose(null, "unsigned.jar", "long.jar", "long")
|
||||||
|
.shouldNotContain("signer certificate has expired")
|
||||||
|
.shouldNotContain("signer certificate will expire within")
|
||||||
|
.shouldContain("signer certificate will expire on")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
verify("long.jar")
|
||||||
|
.shouldNotContain("signer certificate has expired")
|
||||||
|
.shouldNotContain("signer certificate will expire within")
|
||||||
|
.shouldNotContain("The signer certificate will expire")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
verify("long.jar", "-verbose")
|
||||||
|
.shouldContain("The signer certificate will expire")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
// Both expired
|
||||||
|
signVerbose("tsexpired", "unsigned.jar",
|
||||||
|
"tsexpired-expired.jar", "expired")
|
||||||
|
.shouldContain("The signer certificate has expired.")
|
||||||
|
.shouldContain("The timestamp has expired.")
|
||||||
|
.shouldHaveExitValue(4);
|
||||||
|
verify("tsexpired-expired.jar")
|
||||||
|
.shouldContain("signer certificate has expired")
|
||||||
|
.shouldContain("timestamp has expired.")
|
||||||
|
.shouldHaveExitValue(4);
|
||||||
|
|
||||||
|
// TS expired but signer still good
|
||||||
|
signVerbose("tsexpired", "unsigned.jar",
|
||||||
|
"tsexpired-long.jar", "long")
|
||||||
|
.shouldContain("The timestamp expired on")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
verify("tsexpired-long.jar")
|
||||||
|
.shouldMatch("timestamp expired on.*However, the JAR will be valid")
|
||||||
|
.shouldNotContain("Error")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
signVerbose("tsexpired", "unsigned.jar",
|
||||||
|
"tsexpired-ca.jar", "ca")
|
||||||
|
.shouldContain("The timestamp has expired.")
|
||||||
|
.shouldHaveExitValue(4);
|
||||||
|
verify("tsexpired-ca.jar")
|
||||||
|
.shouldNotContain("timestamp has expired")
|
||||||
|
.shouldNotContain("Error")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
// Warning when expiring
|
||||||
|
sign("tsexpiring")
|
||||||
|
.shouldContain("timestamp will expire within")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
verify("tsexpiring.jar")
|
||||||
|
.shouldContain("timestamp will expire within")
|
||||||
|
.shouldNotContain("still valid")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
signVerbose("tsexpiring", "unsigned.jar",
|
||||||
|
"tsexpiring-ca.jar", "ca")
|
||||||
|
.shouldContain("self-signed")
|
||||||
|
.stderrShouldNotMatch("The.*expir")
|
||||||
|
.shouldHaveExitValue(4); // self-signed
|
||||||
|
verify("tsexpiring-ca.jar")
|
||||||
|
.stderrShouldNotMatch("The.*expir")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
signVerbose("tsexpiringsoon", "unsigned.jar",
|
||||||
|
"tsexpiringsoon-long.jar", "long")
|
||||||
|
.shouldContain("The timestamp will expire")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
verify("tsexpiringsoon-long.jar")
|
||||||
|
.shouldMatch("timestamp will expire.*However, the JAR will be valid until")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
// Info for long
|
||||||
|
sign("tslong")
|
||||||
|
.shouldNotContain("timestamp has expired")
|
||||||
|
.shouldNotContain("timestamp will expire within")
|
||||||
|
.shouldContain("timestamp will expire on")
|
||||||
|
.shouldContain("signer certificate will expire on")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
verify("tslong.jar")
|
||||||
|
.shouldNotContain("timestamp has expired")
|
||||||
|
.shouldNotContain("timestamp will expire within")
|
||||||
|
.shouldNotContain("timestamp will expire on")
|
||||||
|
.shouldNotContain("signer certificate will expire on")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
verify("tslong.jar", "-verbose")
|
||||||
|
.shouldContain("timestamp will expire on")
|
||||||
|
.shouldContain("signer certificate will expire on")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
private static void checkInvalidTsaCertKeyUsage() throws Exception {
|
private static void checkInvalidTsaCertKeyUsage() throws Exception {
|
||||||
|
|
||||||
// Hack: Rewrite the TSA cert inside normal.jar into ts2.jar.
|
// Hack: Rewrite the TSA cert inside normal.jar into ts2.jar.
|
||||||
|
@ -680,6 +832,14 @@ public class TimestampCheck {
|
||||||
keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3");
|
keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3");
|
||||||
keytool("-alias tsnoca -genkeypair -dname CN=tsnoca");
|
keytool("-alias tsnoca -genkeypair -dname CN=tsnoca");
|
||||||
|
|
||||||
|
keytool("-alias expired -genkeypair -dname CN=expired");
|
||||||
|
keytool("-alias expiring -genkeypair -dname CN=expiring");
|
||||||
|
keytool("-alias long -genkeypair -dname CN=long");
|
||||||
|
keytool("-alias tsexpired -genkeypair -dname CN=tsexpired");
|
||||||
|
keytool("-alias tsexpiring -genkeypair -dname CN=tsexpiring");
|
||||||
|
keytool("-alias tsexpiringsoon -genkeypair -dname CN=tsexpiringsoon");
|
||||||
|
keytool("-alias tslong -genkeypair -dname CN=tslong");
|
||||||
|
|
||||||
// tsnoca's issuer will be removed from keystore later
|
// tsnoca's issuer will be removed from keystore later
|
||||||
keytool("-alias ca -genkeypair -ext bc -dname CN=CA");
|
keytool("-alias ca -genkeypair -ext bc -dname CN=CA");
|
||||||
gencert("tsnoca", "-ext eku:critical=ts");
|
gencert("tsnoca", "-ext eku:critical=ts");
|
||||||
|
@ -691,7 +851,15 @@ public class TimestampCheck {
|
||||||
gencert("dsakey");
|
gencert("dsakey");
|
||||||
gencert("weakkeysize");
|
gencert("weakkeysize");
|
||||||
gencert("badku", "-ext ku:critical=keyAgreement");
|
gencert("badku", "-ext ku:critical=keyAgreement");
|
||||||
gencert("ts", "-ext eku:critical=ts");
|
gencert("ts", "-ext eku:critical=ts -validity 500");
|
||||||
|
|
||||||
|
gencert("expired", "-validity 10 -startdate -12d");
|
||||||
|
gencert("expiring", "-validity 178");
|
||||||
|
gencert("long", "-validity 182");
|
||||||
|
gencert("tsexpired", "-ext eku:critical=ts -validity 10 -startdate -12d");
|
||||||
|
gencert("tsexpiring", "-ext eku:critical=ts -validity 364");
|
||||||
|
gencert("tsexpiringsoon", "-ext eku:critical=ts -validity 170"); // earlier than expiring
|
||||||
|
gencert("tslong", "-ext eku:critical=ts -validity 367");
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
|
@ -711,7 +879,7 @@ public class TimestampCheck {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 45");
|
gencert("tsold", "-ext eku:critical=ts -startdate -40d -validity 500");
|
||||||
|
|
||||||
gencert("tsweak", "-ext eku:critical=ts");
|
gencert("tsweak", "-ext eku:critical=ts");
|
||||||
gencert("tsbad1");
|
gencert("tsbad1");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -51,32 +51,12 @@ public class AliasNotInStoreTest extends Test {
|
||||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||||
|
|
||||||
// create first key pair for signing
|
// create first key pair for signing
|
||||||
keytool(
|
createAlias(FIRST_KEY_ALIAS);
|
||||||
"-genkey",
|
createAlias(SECOND_KEY_ALIAS);
|
||||||
"-alias", FIRST_KEY_ALIAS,
|
|
||||||
"-keyalg", KEY_ALG,
|
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
|
||||||
"-keystore", BOTH_KEYS_KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=First",
|
|
||||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
// create second key pair for signing
|
|
||||||
keytool(
|
|
||||||
"-genkey",
|
|
||||||
"-alias", SECOND_KEY_ALIAS,
|
|
||||||
"-keyalg", KEY_ALG,
|
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
|
||||||
"-keystore", BOTH_KEYS_KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=Second",
|
|
||||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
// sign jar with first key
|
// sign jar with first key
|
||||||
OutputAnalyzer analyzer = jarsigner(
|
OutputAnalyzer analyzer = jarsigner(
|
||||||
"-keystore", BOTH_KEYS_KEYSTORE,
|
"-keystore", KEYSTORE,
|
||||||
"-storepass", PASSWORD,
|
"-storepass", PASSWORD,
|
||||||
"-keypass", PASSWORD,
|
"-keypass", PASSWORD,
|
||||||
"-signedjar", SIGNED_JARFILE,
|
"-signedjar", SIGNED_JARFILE,
|
||||||
|
@ -93,7 +73,7 @@ public class AliasNotInStoreTest extends Test {
|
||||||
|
|
||||||
// sign jar with second key
|
// sign jar with second key
|
||||||
analyzer = jarsigner(
|
analyzer = jarsigner(
|
||||||
"-keystore", BOTH_KEYS_KEYSTORE,
|
"-keystore", KEYSTORE,
|
||||||
"-storepass", PASSWORD,
|
"-storepass", PASSWORD,
|
||||||
"-keypass", PASSWORD,
|
"-keypass", PASSWORD,
|
||||||
UPDATED_SIGNED_JARFILE,
|
UPDATED_SIGNED_JARFILE,
|
||||||
|
@ -104,7 +84,7 @@ public class AliasNotInStoreTest extends Test {
|
||||||
// create keystore that contains only first key
|
// create keystore that contains only first key
|
||||||
keytool(
|
keytool(
|
||||||
"-importkeystore",
|
"-importkeystore",
|
||||||
"-srckeystore", BOTH_KEYS_KEYSTORE,
|
"-srckeystore", KEYSTORE,
|
||||||
"-srcalias", FIRST_KEY_ALIAS,
|
"-srcalias", FIRST_KEY_ALIAS,
|
||||||
"-srcstorepass", PASSWORD,
|
"-srcstorepass", PASSWORD,
|
||||||
"-srckeypass", PASSWORD,
|
"-srckeypass", PASSWORD,
|
||||||
|
@ -113,7 +93,7 @@ public class AliasNotInStoreTest extends Test {
|
||||||
"-deststorepass", PASSWORD,
|
"-deststorepass", PASSWORD,
|
||||||
"-destkeypass", PASSWORD).shouldHaveExitValue(0);
|
"-destkeypass", PASSWORD).shouldHaveExitValue(0);
|
||||||
|
|
||||||
// verify jar with keystore that contains only first key in strict mode,
|
// verify jar with keystore that contains only first key,
|
||||||
// so there is signed entry (FirstClass.class) that is not signed
|
// so there is signed entry (FirstClass.class) that is not signed
|
||||||
// by any alias in the keystore
|
// by any alias in the keystore
|
||||||
analyzer = jarsigner(
|
analyzer = jarsigner(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -52,17 +52,14 @@ public class BadExtendedKeyUsageTest extends Test {
|
||||||
|
|
||||||
// create a certificate whose signer certificate's
|
// create a certificate whose signer certificate's
|
||||||
// ExtendedKeyUsage extension doesn't allow code signing
|
// ExtendedKeyUsage extension doesn't allow code signing
|
||||||
keytool(
|
// create key pair for jar signing
|
||||||
"-genkey",
|
createAlias(CA_KEY_ALIAS);
|
||||||
"-alias", KEY_ALIAS,
|
createAlias(KEY_ALIAS);
|
||||||
"-keyalg", KEY_ALG,
|
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
issueCert(
|
||||||
"-keystore", KEYSTORE,
|
KEY_ALIAS,
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=Test",
|
|
||||||
"-ext", "ExtendedkeyUsage=serverAuth",
|
"-ext", "ExtendedkeyUsage=serverAuth",
|
||||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
"-validity", Integer.toString(VALIDITY));
|
||||||
|
|
||||||
// sign jar
|
// sign jar
|
||||||
OutputAnalyzer analyzer = jarsigner(
|
OutputAnalyzer analyzer = jarsigner(
|
||||||
|
|
|
@ -53,17 +53,13 @@ public class BadKeyUsageTest extends Test {
|
||||||
|
|
||||||
// create a certificate whose signer certificate's KeyUsage extension
|
// create a certificate whose signer certificate's KeyUsage extension
|
||||||
// doesn't allow code signing
|
// doesn't allow code signing
|
||||||
keytool(
|
createAlias(CA_KEY_ALIAS);
|
||||||
"-genkey",
|
createAlias(KEY_ALIAS);
|
||||||
"-alias", KEY_ALIAS,
|
|
||||||
"-keyalg", KEY_ALG,
|
issueCert(
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
KEY_ALIAS,
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=Test",
|
|
||||||
"-ext", "KeyUsage=keyAgreement",
|
"-ext", "KeyUsage=keyAgreement",
|
||||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
"-validity", Integer.toString(VALIDITY));
|
||||||
|
|
||||||
// sign jar
|
// sign jar
|
||||||
OutputAnalyzer analyzer = jarsigner(
|
OutputAnalyzer analyzer = jarsigner(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -24,10 +24,6 @@
|
||||||
import jdk.testlibrary.OutputAnalyzer;
|
import jdk.testlibrary.OutputAnalyzer;
|
||||||
import jdk.test.lib.util.JarUtils;
|
import jdk.test.lib.util.JarUtils;
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @bug 8024302 8026037
|
* @bug 8024302 8026037
|
||||||
|
@ -38,25 +34,14 @@ import java.util.Base64;
|
||||||
*/
|
*/
|
||||||
public class BadNetscapeCertTypeTest extends Test {
|
public class BadNetscapeCertTypeTest extends Test {
|
||||||
|
|
||||||
private static final String NETSCAPE_KEYSTORE_BASE64 = TEST_SOURCES + FS
|
|
||||||
+ "bad_netscape_cert_type.jks.base64";
|
|
||||||
|
|
||||||
private static final String NETSCAPE_KEYSTORE
|
|
||||||
= "bad_netscape_cert_type.jks";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The test signs and verifies a jar that contains entries
|
* The test signs and verifies a jar that contains entries
|
||||||
* whose signer certificate's NetscapeCertType extension
|
* whose signer certificate's NetscapeCertType extension
|
||||||
* doesn't allow code signing (badNetscapeCertType).
|
* doesn't allow code signing (badNetscapeCertType).
|
||||||
* Warning message is expected.
|
* Warning message is expected.
|
||||||
* Run bad_netscape_cert_type.sh script to create bad_netscape_cert_type.jks
|
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) throws Throwable {
|
public static void main(String[] args) throws Throwable {
|
||||||
|
|
||||||
Files.write(Paths.get(NETSCAPE_KEYSTORE),
|
|
||||||
Base64.getMimeDecoder().decode(
|
|
||||||
Files.readAllBytes(Paths.get(NETSCAPE_KEYSTORE_BASE64))));
|
|
||||||
|
|
||||||
BadNetscapeCertTypeTest test = new BadNetscapeCertTypeTest();
|
BadNetscapeCertTypeTest test = new BadNetscapeCertTypeTest();
|
||||||
test.start();
|
test.start();
|
||||||
}
|
}
|
||||||
|
@ -66,10 +51,22 @@ public class BadNetscapeCertTypeTest extends Test {
|
||||||
Utils.createFiles(FIRST_FILE);
|
Utils.createFiles(FIRST_FILE);
|
||||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||||
|
|
||||||
|
// create a certificate whose signer certificate's
|
||||||
|
// NetscapeCertType extension doesn't allow code signing
|
||||||
|
// create key pair for jar signing
|
||||||
|
createAlias(CA_KEY_ALIAS);
|
||||||
|
createAlias(KEY_ALIAS);
|
||||||
|
|
||||||
|
issueCert(
|
||||||
|
KEY_ALIAS,
|
||||||
|
// NetscapeCertType [ SSL client ]
|
||||||
|
"-ext", "2.16.840.1.113730.1.1=03020780",
|
||||||
|
"-validity", Integer.toString(VALIDITY));
|
||||||
|
|
||||||
// sign jar
|
// sign jar
|
||||||
OutputAnalyzer analyzer = jarsigner(
|
OutputAnalyzer analyzer = jarsigner(
|
||||||
"-verbose",
|
"-verbose",
|
||||||
"-keystore", NETSCAPE_KEYSTORE,
|
"-keystore", KEYSTORE,
|
||||||
"-storepass", PASSWORD,
|
"-storepass", PASSWORD,
|
||||||
"-keypass", PASSWORD,
|
"-keypass", PASSWORD,
|
||||||
"-signedjar", SIGNED_JARFILE,
|
"-signedjar", SIGNED_JARFILE,
|
||||||
|
@ -82,7 +79,7 @@ public class BadNetscapeCertTypeTest extends Test {
|
||||||
analyzer = jarsigner(
|
analyzer = jarsigner(
|
||||||
"-verify",
|
"-verify",
|
||||||
"-verbose",
|
"-verbose",
|
||||||
"-keystore", NETSCAPE_KEYSTORE,
|
"-keystore", KEYSTORE,
|
||||||
"-storepass", PASSWORD,
|
"-storepass", PASSWORD,
|
||||||
"-keypass", PASSWORD,
|
"-keypass", PASSWORD,
|
||||||
SIGNED_JARFILE);
|
SIGNED_JARFILE);
|
||||||
|
@ -94,7 +91,7 @@ public class BadNetscapeCertTypeTest extends Test {
|
||||||
"-verify",
|
"-verify",
|
||||||
"-verbose",
|
"-verbose",
|
||||||
"-strict",
|
"-strict",
|
||||||
"-keystore", NETSCAPE_KEYSTORE,
|
"-keystore", KEYSTORE,
|
||||||
"-storepass", PASSWORD,
|
"-storepass", PASSWORD,
|
||||||
"-keypass", PASSWORD,
|
"-keypass", PASSWORD,
|
||||||
SIGNED_JARFILE);
|
SIGNED_JARFILE);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -21,118 +21,52 @@
|
||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import jdk.testlibrary.OutputAnalyzer;
|
import jdk.testlibrary.OutputAnalyzer;
|
||||||
import jdk.testlibrary.ProcessTools;
|
|
||||||
import jdk.test.lib.util.JarUtils;
|
import jdk.test.lib.util.JarUtils;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @bug 8024302 8026037
|
* @bug 8024302 8026037
|
||||||
* @summary Test for chainNotValidated warning
|
* @summary Test for chainNotValidated warning
|
||||||
* @library /lib/testlibrary /test/lib ../
|
* @library /lib/testlibrary /test/lib ../
|
||||||
* @build jdk.test.lib.util.JarUtils
|
* @build jdk.test.lib.util.JarUtils
|
||||||
* @run main ChainNotValidatedTest
|
* @run main ChainNotValidatedTest ca2yes
|
||||||
|
* @run main ChainNotValidatedTest ca2no
|
||||||
*/
|
*/
|
||||||
public class ChainNotValidatedTest extends Test {
|
public class ChainNotValidatedTest extends Test {
|
||||||
|
|
||||||
private static final String CHAIN = "chain";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The test signs and verifies a jar that contains entries
|
|
||||||
* whose cert chain can't be correctly validated (chainNotValidated).
|
|
||||||
* Warning message is expected.
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) throws Throwable {
|
public static void main(String[] args) throws Throwable {
|
||||||
ChainNotValidatedTest test = new ChainNotValidatedTest();
|
ChainNotValidatedTest test = new ChainNotValidatedTest();
|
||||||
test.start();
|
test.start(args[0].equals("ca2yes"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void start() throws Throwable {
|
private void start(boolean ca2yes) throws Throwable {
|
||||||
// create a jar file that contains one class file
|
// create a jar file that contains one class file
|
||||||
Utils.createFiles(FIRST_FILE);
|
Utils.createFiles(FIRST_FILE);
|
||||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||||
|
|
||||||
// create self-signed certificate whose BasicConstraints extension
|
// We have 2 @run. Need cleanup.
|
||||||
// is set to false, so the certificate may not be used
|
Files.deleteIfExists(Paths.get(KEYSTORE));
|
||||||
// as a parent certificate (certpath validation should fail)
|
|
||||||
keytool(
|
|
||||||
"-genkeypair",
|
|
||||||
"-alias", CA_KEY_ALIAS,
|
|
||||||
"-keyalg", KEY_ALG,
|
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=CA",
|
|
||||||
"-ext", "BasicConstraints:critical=ca:false",
|
|
||||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
// create a certificate that is signed by self-signed certificate
|
// Root CA is not checked at all. If the intermediate CA has
|
||||||
// despite of it may not be used as a parent certificate
|
// BasicConstraints extension set to true, it will be valid.
|
||||||
// (certpath validation should fail)
|
// Otherwise, chain validation will fail.
|
||||||
keytool(
|
createAlias(CA_KEY_ALIAS);
|
||||||
"-genkeypair",
|
createAlias(CA2_KEY_ALIAS);
|
||||||
"-alias", KEY_ALIAS,
|
issueCert(CA2_KEY_ALIAS,
|
||||||
"-keyalg", KEY_ALG,
|
"-ext",
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
"bc=ca:" + ca2yes);
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=Test",
|
|
||||||
"-ext", "BasicConstraints:critical=ca:false",
|
|
||||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
keytool(
|
createAlias(KEY_ALIAS);
|
||||||
"-certreq",
|
issueCert(KEY_ALIAS, "-alias", CA2_KEY_ALIAS);
|
||||||
"-alias", KEY_ALIAS,
|
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-file", CERT_REQUEST_FILENAME).shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
keytool(
|
// remove CA2 certificate so it's not trusted
|
||||||
"-gencert",
|
|
||||||
"-alias", CA_KEY_ALIAS,
|
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-infile", CERT_REQUEST_FILENAME,
|
|
||||||
"-validity", Integer.toString(VALIDITY),
|
|
||||||
"-outfile", CERT_FILENAME).shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
keytool(
|
|
||||||
"-importcert",
|
|
||||||
"-alias", KEY_ALIAS,
|
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-file", CERT_FILENAME).shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
ProcessBuilder pb = new ProcessBuilder(KEYTOOL,
|
|
||||||
"-export",
|
|
||||||
"-rfc",
|
|
||||||
"-alias", KEY_ALIAS,
|
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD);
|
|
||||||
pb.redirectOutput(ProcessBuilder.Redirect.appendTo(new File(CHAIN)));
|
|
||||||
ProcessTools.executeCommand(pb).shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
pb = new ProcessBuilder(KEYTOOL,
|
|
||||||
"-export",
|
|
||||||
"-rfc",
|
|
||||||
"-alias", CA_KEY_ALIAS,
|
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD);
|
|
||||||
pb.redirectOutput(ProcessBuilder.Redirect.appendTo(new File(CHAIN)));
|
|
||||||
ProcessTools.executeCommand(pb).shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
// remove CA certificate
|
|
||||||
keytool(
|
keytool(
|
||||||
"-delete",
|
"-delete",
|
||||||
"-alias", CA_KEY_ALIAS,
|
"-alias", CA2_KEY_ALIAS,
|
||||||
"-keystore", KEYSTORE,
|
"-keystore", KEYSTORE,
|
||||||
"-storepass", PASSWORD,
|
"-storepass", PASSWORD,
|
||||||
"-keypass", PASSWORD).shouldHaveExitValue(0);
|
"-keypass", PASSWORD).shouldHaveExitValue(0);
|
||||||
|
@ -142,12 +76,15 @@ public class ChainNotValidatedTest extends Test {
|
||||||
"-keystore", KEYSTORE,
|
"-keystore", KEYSTORE,
|
||||||
"-storepass", PASSWORD,
|
"-storepass", PASSWORD,
|
||||||
"-keypass", PASSWORD,
|
"-keypass", PASSWORD,
|
||||||
"-certchain", CHAIN,
|
|
||||||
"-signedjar", SIGNED_JARFILE,
|
"-signedjar", SIGNED_JARFILE,
|
||||||
UNSIGNED_JARFILE,
|
UNSIGNED_JARFILE,
|
||||||
KEY_ALIAS);
|
KEY_ALIAS);
|
||||||
|
|
||||||
checkSigning(analyzer, CHAIN_NOT_VALIDATED_SIGNING_WARNING);
|
if (ca2yes) {
|
||||||
|
checkSigning(analyzer, "!" + CHAIN_NOT_VALIDATED_SIGNING_WARNING);
|
||||||
|
} else {
|
||||||
|
checkSigning(analyzer, CHAIN_NOT_VALIDATED_SIGNING_WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
// verify signed jar
|
// verify signed jar
|
||||||
analyzer = jarsigner(
|
analyzer = jarsigner(
|
||||||
|
@ -156,10 +93,13 @@ public class ChainNotValidatedTest extends Test {
|
||||||
"-keystore", KEYSTORE,
|
"-keystore", KEYSTORE,
|
||||||
"-storepass", PASSWORD,
|
"-storepass", PASSWORD,
|
||||||
"-keypass", PASSWORD,
|
"-keypass", PASSWORD,
|
||||||
"-certchain", CHAIN,
|
|
||||||
SIGNED_JARFILE);
|
SIGNED_JARFILE);
|
||||||
|
|
||||||
checkVerifying(analyzer, 0, CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
|
if (ca2yes) {
|
||||||
|
checkVerifying(analyzer, 0, "!" + CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
|
||||||
|
} else {
|
||||||
|
checkVerifying(analyzer, 0, CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
// verify signed jar in strict mode
|
// verify signed jar in strict mode
|
||||||
analyzer = jarsigner(
|
analyzer = jarsigner(
|
||||||
|
@ -169,11 +109,15 @@ public class ChainNotValidatedTest extends Test {
|
||||||
"-keystore", KEYSTORE,
|
"-keystore", KEYSTORE,
|
||||||
"-storepass", PASSWORD,
|
"-storepass", PASSWORD,
|
||||||
"-keypass", PASSWORD,
|
"-keypass", PASSWORD,
|
||||||
"-certchain", CHAIN,
|
|
||||||
SIGNED_JARFILE);
|
SIGNED_JARFILE);
|
||||||
|
|
||||||
checkVerifying(analyzer, CHAIN_NOT_VALIDATED_EXIT_CODE,
|
if (ca2yes) {
|
||||||
CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
|
checkVerifying(analyzer, 0,
|
||||||
|
"!" + CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
|
||||||
|
} else {
|
||||||
|
checkVerifying(analyzer, CHAIN_NOT_VALIDATED_EXIT_CODE,
|
||||||
|
CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
System.out.println("Test passed");
|
System.out.println("Test passed");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -52,18 +52,13 @@ public class HasExpiredCertTest extends Test {
|
||||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||||
|
|
||||||
// create key pair for jar signing
|
// create key pair for jar signing
|
||||||
keytool(
|
createAlias(CA_KEY_ALIAS);
|
||||||
"-genkey",
|
createAlias(KEY_ALIAS);
|
||||||
"-alias", KEY_ALIAS,
|
|
||||||
"-keyalg", KEY_ALG,
|
issueCert(
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
KEY_ALIAS,
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=Test",
|
|
||||||
"-startdate", "-" + SHORT_VALIDITY * 2 + "d",
|
"-startdate", "-" + SHORT_VALIDITY * 2 + "d",
|
||||||
"-validity", Integer.toString(SHORT_VALIDITY))
|
"-validity", Integer.toString(SHORT_VALIDITY));
|
||||||
.shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
// sign jar
|
// sign jar
|
||||||
OutputAnalyzer analyzer = jarsigner(
|
OutputAnalyzer analyzer = jarsigner(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -52,17 +52,12 @@ public class HasExpiringCertTest extends Test {
|
||||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||||
|
|
||||||
// create key pair for jar signing
|
// create key pair for jar signing
|
||||||
keytool(
|
createAlias(CA_KEY_ALIAS);
|
||||||
"-genkey",
|
createAlias(KEY_ALIAS);
|
||||||
"-alias", KEY_ALIAS,
|
|
||||||
"-keyalg", KEY_ALG,
|
issueCert(
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
KEY_ALIAS,
|
||||||
"-keystore", KEYSTORE,
|
"-validity", Integer.toString(SHORT_VALIDITY));
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=Test",
|
|
||||||
"-validity", Integer.toString(SHORT_VALIDITY))
|
|
||||||
.shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
// sign jar
|
// sign jar
|
||||||
OutputAnalyzer analyzer = jarsigner(
|
OutputAnalyzer analyzer = jarsigner(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -51,16 +51,11 @@ public class HasUnsignedEntryTest extends Test {
|
||||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||||
|
|
||||||
// create key pair for signing
|
// create key pair for signing
|
||||||
keytool(
|
createAlias(CA_KEY_ALIAS);
|
||||||
"-genkey",
|
createAlias(KEY_ALIAS);
|
||||||
"-alias", KEY_ALIAS,
|
issueCert(
|
||||||
"-keyalg", KEY_ALG,
|
KEY_ALIAS,
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
"-validity", Integer.toString(VALIDITY));
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=Test",
|
|
||||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
// sign jar
|
// sign jar
|
||||||
OutputAnalyzer analyzer = jarsigner(
|
OutputAnalyzer analyzer = jarsigner(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -54,35 +54,25 @@ public class MultipleWarningsTest extends Test {
|
||||||
// create a jar file that contains one class file
|
// create a jar file that contains one class file
|
||||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||||
|
|
||||||
|
createAlias(CA_KEY_ALIAS);
|
||||||
|
|
||||||
// create first expired certificate
|
// create first expired certificate
|
||||||
// whose ExtendedKeyUsage extension does not allow code signing
|
// whose ExtendedKeyUsage extension does not allow code signing
|
||||||
keytool(
|
createAlias(FIRST_KEY_ALIAS);
|
||||||
"-genkey",
|
issueCert(
|
||||||
"-alias", FIRST_KEY_ALIAS,
|
FIRST_KEY_ALIAS,
|
||||||
"-keyalg", KEY_ALG,
|
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=First",
|
|
||||||
"-ext", "ExtendedkeyUsage=serverAuth",
|
"-ext", "ExtendedkeyUsage=serverAuth",
|
||||||
"-startdate", "-" + VALIDITY * 2 + "d",
|
"-startdate", "-" + VALIDITY * 2 + "d",
|
||||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
"-validity", Integer.toString(VALIDITY));
|
||||||
|
|
||||||
// create second expired certificate
|
// create second expired certificate
|
||||||
// whose KeyUsage extension does not allow code signing
|
// whose KeyUsage extension does not allow code signing
|
||||||
keytool(
|
createAlias(SECOND_KEY_ALIAS);
|
||||||
"-genkey",
|
issueCert(
|
||||||
"-alias", SECOND_KEY_ALIAS,
|
SECOND_KEY_ALIAS,
|
||||||
"-keyalg", KEY_ALG,
|
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=Second",
|
|
||||||
"-ext", "ExtendedkeyUsage=serverAuth",
|
"-ext", "ExtendedkeyUsage=serverAuth",
|
||||||
"-startdate", "-" + VALIDITY * 2 + "d",
|
"-startdate", "-" + VALIDITY * 2 + "d",
|
||||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
"-validity", Integer.toString(VALIDITY));
|
||||||
|
|
||||||
// sign jar with first key
|
// sign jar with first key
|
||||||
OutputAnalyzer analyzer = jarsigner(
|
OutputAnalyzer analyzer = jarsigner(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -57,15 +57,9 @@ public class NoTimestampTest extends Test {
|
||||||
* 24 * 60 * 60 * 1000L);
|
* 24 * 60 * 60 * 1000L);
|
||||||
|
|
||||||
// create key pair
|
// create key pair
|
||||||
keytool(
|
createAlias(CA_KEY_ALIAS);
|
||||||
"-genkey",
|
createAlias(KEY_ALIAS);
|
||||||
"-alias", KEY_ALIAS,
|
issueCert(KEY_ALIAS,
|
||||||
"-keyalg", KEY_ALG,
|
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=Test",
|
|
||||||
"-validity", Integer.toString(VALIDITY));
|
"-validity", Integer.toString(VALIDITY));
|
||||||
|
|
||||||
// sign jar file
|
// sign jar file
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -49,29 +49,19 @@ public class NotSignedByAliasTest extends Test {
|
||||||
Utils.createFiles(FIRST_FILE);
|
Utils.createFiles(FIRST_FILE);
|
||||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||||
|
|
||||||
// create first key pair for signing
|
createAlias(CA_KEY_ALIAS);
|
||||||
keytool(
|
|
||||||
"-genkey",
|
|
||||||
"-alias", FIRST_KEY_ALIAS,
|
|
||||||
"-keyalg", KEY_ALG,
|
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=First",
|
|
||||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
|
||||||
|
|
||||||
// create first key pair for signing
|
// create first key pair for signing
|
||||||
keytool(
|
createAlias(FIRST_KEY_ALIAS);
|
||||||
"-genkey",
|
issueCert(
|
||||||
"-alias", SECOND_KEY_ALIAS,
|
FIRST_KEY_ALIAS,
|
||||||
"-keyalg", KEY_ALG,
|
"-validity", Integer.toString(VALIDITY));
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
|
||||||
"-keystore", KEYSTORE,
|
// create first key pair for signing
|
||||||
"-storepass", PASSWORD,
|
createAlias(SECOND_KEY_ALIAS);
|
||||||
"-keypass", PASSWORD,
|
issueCert(
|
||||||
"-dname", "CN=Second",
|
SECOND_KEY_ALIAS,
|
||||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
"-validity", Integer.toString(VALIDITY));
|
||||||
|
|
||||||
// sign jar with first key
|
// sign jar with first key
|
||||||
OutputAnalyzer analyzer = jarsigner(
|
OutputAnalyzer analyzer = jarsigner(
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -50,15 +50,11 @@ public class NotYetValidCertTest extends Test {
|
||||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||||
|
|
||||||
// create certificate that will be valid only tomorrow
|
// create certificate that will be valid only tomorrow
|
||||||
keytool(
|
createAlias(CA_KEY_ALIAS);
|
||||||
"-genkey",
|
createAlias(KEY_ALIAS);
|
||||||
"-alias", KEY_ALIAS,
|
|
||||||
"-keyalg", KEY_ALG,
|
issueCert(
|
||||||
"-keysize", Integer.toString(KEY_SIZE),
|
KEY_ALIAS,
|
||||||
"-keystore", KEYSTORE,
|
|
||||||
"-storepass", PASSWORD,
|
|
||||||
"-keypass", PASSWORD,
|
|
||||||
"-dname", "CN=Test",
|
|
||||||
"-startdate", "+1d",
|
"-startdate", "+1d",
|
||||||
"-validity", Integer.toString(VALIDITY));
|
"-validity", Integer.toString(VALIDITY));
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -45,7 +45,6 @@ public abstract class Test {
|
||||||
static final String FIRST_FILE = "first.txt";
|
static final String FIRST_FILE = "first.txt";
|
||||||
static final String SECOND_FILE = "second.txt";
|
static final String SECOND_FILE = "second.txt";
|
||||||
static final String PASSWORD = "password";
|
static final String PASSWORD = "password";
|
||||||
static final String BOTH_KEYS_KEYSTORE = "both_keys.jks";
|
|
||||||
static final String FIRST_KEY_KEYSTORE = "first_key.jks";
|
static final String FIRST_KEY_KEYSTORE = "first_key.jks";
|
||||||
static final String KEYSTORE = "keystore.jks";
|
static final String KEYSTORE = "keystore.jks";
|
||||||
static final String FIRST_KEY_ALIAS = "first";
|
static final String FIRST_KEY_ALIAS = "first";
|
||||||
|
@ -55,11 +54,13 @@ public abstract class Test {
|
||||||
static final String CERT_REQUEST_FILENAME = "test.req";
|
static final String CERT_REQUEST_FILENAME = "test.req";
|
||||||
static final String CERT_FILENAME = "test.crt";
|
static final String CERT_FILENAME = "test.crt";
|
||||||
static final String CA_KEY_ALIAS = "ca";
|
static final String CA_KEY_ALIAS = "ca";
|
||||||
|
static final String CA2_KEY_ALIAS = "ca2";
|
||||||
static final int KEY_SIZE = 2048;
|
static final int KEY_SIZE = 2048;
|
||||||
static final int TIMEOUT = 6 * 60 * 1000; // in millis
|
static final int TIMEOUT = 6 * 60 * 1000; // in millis
|
||||||
static final int VALIDITY = 365;
|
static final int VALIDITY = 365;
|
||||||
|
|
||||||
static final String WARNING = "Warning:";
|
static final String WARNING = "Warning:";
|
||||||
|
static final String WARNING_OR_ERROR = "(Warning|Error):";
|
||||||
|
|
||||||
static final String CHAIN_NOT_VALIDATED_VERIFYING_WARNING
|
static final String CHAIN_NOT_VALIDATED_VERIFYING_WARNING
|
||||||
= "This jar contains entries "
|
= "This jar contains entries "
|
||||||
|
@ -154,14 +155,72 @@ public abstract class Test {
|
||||||
static final int ALIAS_NOT_IN_STORE_EXIT_CODE = 32;
|
static final int ALIAS_NOT_IN_STORE_EXIT_CODE = 32;
|
||||||
static final int NOT_SIGNED_BY_ALIAS_EXIT_CODE = 32;
|
static final int NOT_SIGNED_BY_ALIAS_EXIT_CODE = 32;
|
||||||
|
|
||||||
|
protected void createAlias(String alias, String ... options)
|
||||||
|
throws Throwable {
|
||||||
|
List<String> cmd = new ArrayList<>();
|
||||||
|
cmd.addAll(List.of(
|
||||||
|
"-genkeypair",
|
||||||
|
"-alias", alias,
|
||||||
|
"-keyalg", KEY_ALG,
|
||||||
|
"-keysize", Integer.toString(KEY_SIZE),
|
||||||
|
"-keystore", KEYSTORE,
|
||||||
|
"-storepass", PASSWORD,
|
||||||
|
"-keypass", PASSWORD,
|
||||||
|
"-dname", "CN=" + alias));
|
||||||
|
cmd.addAll(Arrays.asList(options));
|
||||||
|
|
||||||
|
keytool(cmd.toArray(new String[cmd.size()]))
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void issueCert(String alias, String ... options)
|
||||||
|
throws Throwable {
|
||||||
|
keytool("-certreq",
|
||||||
|
"-alias", alias,
|
||||||
|
"-keystore", KEYSTORE,
|
||||||
|
"-storepass", PASSWORD,
|
||||||
|
"-keypass", PASSWORD,
|
||||||
|
"-file", alias + ".req")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
List<String> cmd = new ArrayList<>();
|
||||||
|
cmd.addAll(List.of(
|
||||||
|
"-gencert",
|
||||||
|
"-alias", CA_KEY_ALIAS,
|
||||||
|
"-infile", alias + ".req",
|
||||||
|
"-outfile", alias + ".cert",
|
||||||
|
"-keystore", KEYSTORE,
|
||||||
|
"-storepass", PASSWORD,
|
||||||
|
"-keypass", PASSWORD,
|
||||||
|
"-file", alias + ".req"));
|
||||||
|
cmd.addAll(Arrays.asList(options));
|
||||||
|
|
||||||
|
keytool(cmd.toArray(new String[cmd.size()]))
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
|
||||||
|
keytool("-importcert",
|
||||||
|
"-alias", alias,
|
||||||
|
"-keystore", KEYSTORE,
|
||||||
|
"-storepass", PASSWORD,
|
||||||
|
"-keypass", PASSWORD,
|
||||||
|
"-file", alias + ".cert")
|
||||||
|
.shouldHaveExitValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
protected void checkVerifying(OutputAnalyzer analyzer, int expectedExitCode,
|
protected void checkVerifying(OutputAnalyzer analyzer, int expectedExitCode,
|
||||||
String... warnings) {
|
String... warnings) {
|
||||||
analyzer.shouldHaveExitValue(expectedExitCode);
|
analyzer.shouldHaveExitValue(expectedExitCode);
|
||||||
|
int count = 0;
|
||||||
for (String warning : warnings) {
|
for (String warning : warnings) {
|
||||||
analyzer.shouldContain(warning);
|
if (warning.startsWith("!")) {
|
||||||
|
analyzer.shouldNotContain(warning.substring(1));
|
||||||
|
} else {
|
||||||
|
count++;
|
||||||
|
analyzer.shouldContain(warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (warnings.length > 0) {
|
if (count > 0) {
|
||||||
analyzer.shouldContain(WARNING);
|
analyzer.shouldMatch(WARNING_OR_ERROR);
|
||||||
}
|
}
|
||||||
if (expectedExitCode == 0) {
|
if (expectedExitCode == 0) {
|
||||||
analyzer.shouldContain(JAR_VERIFIED);
|
analyzer.shouldContain(JAR_VERIFIED);
|
||||||
|
@ -172,11 +231,17 @@ public abstract class Test {
|
||||||
|
|
||||||
protected void checkSigning(OutputAnalyzer analyzer, String... warnings) {
|
protected void checkSigning(OutputAnalyzer analyzer, String... warnings) {
|
||||||
analyzer.shouldHaveExitValue(0);
|
analyzer.shouldHaveExitValue(0);
|
||||||
|
int count = 0;
|
||||||
for (String warning : warnings) {
|
for (String warning : warnings) {
|
||||||
analyzer.shouldContain(warning);
|
if (warning.startsWith("!")) {
|
||||||
|
analyzer.shouldNotContain(warning.substring(1));
|
||||||
|
} else {
|
||||||
|
count++;
|
||||||
|
analyzer.shouldContain(warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (warnings.length > 0) {
|
if (count > 0) {
|
||||||
analyzer.shouldContain(WARNING);
|
analyzer.shouldMatch(WARNING_OR_ERROR);
|
||||||
}
|
}
|
||||||
analyzer.shouldContain(JAR_SIGNED);
|
analyzer.shouldContain(JAR_SIGNED);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
/u3+7QAAAAIAAAABAAAAAQAFYWxpYXMAAAFBpkwW0gAAAr0wggK5MA4GCisGAQQB
|
|
||||||
KgIRAQEFAASCAqWkGJ3PPjYmWNKrV23Y1u413RMAkrRZ+1OLWYRcQt4jtxtIyEH5
|
|
||||||
Ho5b9dy9XN9FBKlTOD4c2Pc1T43BLKXeuLu3uLLeIxgXFt0z9CLyGwdYZZ751kXr
|
|
||||||
DQ99qY6aNQUO6SeE4Wdty0KPAqid6ZJ8bF7T6wsTZSvNhaBRzyFydEfG7bbUYjOl
|
|
||||||
mWC44nlsu6VEU3o9RQpcm1gIMwradOaIVT/HoB2bKmAv8gHqI6kreiEZwTdZkSAI
|
|
||||||
IRi2vt1RPllXt5hgjDxUfZe8XOYYweR4Vt2/jVuKLJ80DNTu/9SeUD88zQAz53k4
|
|
||||||
r3nRhv6TRcPm6tV/Fh92XLHiskL+TAzTfm+bUAudPCCVxN+yRtxvAgA+UhdV/SuM
|
|
||||||
Zn5F6nrmP+YJG1hmprgCJIJJaCEXa9RXYC+vIVpO0WVNRuGlGm+/1afnOuQC8Wss
|
|
||||||
ShXwjkaqTwAhqBFq7eYmmP8BK3gflYrt2zDLXvhl4ndVvMhMthFJ3ZvLh2LWpqLI
|
|
||||||
/n8EMCf8US3lIEFk9DTHBZjffiHkqK2e7+FXEpG3xrgE6ZYLMdbd5Pb3YjZfhQx+
|
|
||||||
ZTtiEFzYSaEGhacek/m7dRq1qmwgFsytng2OdWZe2ln8LJY0odr1dGUfJHfgafvi
|
|
||||||
tlfbkg/rgjONtwliChDggbkUwnerrj/D/zrdEufUvfyltSshhHXRNDD3fH6spmEk
|
|
||||||
hHKgxEc4yvxqJxzdMGtuib355aSfNegyl+GsnsKzXQCVEK2h3BLTQObzaD+8NZ12
|
|
||||||
LQHvbrCiaS34vxJ3rEC+a+SW7itZp0aCdXMWdMJNkRKqyLBD3vG3zN05sN3XrhEM
|
|
||||||
8BRT020TWY00tbVFbbBFheYLQRgTjrQtr0Yt6UHWBZc4N20crDLcSH5gqcCOVpla
|
|
||||||
1Y2uqFEn8yqrGRwn/kgfNgAAAAEABVguNTA5AAABtTCCAbEwggEaoAMCAQICCQDH
|
|
||||||
cEuVvzCuqzANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDDARUZXN0MB4XDTEzMTAx
|
|
||||||
MTA2NTUwNloXDTIzMTAwOTA2NTUwNlowDzENMAsGA1UEAwwEVGVzdDCBnzANBgkq
|
|
||||||
hkiG9w0BAQEFAAOBjQAwgYkCgYEA8hOfp2Dcnvt//ZZQAja9TRiwKqXVS+TiYE3S
|
|
||||||
gngCBjIi+YYdo0DsUeO5MBfE6uvCWOr5lwAR/u1iaJOhIoGJDiGoPasZlt+yIgtR
|
|
||||||
LzA7j2q+1q6kcwiVxfikI3aUgHV/QsybTriT4Bf7TQNKtJG23MQa4sD7+PjtCWD7
|
|
||||||
p3cHTfkCAwEAAaMVMBMwEQYJYIZIAYb4QgEBBAQDAgeAMA0GCSqGSIb3DQEBBQUA
|
|
||||||
A4GBAKoDlTJ8wLRA7G8XdGm4gv733n1cSQzlkcsjfOO6/mA5Jvu8tyFNq9HTf9AT
|
|
||||||
VXbrbGcUYJjhzSSY3w5apXK1kXyqTB1LUNEJ45WnmciqSSecVTpJz9TuegyoX0Zf
|
|
||||||
HScSgqfDmjqoiiFiNCgn3ZEJ85ykGvoFYGH+php+BVi3S0bj5E/jRpyV3vNnii/S
|
|
||||||
wJDSAXF6bYU=
|
|
|
@ -1,48 +0,0 @@
|
||||||
#
|
|
||||||
# Copyright (c) 2013, 2015, 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
|
|
||||||
# under the terms of the GNU General Public License version 2 only, as
|
|
||||||
# published by the Free Software Foundation.
|
|
||||||
#
|
|
||||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
# version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
# accompanied this code).
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License version
|
|
||||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
#
|
|
||||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
# or visit www.oracle.com if you need additional information or have any
|
|
||||||
# questions.
|
|
||||||
#
|
|
||||||
|
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# This script creates JKS keystore with a certificate
|
|
||||||
# that contains Netscape Certificate Type extension
|
|
||||||
# that does not allow code signing
|
|
||||||
# The keystore is used by BadNetscapeCertTypeTest.java test
|
|
||||||
|
|
||||||
rm -rf keystore.jks
|
|
||||||
echo "nsCertType = client" > ext.cfg
|
|
||||||
|
|
||||||
openssl req -new -out cert.req -keyout key.pem -days 3650 \
|
|
||||||
-passin pass:password -passout pass:password -subj "/CN=Test"
|
|
||||||
openssl x509 -in cert.req -out cert.pem -req -signkey key.pem -days 3650 \
|
|
||||||
-passin pass:password -extfile ext.cfg
|
|
||||||
openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 \
|
|
||||||
-passin pass:password -passout pass:password -name alias
|
|
||||||
|
|
||||||
${JAVA_HOME}/bin/keytool -importkeystore \
|
|
||||||
-srckeystore keystore.p12 -srcstoretype pkcs12 \
|
|
||||||
-srcstorepass password -alias alias \
|
|
||||||
-destkeystore bad_netscape_cert_type.jks -deststoretype jks \
|
|
||||||
-deststorepass password -destalias alias \
|
|
||||||
|
|
||||||
openssl base64 < bad_netscape_cert_type.jks > bad_netscape_cert_type.jks.base64
|
|
||||||
rm -rf cert.req key.pem cert.pem keystore.p12 ext.cfg bad_netscape_cert_type.jks
|
|
Loading…
Add table
Add a link
Reference in a new issue