8191438: jarsigner should print when a timestamp will expire
authorweijun
Wed, 14 Feb 2018 16:58:49 +0800
changeset 48893 454518b338b0
parent 48892 034839ee4f4b
child 48894 99b94636fcd3
child 48969 7eb296a8ce2c
child 56123 9794cd2de23a
8191438: jarsigner should print when a timestamp will expire Reviewed-by: mullan
src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java
src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java
test/jdk/sun/security/tools/jarsigner/TimestampCheck.java
test/jdk/sun/security/tools/jarsigner/warnings/AliasNotInStoreTest.java
test/jdk/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java
test/jdk/sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java
test/jdk/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java
test/jdk/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java
test/jdk/sun/security/tools/jarsigner/warnings/HasExpiredCertTest.java
test/jdk/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java
test/jdk/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java
test/jdk/sun/security/tools/jarsigner/warnings/MultipleWarningsTest.java
test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java
test/jdk/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java
test/jdk/sun/security/tools/jarsigner/warnings/NotYetValidCertTest.java
test/jdk/sun/security/tools/jarsigner/warnings/Test.java
test/jdk/sun/security/tools/jarsigner/warnings/bad_netscape_cert_type.jks.base64
test/jdk/sun/security/tools/jarsigner/warnings/bad_netscape_cert_type.sh
--- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Main.java	Wed Feb 14 16:58:49 2018 +0800
@@ -30,6 +30,7 @@
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.PKIXBuilderParameters;
 import java.util.*;
+import java.util.stream.Collectors;
 import java.util.zip.*;
 import java.util.jar.*;
 import java.net.URI;
@@ -92,6 +93,7 @@
     private static final String P11KEYSTORE = "PKCS11";
 
     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 =
             new DisabledAlgorithmConstraints(
@@ -102,6 +104,13 @@
     private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
             .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:
     // This is the entry that get launched by the security tool jarsigner.
     public static void main(String args[]) throws Exception {
@@ -109,13 +118,6 @@
         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)
     PrivateKey privateKey;          // private key
     KeyStore store;                 // the keystore specified by -keystore
@@ -160,8 +162,16 @@
 
     // Informational warnings
     private boolean hasExpiringCert = false;
-    private boolean noTimestamp = false;
-    private Date expireDate = new Date(0L);     // used in noTimestamp warning
+    private boolean hasExpiringTsaCert = false;
+    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.
 
@@ -174,6 +184,7 @@
 
     private int weakAlg = 0; // 1. digestalg, 2. sigalg, 4. tsadigestalg
     private boolean hasExpiredCert = false;
+    private boolean hasExpiredTsaCert = false;
     private boolean notYetValidCert = false;
     private boolean chainNotValidated = false;
     private boolean tsaChainNotValidated = false;
@@ -191,6 +202,7 @@
     private boolean seeWeak = false;
 
     PKIXBuilderParameters pkixParameters;
+    Set<X509Certificate> trustedCerts = new HashSet<>();
 
     public void run(String args[]) {
         try {
@@ -277,8 +289,8 @@
 
         if (strict) {
             int exitCode = 0;
-            if (weakAlg != 0 || chainNotValidated
-                    || hasExpiredCert || notYetValidCert || signerSelfSigned) {
+            if (weakAlg != 0 || chainNotValidated || hasExpiredCert
+                    || hasExpiredTsaCert || notYetValidCert || signerSelfSigned) {
                 exitCode |= 4;
             }
             if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType) {
@@ -879,14 +891,12 @@
             }
 
             // If signer is a trusted cert or private entry in user's own
-            // keystore, it can be self-signed.
-            if (!aliasNotInStore) {
+            // keystore, it can be self-signed. Please note aliasNotInStore
+            // is always false when ~/.keystore is used.
+            if (!aliasNotInStore && keystore != null) {
                 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
             // must be generated so seeWeak can be updated.
             if (!digestMap.isEmpty()
@@ -986,118 +996,7 @@
                     System.out.println(rb.getString("jar.is.unsigned"));
                 }
             } else {
-                boolean warningAppeared = 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."));
-                    }
-                }
+                displayMessagesAndResult(false);
             }
             return;
         } catch (Exception e) {
@@ -1114,6 +1013,230 @@
         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) {
         if (DISABLED_CHECK.permits(primitiveSet, alg, null)) {
             return alg;
@@ -1152,8 +1275,9 @@
      *
      * Note: no newline character at the end.
      *
-     * When isTsCert is true, this method sets global flags like hasExpiredCert,
-     * notYetValidCert, badKeyUsage, badExtendedKeyUsage, badNetscapeCertType.
+     * This method sets global flags like hasExpiringCert, hasExpiredCert,
+     * notYetValidCert, badKeyUsage, badExtendedKeyUsage, badNetscapeCertType,
+     * hasExpiringTsaCert, hasExpiredTsaCert.
      *
      * @param isTsCert true if c is in the TSA cert chain, false otherwise.
      * @param checkUsage true to check code signer keyUsage
@@ -1182,55 +1306,75 @@
         if (x509Cert != null) {
 
             certStr.append("\n").append(tab).append("[");
-            Date notAfter = x509Cert.getNotAfter();
-            try {
-                boolean printValidity = true;
-                if (timestamp == null) {
-                    if (expireDate.getTime() == 0 || expireDate.after(notAfter)) {
-                        expireDate = notAfter;
+
+            if (trustedCerts.contains(x509Cert)) {
+                certStr.append(rb.getString("trusted.certificate"));
+            } else {
+                Date notAfter = x509Cert.getNotAfter();
+                try {
+                    boolean printValidity = true;
+                    if (isTsCert) {
+                        if (tsaExpireDate == null || tsaExpireDate.after(notAfter)) {
+                            tsaExpireDate = notAfter;
+                        }
+                    } else {
+                        if (expireDate == null || expireDate.after(notAfter)) {
+                            expireDate = notAfter;
+                        }
                     }
-                    x509Cert.checkValidity();
-                    // test if cert will expire within six months
-                    if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) {
-                        if (!isTsCert) hasExpiringCert = true;
-                        if (expiringTimeForm == null) {
-                            expiringTimeForm = new MessageFormat(
-                                rb.getString("certificate.will.expire.on"));
+                    if (timestamp == null) {
+                        x509Cert.checkValidity();
+                        // test if cert will expire within six months (or one year for tsa)
+                        long age = isTsCert ? ONE_YEAR : SIX_MONTHS;
+                        if (notAfter.getTime() < System.currentTimeMillis() + age) {
+                            if (isTsCert) {
+                                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 = { notAfter };
-                        certStr.append(expiringTimeForm.format(source));
-                        printValidity = false;
+                        Object[] source = {x509Cert.getNotBefore(), notAfter};
+                        certStr.append(validityTimeForm.format(source));
+                    }
+                } catch (CertificateExpiredException cee) {
+                    if (isTsCert) {
+                        hasExpiredTsaCert = true;
+                    } else {
+                        hasExpiredCert = true;
                     }
-                } else {
-                    x509Cert.checkValidity(timestamp);
+
+                    if (expiredTimeForm == null) {
+                        expiredTimeForm = new MessageFormat(
+                                rb.getString("certificate.expired.on"));
+                    }
+                    Object[] source = {notAfter};
+                    certStr.append(expiredTimeForm.format(source));
+
+                } catch (CertificateNotYetValidException cnyve) {
+                    if (!isTsCert) notYetValidCert = true;
+
+                    if (notYetTimeForm == null) {
+                        notYetTimeForm = new MessageFormat(
+                                rb.getString("certificate.is.not.valid.until"));
+                    }
+                    Object[] source = {x509Cert.getNotBefore()};
+                    certStr.append(notYetTimeForm.format(source));
                 }
-                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) hasExpiredCert = true;
-
-                if (expiredTimeForm == null) {
-                    expiredTimeForm = new MessageFormat(
-                        rb.getString("certificate.expired.on"));
-                }
-                Object[] source = { notAfter };
-                certStr.append(expiredTimeForm.format(source));
-
-            } catch (CertificateNotYetValidException cnyve) {
-                if (!isTsCert) notYetValidCert = true;
-
-                if (notYetTimeForm == null) {
-                    notYetTimeForm = new MessageFormat(
-                        rb.getString("certificate.is.not.valid.until"));
-                }
-                Object[] source = { x509Cert.getNotBefore() };
-                certStr.append(notYetTimeForm.format(source));
             }
             certStr.append("]");
 
@@ -1446,8 +1590,6 @@
             if (tSAPolicyID != null) {
                 builder.setProperty("tsaPolicyId", tSAPolicyID);
             }
-        } else {
-            noTimestamp = true;
         }
 
         if (altSignerClass != null) {
@@ -1519,160 +1661,64 @@
             error(failedMessage, failedCause);
         }
 
+        if (verbose != null) {
+            System.out.println();
+        }
+
         // The JarSigner API always accepts the timestamp received.
         // We need to extract the certs from the signed jar to
         // validate it.
-        if (!noTimestamp) {
-            try (JarFile check = new JarFile(signedJarFile)) {
-                PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry(
-                        "META-INF/" + sigfile + "." + privateKey.getAlgorithm())));
+        try (JarFile check = new JarFile(signedJarFile)) {
+            PKCS7 p7 = new PKCS7(check.getInputStream(check.getEntry(
+                    "META-INF/" + sigfile + "." + privateKey.getAlgorithm())));
+            Timestamp ts = null;
+            try {
                 SignerInfo si = p7.getSignerInfos()[0];
-                PKCS7 tsToken = si.getTsToken();
-                SignerInfo tsSi = tsToken.getSignerInfos()[0];
-                try {
-                    validateCertChain(Validator.VAR_TSA_SERVER,
-                            tsSi.getCertificateChain(tsToken), null);
-                } catch (Exception e) {
-                    tsaChainNotValidated = true;
-                    tsaChainNotValidatedReason = e;
+                if (si.getTsToken() != null) {
+                    hasTimestampBlock = true;
                 }
+                ts = si.getTimestamp();
             } catch (Exception e) {
-                if (debug) {
-                    e.printStackTrace();
+                tsaChainNotValidated = true;
+                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
-        // 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);
-        // }
+        displayMessagesAndResult(true);
     }
 
     /**
@@ -1691,31 +1737,57 @@
     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 {
         if (cacheForSignerInfo.containsKey(signer)) {
             return cacheForSignerInfo.get(signer);
         }
-        StringBuilder sb = new StringBuilder();
         List<? extends Certificate> certs = signer.getSignerCertPath().getCertificates();
-        // display the signature timestamp, if present
-        Date timestamp;
+        // signing time is only displayed on verification
         Timestamp ts = signer.getTimestamp();
+        String tsLine = "";
         if (ts != null) {
-            sb.append(printTimestamp(tab, ts));
-            sb.append('\n');
+            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) {
             timestamp = ts.getTimestamp();
+            noTimestamp = false;
         } else {
             timestamp = null;
-            noTimestamp = true;
         }
         // display the certificate(sb). The first one is end-entity cert and
         // its KeyUsage should be checked.
         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) {
-            sb.append(printCert(false, tab, c, timestamp, first));
+            sb.append(printCert(false, tab2, c, timestamp, first));
             sb.append('\n');
             first = false;
         }
@@ -1724,13 +1796,13 @@
         } catch (Exception e) {
             chainNotValidated = true;
             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");
         }
         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()) {
-                sb.append(printCert(true, tab, c, timestamp, false));
+                sb.append(printCert(true, tab2, c, null, false));
                 sb.append('\n');
             }
             try {
@@ -1739,7 +1811,7 @@
             } catch (Exception e) {
                 tsaChainNotValidated = true;
                 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");
             }
         }
@@ -1747,9 +1819,8 @@
                 && KeyStoreUtil.isSelfSigned((X509Certificate)certs.get(0))) {
             signerSelfSigned = true;
         }
-        String result = sb.toString();
-        cacheForSignerInfo.put(signer, result);
-        return result;
+
+        return sb.toString();
     }
 
     void loadKeyStore(String keyStoreName, boolean prompt) {
@@ -1760,7 +1831,6 @@
         }
 
         try {
-            Set<TrustAnchor> tas = new HashSet<>();
             try {
                 KeyStore caks = KeyStoreUtil.getCacertsKeyStore();
                 if (caks != null) {
@@ -1768,7 +1838,7 @@
                     while (aliases.hasMoreElements()) {
                         String a = aliases.nextElement();
                         try {
-                            tas.add(new TrustAnchor((X509Certificate)caks.getCertificate(a), null));
+                            trustedCerts.add((X509Certificate)caks.getCertificate(a));
                         } catch (Exception e2) {
                             // ignore, when a SecretkeyEntry does not include a cert
                         }
@@ -1827,7 +1897,7 @@
                         // PrivateKeyEntry
                         if (store.isCertificateEntry(a) ||
                                 c.getSubjectDN().equals(c.getIssuerDN())) {
-                            tas.add(new TrustAnchor(c, null));
+                            trustedCerts.add(c);
                         }
                     } catch (Exception e2) {
                         // ignore, when a SecretkeyEntry does not include a cert
@@ -1835,7 +1905,11 @@
                 }
             } finally {
                 try {
-                    pkixParameters = new PKIXBuilderParameters(tas, null);
+                    pkixParameters = new PKIXBuilderParameters(
+                            trustedCerts.stream()
+                                    .map(c -> new TrustAnchor(c, null))
+                                    .collect(Collectors.toSet()),
+                            null);
                     pkixParameters.setRevocationEnabled(false);
                 } catch (InvalidAlgorithmParameterException ex) {
                     // Only if tas is empty
@@ -1951,6 +2025,7 @@
         }
     }
 
+    // Called by signJar().
     void getAliasInfo(String alias) throws Exception {
 
         Key key = null;
@@ -1995,22 +2070,6 @@
                 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 {
                 if (!token && keypass == null)
                     key = store.getKey(alias, storepass);
@@ -2066,7 +2125,7 @@
      * @param parameter this might be a timestamp
      */
     void validateCertChain(String variant, List<? extends Certificate> certs,
-                           Object parameter)
+                           Timestamp parameter)
             throws Exception {
         try {
             Validator.getInstance(Validator.TYPE_PKIX,
@@ -2080,8 +2139,22 @@
             }
 
             // Exception might be dismissed if another warning flag
-            // is already set by printCert. This is only done for
-            // code signing certs.
+            // is already set by printCert.
+
+            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) &&
                     e instanceof ValidatorException) {
--- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/Resources.java	Wed Feb 14 16:58:49 2018 +0800
@@ -229,6 +229,7 @@
         {"Error.", "Error: "},
         {"...Signer", ">>> Signer"},
         {"...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.entries.whose.signer.certificate.has.expired.",
@@ -245,8 +246,16 @@
                 "Re-run with the -verbose and -certs options for more details."},
         {"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.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.s.KeyUsage.extension.doesn.t.allow.code.signing.",
@@ -279,10 +288,18 @@
                 "This jar contains entries whose TSA certificate chain is invalid. Reason: %s"},
         {"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)."},
+        {"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",
                 "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",
                 "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: "},
         {"Cannot.find.environment.variable.",
                 "Cannot find environment variable: "},
--- a/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/TimestampCheck.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -79,6 +79,7 @@
  *        jdk.test.lib.JDKToolLauncher
  *        jdk.test.lib.Platform
  *        jdk.test.lib.process.*
+ * @compile -XDignore.symbol.file TimestampCheck.java
  * @run main/timeout=600 TimestampCheck
  */
 public class TimestampCheck {
@@ -126,12 +127,12 @@
         byte[] sign(byte[] input, String path) throws Exception {
 
             DerValue value = new DerValue(input);
-            System.out.println("\nIncoming Request\n===================");
-            System.out.println("Version: " + value.data.getInteger());
+            System.out.println("#\n# Incoming Request\n===================");
+            System.out.println("# Version: " + value.data.getInteger());
             DerValue messageImprint = value.data.getDerValue();
             AlgorithmId aid = AlgorithmId.parse(
                     messageImprint.data.getDerValue());
-            System.out.println("AlgorithmId: " + aid);
+            System.out.println("# AlgorithmId: " + aid);
 
             ObjectIdentifier policyId = new ObjectIdentifier(defaultPolicyId);
             BigInteger nonce = null;
@@ -139,16 +140,16 @@
                 DerValue v = value.data.getDerValue();
                 if (v.tag == DerValue.tag_Integer) {
                     nonce = v.getBigInteger();
-                    System.out.println("nonce: " + nonce);
+                    System.out.println("# nonce: " + nonce);
                 } 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) {
                     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(
                     new File(keystore), "changeit".toCharArray());
 
@@ -232,10 +233,10 @@
                     "1.2.840.113549.1.9.16.1.4"),
                     new DerValue(tstInfo2.toByteArray()));
 
-            System.out.println("Signing...");
-            System.out.println(new X500Name(signer
+            System.out.println("# Signing...");
+            System.out.println("# " + new X500Name(signer
                     .getIssuerX500Principal().getName()));
-            System.out.println(signer.getSerialNumber());
+            System.out.println("# " + signer.getSerialNumber());
 
             SignerInfo signerInfo = new SignerInfo(
                     new X500Name(signer.getIssuerX500Principal().getName()),
@@ -306,8 +307,6 @@
 
     public static void main(String[] args) throws Throwable {
 
-        prepare();
-
         try (Handler tsa = Handler.init(0, "ks");) {
             tsa.start();
             int port = tsa.getPort();
@@ -315,62 +314,99 @@
 
             if (args.length == 0) {         // Run this test
 
+                prepare();
+
                 sign("normal")
                         .shouldNotContain("Warning")
+                        .shouldContain("The signer certificate will expire on")
+                        .shouldContain("The timestamp will expire on")
                         .shouldHaveExitValue(0);
 
                 verify("normal.jar")
                         .shouldNotContain("Warning")
                         .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:
                 // 1. tsold will create a timestamp of 20 days ago.
                 // 2. oldsigner expired 10 days ago.
-                // jarsigner will show a warning at signing.
                 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.
                 verify("tsold.jar", "-verbose", "-certs")
                         .shouldNotContain("Warning")
+                        .shouldMatch("signer certificate expired on .*. "
+                                + "However, the JAR will be valid")
                         .shouldHaveExitValue(0);
 
+                // No timestamp
                 signVerbose(null, "unsigned.jar", "none.jar", "signer")
                         .shouldContain("is not timestamped")
+                        .shouldContain("The signer certificate will expire on")
                         .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")
+                        .shouldContain("KeyUsage extension doesn't allow code signing")
                         .shouldHaveExitValue(8);
                 checkBadKU("badku.jar");
 
                 // 8180289: unvalidated TSA cert chain
                 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);
 
                 verify("tsnoca.jar", "-verbose", "-certs")
                         .shouldHaveExitValue(64)
                         .shouldContain("jar verified")
-                        .shouldContain("Invalid TSA certificate chain")
-                        .shouldContain("TSA certificate chain is invalid");
+                        .shouldContain("Invalid TSA certificate chain: "
+                                + "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")
+                        .shouldContain("Nonce missing in timestamp token")
                         .shouldHaveExitValue(1);
                 sign("diffnonce")
+                        .shouldContain("Nonce changed in timestamp token")
                         .shouldHaveExitValue(1);
                 sign("baddigest")
+                        .shouldContain("Digest octets changed in timestamp token")
                         .shouldHaveExitValue(1);
                 sign("diffalg")
+                        .shouldContain("Digest algorithm not")
                         .shouldHaveExitValue(1);
+
                 sign("fullchain")
                         .shouldHaveExitValue(0);   // Success, 6543440 solved.
+
                 sign("tsbad1")
+                        .shouldContain("Certificate is not valid for timestamping")
                         .shouldHaveExitValue(1);
                 sign("tsbad2")
+                        .shouldContain("Certificate is not valid for timestamping")
                         .shouldHaveExitValue(1);
                 sign("tsbad3")
+                        .shouldContain("Certificate is not valid for timestamping")
                         .shouldHaveExitValue(1);
                 sign("nocert")
+                        .shouldContain("Certificate not included in timestamp token")
                         .shouldHaveExitValue(1);
 
                 sign("policy", "-tsapolicyid",  "1.2.3")
@@ -378,6 +414,7 @@
                 checkTimestamp("policy.jar", "1.2.3", "SHA-256");
 
                 sign("diffpolicy", "-tsapolicyid", "1.2.3")
+                        .shouldContain("TSAPolicyID changed in timestamp token")
                         .shouldHaveExitValue(1);
 
                 sign("sha1alg", "-tsadigestalg", "SHA")
@@ -387,6 +424,7 @@
                 sign("tsweak", "-digestalg", "MD5",
                                 "-sigalg", "MD5withRSA", "-tsadigestalg", "MD5")
                         .shouldHaveExitValue(68)
+                        .shouldContain("The timestamp is invalid. Without a valid timestamp")
                         .shouldMatch("MD5.*-digestalg.*risk")
                         .shouldMatch("MD5.*-tsadigestalg.*risk")
                         .shouldMatch("MD5withRSA.*-sigalg.*risk");
@@ -394,6 +432,7 @@
 
                 signVerbose("tsweak", "unsigned.jar", "tsweak2.jar", "signer")
                         .shouldHaveExitValue(64)
+                        .shouldContain("The timestamp is invalid. Without a valid timestamp")
                         .shouldContain("TSA certificate chain is invalid");
 
                 // Weak timestamp is an error and jar treated unsigned
@@ -402,19 +441,26 @@
                         .shouldContain("treated as unsigned")
                         .shouldMatch("Timestamp.*512.*weak");
 
+                // Algorithm used in signing is weak
                 signVerbose("normal", "unsigned.jar", "halfWeak.jar", "signer",
                         "-digestalg", "MD5")
+                        .shouldContain("-digestalg option is considered a security risk")
                         .shouldHaveExitValue(4);
                 checkHalfWeak("halfWeak.jar");
 
                 // sign with DSA key
                 signVerbose("normal", "unsigned.jar", "sign1.jar", "dsakey")
                         .shouldHaveExitValue(0);
+
                 // sign with RSAkeysize < 1024
                 signVerbose("normal", "sign1.jar", "sign2.jar", "weakkeysize")
+                        .shouldContain("Algorithm constraints check failed on keysize")
                         .shouldHaveExitValue(4);
                 checkMultiple("sign2.jar");
 
+                // 8191438: jarsigner should print when a timestamp will expire
+                checkExpiration();
+
                 // When .SF or .RSA is missing or invalid
                 checkMissingOrInvalidFiles("normal.jar");
 
@@ -422,12 +468,118 @@
                     checkInvalidTsaCertKeyUsage();
                 }
             } 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();
             }
         }
     }
 
+    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 {
 
         // Hack: Rewrite the TSA cert inside normal.jar into ts2.jar.
@@ -680,6 +832,14 @@
         keytool("-alias tsbad3 -genkeypair -dname CN=tsbad3");
         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
         keytool("-alias ca -genkeypair -ext bc -dname CN=CA");
         gencert("tsnoca", "-ext eku:critical=ts");
@@ -691,7 +851,15 @@
         gencert("dsakey");
         gencert("weakkeysize");
         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++) {
@@ -711,7 +879,7 @@
             }
         }
 
-        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("tsbad1");
--- a/test/jdk/sun/security/tools/jarsigner/warnings/AliasNotInStoreTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/AliasNotInStoreTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,32 +51,12 @@
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
         // create first key pair for signing
-        keytool(
-                "-genkey",
-                "-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);
+        createAlias(FIRST_KEY_ALIAS);
+        createAlias(SECOND_KEY_ALIAS);
 
         // sign jar with first key
         OutputAnalyzer analyzer = jarsigner(
-                "-keystore", BOTH_KEYS_KEYSTORE,
+                "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD,
                 "-signedjar", SIGNED_JARFILE,
@@ -93,7 +73,7 @@
 
         // sign jar with second key
         analyzer = jarsigner(
-                "-keystore", BOTH_KEYS_KEYSTORE,
+                "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD,
                 UPDATED_SIGNED_JARFILE,
@@ -104,7 +84,7 @@
         // create keystore that contains only first key
         keytool(
                 "-importkeystore",
-                "-srckeystore", BOTH_KEYS_KEYSTORE,
+                "-srckeystore", KEYSTORE,
                 "-srcalias", FIRST_KEY_ALIAS,
                 "-srcstorepass", PASSWORD,
                 "-srckeypass", PASSWORD,
@@ -113,7 +93,7 @@
                 "-deststorepass", PASSWORD,
                 "-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
         // by any alias in the keystore
         analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,17 +52,14 @@
 
         // create a certificate whose signer certificate's
         // ExtendedKeyUsage extension doesn't allow code signing
-        keytool(
-                "-genkey",
-                "-alias", KEY_ALIAS,
-                "-keyalg", KEY_ALG,
-                "-keysize", Integer.toString(KEY_SIZE),
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-dname", "CN=Test",
+        // create key pair for jar signing
+        createAlias(CA_KEY_ALIAS);
+        createAlias(KEY_ALIAS);
+
+        issueCert(
+                KEY_ALIAS,
                 "-ext", "ExtendedkeyUsage=serverAuth",
-                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+                "-validity", Integer.toString(VALIDITY));
 
         // sign jar
         OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -53,17 +53,13 @@
 
         // create a certificate whose signer certificate's KeyUsage extension
         // doesn't allow code signing
-        keytool(
-                "-genkey",
-                "-alias", KEY_ALIAS,
-                "-keyalg", KEY_ALG,
-                "-keysize", Integer.toString(KEY_SIZE),
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-dname", "CN=Test",
+        createAlias(CA_KEY_ALIAS);
+        createAlias(KEY_ALIAS);
+
+        issueCert(
+                KEY_ALIAS,
                 "-ext", "KeyUsage=keyAgreement",
-                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+                "-validity", Integer.toString(VALIDITY));
 
         // sign jar
         OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,6 @@
 import jdk.testlibrary.OutputAnalyzer;
 import jdk.test.lib.util.JarUtils;
 
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.Base64;
-
 /**
  * @test
  * @bug 8024302 8026037
@@ -38,25 +34,14 @@
  */
 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
      * whose signer certificate's NetscapeCertType extension
      * doesn't allow code signing (badNetscapeCertType).
      * 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 {
 
-        Files.write(Paths.get(NETSCAPE_KEYSTORE),
-                Base64.getMimeDecoder().decode(
-                    Files.readAllBytes(Paths.get(NETSCAPE_KEYSTORE_BASE64))));
-
         BadNetscapeCertTypeTest test = new BadNetscapeCertTypeTest();
         test.start();
     }
@@ -66,10 +51,22 @@
         Utils.createFiles(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
         OutputAnalyzer analyzer = jarsigner(
                 "-verbose",
-                "-keystore", NETSCAPE_KEYSTORE,
+                "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD,
                 "-signedjar", SIGNED_JARFILE,
@@ -82,7 +79,7 @@
         analyzer = jarsigner(
                 "-verify",
                 "-verbose",
-                "-keystore", NETSCAPE_KEYSTORE,
+                "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD,
                 SIGNED_JARFILE);
@@ -94,7 +91,7 @@
                 "-verify",
                 "-verbose",
                 "-strict",
-                "-keystore", NETSCAPE_KEYSTORE,
+                "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD,
                 SIGNED_JARFILE);
--- a/test/jdk/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -21,118 +21,52 @@
  * questions.
  */
 
-import java.io.File;
 import jdk.testlibrary.OutputAnalyzer;
-import jdk.testlibrary.ProcessTools;
 import jdk.test.lib.util.JarUtils;
 
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
 /**
  * @test
  * @bug 8024302 8026037
  * @summary Test for chainNotValidated warning
  * @library /lib/testlibrary /test/lib ../
  * @build jdk.test.lib.util.JarUtils
- * @run main ChainNotValidatedTest
+ * @run main ChainNotValidatedTest ca2yes
+ * @run main ChainNotValidatedTest ca2no
  */
 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 {
         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
         Utils.createFiles(FIRST_FILE);
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
-        // create self-signed certificate whose BasicConstraints extension
-        // is set to false, so the certificate may not be used
-        // 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
-        // despite of it may not be used as a parent certificate
-        // (certpath validation should fail)
-        keytool(
-                "-genkeypair",
-                "-alias", KEY_ALIAS,
-                "-keyalg", KEY_ALG,
-                "-keysize", Integer.toString(KEY_SIZE),
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-dname", "CN=Test",
-                "-ext", "BasicConstraints:critical=ca:false",
-                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
-
-        keytool(
-                "-certreq",
-                "-alias", KEY_ALIAS,
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-file", CERT_REQUEST_FILENAME).shouldHaveExitValue(0);
+        // We have 2 @run. Need cleanup.
+        Files.deleteIfExists(Paths.get(KEYSTORE));
 
-        keytool(
-                "-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);
+        // Root CA is not checked at all. If the intermediate CA has
+        // BasicConstraints extension set to true, it will be valid.
+        // Otherwise, chain validation will fail.
+        createAlias(CA_KEY_ALIAS);
+        createAlias(CA2_KEY_ALIAS);
+        issueCert(CA2_KEY_ALIAS,
+                "-ext",
+                "bc=ca:" + ca2yes);
 
-        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);
+        createAlias(KEY_ALIAS);
+        issueCert(KEY_ALIAS, "-alias", CA2_KEY_ALIAS);
 
-        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
+        // remove CA2 certificate so it's not trusted
         keytool(
                 "-delete",
-                "-alias", CA_KEY_ALIAS,
+                "-alias", CA2_KEY_ALIAS,
                 "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD).shouldHaveExitValue(0);
@@ -142,12 +76,15 @@
                 "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD,
-                "-certchain", CHAIN,
                 "-signedjar", SIGNED_JARFILE,
                 UNSIGNED_JARFILE,
                 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
         analyzer = jarsigner(
@@ -156,10 +93,13 @@
                 "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD,
-                "-certchain", CHAIN,
                 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
         analyzer = jarsigner(
@@ -169,11 +109,15 @@
                 "-keystore", KEYSTORE,
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD,
-                "-certchain", CHAIN,
                 SIGNED_JARFILE);
 
-        checkVerifying(analyzer, CHAIN_NOT_VALIDATED_EXIT_CODE,
-                CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
+        if (ca2yes) {
+            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");
     }
--- a/test/jdk/sun/security/tools/jarsigner/warnings/HasExpiredCertTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/HasExpiredCertTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,18 +52,13 @@
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
         // create key pair for jar signing
-        keytool(
-                "-genkey",
-                "-alias", KEY_ALIAS,
-                "-keyalg", KEY_ALG,
-                "-keysize", Integer.toString(KEY_SIZE),
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-dname", "CN=Test",
+        createAlias(CA_KEY_ALIAS);
+        createAlias(KEY_ALIAS);
+
+        issueCert(
+                KEY_ALIAS,
                 "-startdate", "-" + SHORT_VALIDITY * 2 + "d",
-                "-validity", Integer.toString(SHORT_VALIDITY))
-                .shouldHaveExitValue(0);
+                "-validity", Integer.toString(SHORT_VALIDITY));
 
         // sign jar
         OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,17 +52,12 @@
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
         // create key pair for jar signing
-        keytool(
-                "-genkey",
-                "-alias", KEY_ALIAS,
-                "-keyalg", KEY_ALG,
-                "-keysize", Integer.toString(KEY_SIZE),
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-dname", "CN=Test",
-                "-validity", Integer.toString(SHORT_VALIDITY))
-                .shouldHaveExitValue(0);
+        createAlias(CA_KEY_ALIAS);
+        createAlias(KEY_ALIAS);
+
+        issueCert(
+                KEY_ALIAS,
+                "-validity", Integer.toString(SHORT_VALIDITY));
 
         // sign jar
         OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,16 +51,11 @@
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
         // create key pair for signing
-        keytool(
-                "-genkey",
-                "-alias", KEY_ALIAS,
-                "-keyalg", KEY_ALG,
-                "-keysize", Integer.toString(KEY_SIZE),
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-dname", "CN=Test",
-                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+        createAlias(CA_KEY_ALIAS);
+        createAlias(KEY_ALIAS);
+        issueCert(
+                KEY_ALIAS,
+                "-validity", Integer.toString(VALIDITY));
 
         // sign jar
         OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/MultipleWarningsTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/MultipleWarningsTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,35 +54,25 @@
         // create a jar file that contains one class file
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
+        createAlias(CA_KEY_ALIAS);
+
         // create first expired certificate
         // whose ExtendedKeyUsage extension does not allow code signing
-        keytool(
-                "-genkey",
-                "-alias", FIRST_KEY_ALIAS,
-                "-keyalg", KEY_ALG,
-                "-keysize", Integer.toString(KEY_SIZE),
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-dname", "CN=First",
+        createAlias(FIRST_KEY_ALIAS);
+        issueCert(
+                FIRST_KEY_ALIAS,
                 "-ext", "ExtendedkeyUsage=serverAuth",
                 "-startdate", "-" + VALIDITY * 2 + "d",
-                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+                "-validity", Integer.toString(VALIDITY));
 
         // create second expired certificate
         // whose KeyUsage extension does not allow code signing
-        keytool(
-                "-genkey",
-                "-alias", SECOND_KEY_ALIAS,
-                "-keyalg", KEY_ALG,
-                "-keysize", Integer.toString(KEY_SIZE),
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-dname", "CN=Second",
+        createAlias(SECOND_KEY_ALIAS);
+        issueCert(
+                SECOND_KEY_ALIAS,
                 "-ext", "ExtendedkeyUsage=serverAuth",
                 "-startdate", "-" + VALIDITY * 2 + "d",
-                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+                "-validity", Integer.toString(VALIDITY));
 
         // sign jar with first key
         OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -57,15 +57,9 @@
                 * 24 * 60 * 60 * 1000L);
 
         // create key pair
-        keytool(
-                "-genkey",
-                "-alias", KEY_ALIAS,
-                "-keyalg", KEY_ALG,
-                "-keysize", Integer.toString(KEY_SIZE),
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-dname", "CN=Test",
+        createAlias(CA_KEY_ALIAS);
+        createAlias(KEY_ALIAS);
+        issueCert(KEY_ALIAS,
                 "-validity", Integer.toString(VALIDITY));
 
         // sign jar file
--- a/test/jdk/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,29 +49,19 @@
         Utils.createFiles(FIRST_FILE);
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
-        // create first key pair for signing
-        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);
+        createAlias(CA_KEY_ALIAS);
 
         // create first key pair for signing
-        keytool(
-                "-genkey",
-                "-alias", SECOND_KEY_ALIAS,
-                "-keyalg", KEY_ALG,
-                "-keysize", Integer.toString(KEY_SIZE),
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-dname", "CN=Second",
-                "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
+        createAlias(FIRST_KEY_ALIAS);
+        issueCert(
+                FIRST_KEY_ALIAS,
+                "-validity", Integer.toString(VALIDITY));
+
+        // create first key pair for signing
+        createAlias(SECOND_KEY_ALIAS);
+        issueCert(
+                SECOND_KEY_ALIAS,
+                "-validity", Integer.toString(VALIDITY));
 
         // sign jar with first key
         OutputAnalyzer analyzer = jarsigner(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/NotYetValidCertTest.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/NotYetValidCertTest.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,15 +50,11 @@
         JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
 
         // create certificate that will be valid only tomorrow
-        keytool(
-                "-genkey",
-                "-alias", KEY_ALIAS,
-                "-keyalg", KEY_ALG,
-                "-keysize", Integer.toString(KEY_SIZE),
-                "-keystore", KEYSTORE,
-                "-storepass", PASSWORD,
-                "-keypass", PASSWORD,
-                "-dname", "CN=Test",
+        createAlias(CA_KEY_ALIAS);
+        createAlias(KEY_ALIAS);
+
+        issueCert(
+                KEY_ALIAS,
                 "-startdate", "+1d",
                 "-validity", Integer.toString(VALIDITY));
 
--- a/test/jdk/sun/security/tools/jarsigner/warnings/Test.java	Tue Feb 13 15:32:41 2018 -0800
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/Test.java	Wed Feb 14 16:58:49 2018 +0800
@@ -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.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -45,7 +45,6 @@
     static final String FIRST_FILE = "first.txt";
     static final String SECOND_FILE = "second.txt";
     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 KEYSTORE = "keystore.jks";
     static final String FIRST_KEY_ALIAS = "first";
@@ -55,11 +54,13 @@
     static final String CERT_REQUEST_FILENAME = "test.req";
     static final String CERT_FILENAME = "test.crt";
     static final String CA_KEY_ALIAS = "ca";
+    static final String CA2_KEY_ALIAS = "ca2";
     static final int KEY_SIZE = 2048;
     static final int TIMEOUT = 6 * 60 * 1000;   // in millis
     static final int VALIDITY = 365;
 
     static final String WARNING = "Warning:";
+    static final String WARNING_OR_ERROR = "(Warning|Error):";
 
     static final String CHAIN_NOT_VALIDATED_VERIFYING_WARNING
             = "This jar contains entries "
@@ -154,14 +155,72 @@
     static final int ALIAS_NOT_IN_STORE_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,
             String... warnings) {
         analyzer.shouldHaveExitValue(expectedExitCode);
+        int count = 0;
         for (String warning : warnings) {
-            analyzer.shouldContain(warning);
+            if (warning.startsWith("!")) {
+                analyzer.shouldNotContain(warning.substring(1));
+            } else {
+                count++;
+                analyzer.shouldContain(warning);
+            }
         }
-        if (warnings.length > 0) {
-            analyzer.shouldContain(WARNING);
+        if (count > 0) {
+            analyzer.shouldMatch(WARNING_OR_ERROR);
         }
         if (expectedExitCode == 0) {
             analyzer.shouldContain(JAR_VERIFIED);
@@ -172,11 +231,17 @@
 
     protected void checkSigning(OutputAnalyzer analyzer, String... warnings) {
         analyzer.shouldHaveExitValue(0);
+        int count = 0;
         for (String warning : warnings) {
-            analyzer.shouldContain(warning);
+            if (warning.startsWith("!")) {
+                analyzer.shouldNotContain(warning.substring(1));
+            } else {
+                count++;
+                analyzer.shouldContain(warning);
+            }
         }
-        if (warnings.length > 0) {
-            analyzer.shouldContain(WARNING);
+        if (count > 0) {
+            analyzer.shouldMatch(WARNING_OR_ERROR);
         }
         analyzer.shouldContain(JAR_SIGNED);
     }
--- a/test/jdk/sun/security/tools/jarsigner/warnings/bad_netscape_cert_type.jks.base64	Tue Feb 13 15:32:41 2018 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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=
--- a/test/jdk/sun/security/tools/jarsigner/warnings/bad_netscape_cert_type.sh	Tue Feb 13 15:32:41 2018 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -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