< prev index next >

src/java.base/share/classes/sun/security/tools/keytool/Main.java

Print this page
rev 16540 : 8171319: keytool should print out warnings when reading or generating cert/cert req using weak algorithms


  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.tools.keytool;
  27 
  28 import java.io.*;
  29 import java.security.CodeSigner;

  30 import java.security.KeyStore;
  31 import java.security.KeyStoreException;
  32 import java.security.MessageDigest;
  33 import java.security.Key;
  34 import java.security.PublicKey;
  35 import java.security.PrivateKey;
  36 import java.security.Signature;
  37 import java.security.Timestamp;
  38 import java.security.UnrecoverableEntryException;
  39 import java.security.UnrecoverableKeyException;
  40 import java.security.Principal;
  41 import java.security.cert.Certificate;
  42 import java.security.cert.CertificateFactory;
  43 import java.security.cert.CertStoreException;
  44 import java.security.cert.CRL;
  45 import java.security.cert.X509Certificate;
  46 import java.security.cert.CertificateException;
  47 import java.security.cert.URICertStoreParameters;
  48 
  49 


 139     private char[] storePassNew = null;
 140     private char[] keyPass = null;
 141     private char[] keyPassNew = null;
 142     private char[] newPass = null;
 143     private char[] destKeyPass = null;
 144     private char[] srckeyPass = null;
 145     private String ksfname = null;
 146     private File ksfile = null;
 147     private InputStream ksStream = null; // keystore stream
 148     private String sslserver = null;
 149     private String jarfile = null;
 150     private KeyStore keyStore = null;
 151     private boolean token = false;
 152     private boolean nullStream = false;
 153     private boolean kssave = false;
 154     private boolean noprompt = false;
 155     private boolean trustcacerts = false;
 156     private boolean protectedPath = false;
 157     private boolean srcprotectedPath = false;
 158     private boolean cacerts = false;

 159     private CertificateFactory cf = null;
 160     private KeyStore caks = null; // "cacerts" keystore
 161     private char[] srcstorePass = null;
 162     private String srcstoretype = null;
 163     private Set<char[]> passwords = new HashSet<>();
 164     private String startDate = null;
 165 
 166     private List<String> ids = new ArrayList<>();   // used in GENCRL
 167     private List<String> v3ext = new ArrayList<>();
 168 










 169     enum Command {
 170         CERTREQ("Generates.a.certificate.request",
 171             ALIAS, SIGALG, FILEOUT, KEYPASS, KEYSTORE, DNAME,
 172             STOREPASS, STORETYPE, PROVIDERNAME, ADDPROVIDER,
 173             PROVIDERCLASS, PROVIDERPATH, V, PROTECTED),
 174         CHANGEALIAS("Changes.an.entry.s.alias",
 175             ALIAS, DESTALIAS, KEYPASS, KEYSTORE, CACERTS, STOREPASS,
 176             STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
 177             PROVIDERPATH, V, PROTECTED),
 178         DELETE("Deletes.an.entry",
 179             ALIAS, KEYSTORE, CACERTS, STOREPASS, STORETYPE,
 180             PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
 181             PROVIDERPATH, V, PROTECTED),
 182         EXPORTCERT("Exports.certificate",
 183             RFC, ALIAS, FILEOUT, KEYSTORE, CACERTS, STOREPASS,
 184             STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
 185             PROVIDERPATH, V, PROTECTED),
 186         GENKEYPAIR("Generates.a.key.pair",
 187             ALIAS, KEYALG, KEYSIZE, SIGALG, DESTALIAS, DNAME,
 188             STARTDATE, EXT, VALIDITY, KEYPASS, KEYSTORE,


 334         STORETYPE("storetype", "<type>", "keystore.type"),
 335         TRUSTCACERTS("trustcacerts", null, "trust.certificates.from.cacerts"),
 336         V("v", null, "verbose.output"),
 337         VALIDITY("validity", "<days>", "validity.number.of.days");
 338 
 339         final String name, arg, description;
 340         Option(String name, String arg, String description) {
 341             this.name = name;
 342             this.arg = arg;
 343             this.description = description;
 344         }
 345         @Override
 346         public String toString() {
 347             return "-" + name;
 348         }
 349     };
 350 
 351     private static final String NONE = "NONE";
 352     private static final String P11KEYSTORE = "PKCS11";
 353     private static final String P12KEYSTORE = "PKCS12";
 354     private final String keyAlias = "mykey";
 355 
 356     // for i18n
 357     private static final java.util.ResourceBundle rb =
 358         java.util.ResourceBundle.getBundle(
 359             "sun.security.tools.keytool.Resources");
 360     private static final Collator collator = Collator.getInstance();
 361     static {
 362         // this is for case insensitive string comparisons
 363         collator.setStrength(Collator.PRIMARY);
 364     };
 365 
 366     private Main() { }
 367 
 368     public static void main(String[] args) throws Exception {
 369         Main kt = new Main();
 370         kt.run(args, System.out);
 371     }
 372 
 373     private void run(String[] args, PrintStream out) throws Exception {
 374         try {
 375             args = parseArgs(args);
 376             if (command != null) {
 377                 doCommands(out);
 378             }
 379         } catch (Exception e) {
 380             System.out.println(rb.getString("keytool.error.") + e);
 381             if (verbose) {
 382                 e.printStackTrace(System.out);
 383             }
 384             if (!debug) {
 385                 System.exit(1);
 386             } else {
 387                 throw e;
 388             }
 389         } finally {

 390             for (char[] pass : passwords) {
 391                 if (pass != null) {
 392                     Arrays.fill(pass, ' ');
 393                     pass = null;
 394                 }
 395             }
 396 
 397             if (ksStream != null) {
 398                 ksStream.close();
 399             }
 400         }
 401     }
 402 
 403     /**
 404      * Parse command line arguments.
 405      */
 406     String[] parseArgs(String[] args) throws Exception {
 407 
 408         int i=0;
 409         boolean help = args.length == 0;


 459              * Check modifiers
 460              */
 461             String modifier = null;
 462             int pos = flags.indexOf(':');
 463             if (pos > 0) {
 464                 modifier = flags.substring(pos+1);
 465                 flags = flags.substring(0, pos);
 466             }
 467 
 468             /*
 469              * command modes
 470              */
 471             Command c = Command.getCommand(flags);
 472 
 473             if (c != null) {
 474                 command = c;
 475             } else if (collator.compare(flags, "-help") == 0) {
 476                 help = true;
 477             } else if (collator.compare(flags, "-conf") == 0) {
 478                 i++;


 479             } else if (collator.compare(flags, "-keystore") == 0) {
 480                 ksfname = args[++i];
 481                 if (new File(ksfname).getCanonicalPath().equals(
 482                         new File(KeyStoreUtil.getCacerts()).getCanonicalPath())) {
 483                     System.err.println(rb.getString("warning.cacerts.option"));
 484                 }
 485             } else if (collator.compare(flags, "-destkeystore") == 0) {
 486                 ksfname = args[++i];
 487             } else if (collator.compare(flags, "-cacerts") == 0) {
 488                 cacerts = true;
 489             } else if (collator.compare(flags, "-storepass") == 0 ||
 490                     collator.compare(flags, "-deststorepass") == 0) {
 491                 storePass = getPass(modifier, args[++i]);
 492                 passwords.add(storePass);
 493             } else if (collator.compare(flags, "-storetype") == 0 ||
 494                     collator.compare(flags, "-deststoretype") == 0) {
 495                 storetype = args[++i];
 496                 hasStoretypeOption = true;
 497             } else if (collator.compare(flags, "-srcstorepass") == 0) {
 498                 srcstorePass = getPass(modifier, args[++i]);


1135 
1136             doCloneEntry(alias, dest, true);  // Now everything can be cloned
1137             kssave = true;
1138         } else if (command == CHANGEALIAS) {
1139             if (alias == null) {
1140                 alias = keyAlias;
1141             }
1142             doCloneEntry(alias, dest, false);
1143             // in PKCS11, clone a PrivateKeyEntry will delete the old one
1144             if (keyStore.containsAlias(alias)) {
1145                 doDeleteEntry(alias);
1146             }
1147             kssave = true;
1148         } else if (command == KEYPASSWD) {
1149             keyPassNew = newPass;
1150             doChangeKeyPasswd(alias);
1151             kssave = true;
1152         } else if (command == LIST) {
1153             if (storePass == null
1154                     && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
1155                 printWarning();
1156             }
1157 
1158             if (alias != null) {
1159                 doPrintEntry(alias, out);
1160             } else {
1161                 doPrintEntries(out);
1162             }
1163         } else if (command == PRINTCERT) {
1164             doPrintCert(out);
1165         } else if (command == SELFCERT) {
1166             doSelfCert(alias, dname, sigAlgName);
1167             kssave = true;
1168         } else if (command == STOREPASSWD) {
1169             storePassNew = newPass;
1170             if (storePassNew == null) {
1171                 storePassNew = getNewPasswd("keystore password", storePass);
1172             }
1173             kssave = true;
1174         } else if (command == GENCERT) {
1175             if (alias == null) {
1176                 alias = keyAlias;
1177             }
1178             InputStream inStream = System.in;
1179             if (infilename != null) {


1236                 } else {
1237                     ByteArrayOutputStream bout = new ByteArrayOutputStream();
1238                     keyStore.store(bout, pass);
1239                     try (FileOutputStream fout = new FileOutputStream(ksfname)) {
1240                         fout.write(bout.toByteArray());
1241                     }
1242                 }
1243             }
1244         }
1245     }
1246 
1247     /**
1248      * Generate a certificate: Read PKCS10 request from in, and print
1249      * certificate to out. Use alias as CA, sigAlgName as the signature
1250      * type.
1251      */
1252     private void doGenCert(String alias, String sigAlgName, InputStream in, PrintStream out)
1253             throws Exception {
1254 
1255 






1256         Certificate signerCert = keyStore.getCertificate(alias);
1257         byte[] encoded = signerCert.getEncoded();
1258         X509CertImpl signerCertImpl = new X509CertImpl(encoded);
1259         X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
1260                 X509CertImpl.NAME + "." + X509CertImpl.INFO);
1261         X500Name issuer = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." +
1262                                            X509CertInfo.DN_NAME);
1263 
1264         Date firstDate = getStartDate(startDate);
1265         Date lastDate = new Date();
1266         lastDate.setTime(firstDate.getTime() + validity*1000L*24L*60L*60L);
1267         CertificateValidity interval = new CertificateValidity(firstDate,
1268                                                                lastDate);
1269 
1270         PrivateKey privateKey =
1271                 (PrivateKey)recoverKey(alias, storePass, keyPass).fst;
1272         if (sigAlgName == null) {
1273             sigAlgName = getCompatibleSigAlgName(privateKey);
1274         }
1275         Signature signature = Signature.getInstance(sigAlgName);


1289         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
1290         boolean canRead = false;
1291         StringBuffer sb = new StringBuffer();
1292         while (true) {
1293             String s = reader.readLine();
1294             if (s == null) break;
1295             // OpenSSL does not use NEW
1296             //if (s.startsWith("-----BEGIN NEW CERTIFICATE REQUEST-----")) {
1297             if (s.startsWith("-----BEGIN") && s.indexOf("REQUEST") >= 0) {
1298                 canRead = true;
1299             //} else if (s.startsWith("-----END NEW CERTIFICATE REQUEST-----")) {
1300             } else if (s.startsWith("-----END") && s.indexOf("REQUEST") >= 0) {
1301                 break;
1302             } else if (canRead) {
1303                 sb.append(s);
1304             }
1305         }
1306         byte[] rawReq = Pem.decode(new String(sb));
1307         PKCS10 req = new PKCS10(rawReq);
1308 


1309         info.set(X509CertInfo.KEY, new CertificateX509Key(req.getSubjectPublicKeyInfo()));
1310         info.set(X509CertInfo.SUBJECT,
1311                     dname==null?req.getSubjectName():new X500Name(dname));
1312         CertificateExtensions reqex = null;
1313         Iterator<PKCS10Attribute> attrs = req.getAttributes().getAttributes().iterator();
1314         while (attrs.hasNext()) {
1315             PKCS10Attribute attr = attrs.next();
1316             if (attr.getAttributeId().equals(PKCS9Attribute.EXTENSION_REQUEST_OID)) {
1317                 reqex = (CertificateExtensions)attr.getAttributeValue();
1318             }
1319         }
1320         CertificateExtensions ext = createV3Extensions(
1321                 reqex,
1322                 null,
1323                 v3ext,
1324                 req.getSubjectPublicKeyInfo(),
1325                 signerCert.getPublicKey());
1326         info.set(X509CertInfo.EXTENSIONS, ext);
1327         X509CertImpl cert = new X509CertImpl(info);
1328         cert.sign(privateKey, sigAlgName);
1329         dumpCert(cert, out);
1330         for (Certificate ca: keyStore.getCertificateChain(alias)) {
1331             if (ca instanceof X509Certificate) {
1332                 X509Certificate xca = (X509Certificate)ca;
1333                 if (!KeyStoreUtil.isSelfSigned(xca)) {
1334                     dumpCert(xca, out);
1335                 }
1336             }
1337         }



1338     }
1339 
1340     private void doGenCRL(PrintStream out)
1341             throws Exception {
1342         if (ids == null) {
1343             throw new Exception("Must provide -id when -gencrl");
1344         }
1345         Certificate signerCert = keyStore.getCertificate(alias);
1346         byte[] encoded = signerCert.getEncoded();
1347         X509CertImpl signerCertImpl = new X509CertImpl(encoded);
1348         X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
1349                 X509CertImpl.NAME + "." + X509CertImpl.INFO);
1350         X500Name owner = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." +
1351                                                       X509CertInfo.DN_NAME);
1352 
1353         Date firstDate = getStartDate(startDate);
1354         Date lastDate = (Date) firstDate.clone();
1355         lastDate.setTime(lastDate.getTime() + validity*1000*24*60*60);
1356         CertificateValidity interval = new CertificateValidity(firstDate,
1357                                                                lastDate);


1368             String id = ids.get(i);
1369             int d = id.indexOf(':');
1370             if (d >= 0) {
1371                 CRLExtensions ext = new CRLExtensions();
1372                 ext.set("Reason", new CRLReasonCodeExtension(Integer.parseInt(id.substring(d+1))));
1373                 badCerts[i] = new X509CRLEntryImpl(new BigInteger(id.substring(0, d)),
1374                         firstDate, ext);
1375             } else {
1376                 badCerts[i] = new X509CRLEntryImpl(new BigInteger(ids.get(i)), firstDate);
1377             }
1378         }
1379         X509CRLImpl crl = new X509CRLImpl(owner, firstDate, lastDate, badCerts);
1380         crl.sign(privateKey, sigAlgName);
1381         if (rfc) {
1382             out.println("-----BEGIN X509 CRL-----");
1383             out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(crl.getEncodedInternal()));
1384             out.println("-----END X509 CRL-----");
1385         } else {
1386             out.write(crl.getEncodedInternal());
1387         }

1388     }
1389 
1390     /**
1391      * Creates a PKCS#10 cert signing request, corresponding to the
1392      * keys (and name) associated with a given alias.
1393      */
1394     private void doCertReq(String alias, String sigAlgName, PrintStream out)
1395         throws Exception
1396     {
1397         if (alias == null) {
1398             alias = keyAlias;
1399         }
1400 
1401         Pair<Key,char[]> objs = recoverKey(alias, storePass, keyPass);
1402         PrivateKey privKey = (PrivateKey)objs.fst;
1403         if (keyPass == null) {
1404             keyPass = objs.snd;
1405         }
1406 
1407         Certificate cert = keyStore.getCertificate(alias);


1414         PKCS10 request = new PKCS10(cert.getPublicKey());
1415         CertificateExtensions ext = createV3Extensions(null, null, v3ext, cert.getPublicKey(), null);
1416         // Attribute name is not significant
1417         request.getAttributes().setAttribute(X509CertInfo.EXTENSIONS,
1418                 new PKCS10Attribute(PKCS9Attribute.EXTENSION_REQUEST_OID, ext));
1419 
1420         // Construct a Signature object, so that we can sign the request
1421         if (sigAlgName == null) {
1422             sigAlgName = getCompatibleSigAlgName(privKey);
1423         }
1424 
1425         Signature signature = Signature.getInstance(sigAlgName);
1426         signature.initSign(privKey);
1427         X500Name subject = dname == null?
1428                 new X500Name(((X509Certificate)cert).getSubjectDN().toString()):
1429                 new X500Name(dname);
1430 
1431         // Sign the request and base-64 encode it
1432         request.encodeAndSign(subject, signature);
1433         request.print(out);


1434     }
1435 
1436     /**
1437      * Deletes an entry from the keystore.
1438      */
1439     private void doDeleteEntry(String alias) throws Exception {
1440         if (keyStore.containsAlias(alias) == false) {
1441             MessageFormat form = new MessageFormat
1442                 (rb.getString("Alias.alias.does.not.exist"));
1443             Object[] source = {alias};
1444             throw new Exception(form.format(source));
1445         }
1446         keyStore.deleteEntry(alias);
1447     }
1448 
1449     /**
1450      * Exports a certificate from the keystore.
1451      */
1452     private void doExportCert(String alias, PrintStream out)
1453         throws Exception
1454     {
1455         if (storePass == null
1456                 && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
1457             printWarning();
1458         }
1459         if (alias == null) {
1460             alias = keyAlias;
1461         }
1462         if (keyStore.containsAlias(alias) == false) {
1463             MessageFormat form = new MessageFormat
1464                 (rb.getString("Alias.alias.does.not.exist"));
1465             Object[] source = {alias};
1466             throw new Exception(form.format(source));
1467         }
1468 
1469         X509Certificate cert = (X509Certificate)keyStore.getCertificate(alias);
1470         if (cert == null) {
1471             MessageFormat form = new MessageFormat
1472                 (rb.getString("Alias.alias.has.no.certificate"));
1473             Object[] source = {alias};
1474             throw new Exception(form.format(source));
1475         }
1476         dumpCert(cert, out);

1477     }
1478 
1479     /**
1480      * Prompt the user for a keypass when generating a key entry.
1481      * @param alias the entry we will set password for
1482      * @param orig the original entry of doing a dup, null if generate new
1483      * @param origPass the password to copy from if user press ENTER
1484      */
1485     private char[] promptForKeyPass(String alias, String orig, char[] origPass) throws Exception{
1486         if (P12KEYSTORE.equalsIgnoreCase(storetype)) {
1487             return origPass;
1488         } else if (!token && !protectedPath) {
1489             // Prompt for key password
1490             int count;
1491             for (count = 0; count < 3; count++) {
1492                 MessageFormat form = new MessageFormat(rb.getString
1493                         ("Enter.key.password.for.alias."));
1494                 Object[] source = {alias};
1495                 System.err.println(form.format(source));
1496                 if (orig == null) {


1712 
1713         X509Certificate[] chain = new X509Certificate[1];
1714         chain[0] = keypair.getSelfCertificate(
1715                 x500Name, getStartDate(startDate), validity*24L*60L*60L, ext);
1716 
1717         if (verbose) {
1718             MessageFormat form = new MessageFormat(rb.getString
1719                 ("Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for"));
1720             Object[] source = {keysize,
1721                                 privKey.getAlgorithm(),
1722                                 chain[0].getSigAlgName(),
1723                                 validity,
1724                                 x500Name};
1725             System.err.println(form.format(source));
1726         }
1727 
1728         if (keyPass == null) {
1729             keyPass = promptForKeyPass(alias, null, storePass);
1730         }
1731         keyStore.setKeyEntry(alias, privKey, keyPass, chain);


1732     }
1733 
1734     /**
1735      * Clones an entry
1736      * @param orig original alias
1737      * @param dest destination alias
1738      * @changePassword if the password can be changed
1739      */
1740     private void doCloneEntry(String orig, String dest, boolean changePassword)
1741         throws Exception
1742     {
1743         if (orig == null) {
1744             orig = keyAlias;
1745         }
1746 
1747         if (keyStore.containsAlias(dest)) {
1748             MessageFormat form = new MessageFormat
1749                 (rb.getString("Destination.alias.dest.already.exists"));
1750             Object[] source = {dest};
1751             throw new Exception(form.format(source));


1793         }
1794         keyStore.setKeyEntry(alias, privKey, keyPassNew,
1795                              keyStore.getCertificateChain(alias));
1796     }
1797 
1798     /**
1799      * Imports a JDK 1.1-style identity database. We can only store one
1800      * certificate per identity, because we use the identity's name as the
1801      * alias (which references a keystore entry), and aliases must be unique.
1802      */
1803     private void doImportIdentityDatabase(InputStream in)
1804         throws Exception
1805     {
1806         System.err.println(rb.getString
1807             ("No.entries.from.identity.database.added"));
1808     }
1809 
1810     /**
1811      * Prints a single keystore entry.
1812      */
1813     private void doPrintEntry(String alias, PrintStream out)
1814         throws Exception
1815     {
1816         if (keyStore.containsAlias(alias) == false) {
1817             MessageFormat form = new MessageFormat
1818                 (rb.getString("Alias.alias.does.not.exist"));
1819             Object[] source = {alias};
1820             throw new Exception(form.format(source));
1821         }
1822 
1823         if (verbose || rfc || debug) {
1824             MessageFormat form = new MessageFormat
1825                 (rb.getString("Alias.name.alias"));
1826             Object[] source = {alias};
1827             out.println(form.format(source));
1828 
1829             if (!token) {
1830                 form = new MessageFormat(rb.getString
1831                     ("Creation.date.keyStore.getCreationDate.alias."));
1832                 Object[] src = {keyStore.getCreationDate(alias)};
1833                 out.println(form.format(src));


1864             }
1865 
1866             // Get the chain
1867             Certificate[] chain = keyStore.getCertificateChain(alias);
1868             if (chain != null) {
1869                 if (verbose || rfc || debug) {
1870                     out.println(rb.getString
1871                         ("Certificate.chain.length.") + chain.length);
1872                     for (int i = 0; i < chain.length; i ++) {
1873                         MessageFormat form = new MessageFormat
1874                                 (rb.getString("Certificate.i.1."));
1875                         Object[] source = {(i + 1)};
1876                         out.println(form.format(source));
1877                         if (verbose && (chain[i] instanceof X509Certificate)) {
1878                             printX509Cert((X509Certificate)(chain[i]), out);
1879                         } else if (debug) {
1880                             out.println(chain[i].toString());
1881                         } else {
1882                             dumpCert(chain[i], out);
1883                         }

1884                     }
1885                 } else {
1886                     // Print the digest of the user cert only
1887                     out.println
1888                         (rb.getString("Certificate.fingerprint.SHA.256.") +
1889                         getCertFingerPrint("SHA-256", chain[0]));

1890                 }
1891             }
1892         } else if (keyStore.entryInstanceOf(alias,
1893                 KeyStore.TrustedCertificateEntry.class)) {
1894             // We have a trusted certificate entry
1895             Certificate cert = keyStore.getCertificate(alias);
1896             Object[] source = {"trustedCertEntry"};
1897             String mf = new MessageFormat(
1898                     rb.getString("Entry.type.type.")).format(source) + "\n";
1899             if (verbose && (cert instanceof X509Certificate)) {
1900                 out.println(mf);
1901                 printX509Cert((X509Certificate)cert, out);
1902             } else if (rfc) {
1903                 out.println(mf);
1904                 dumpCert(cert, out);
1905             } else if (debug) {
1906                 out.println(cert.toString());
1907             } else {
1908                 out.println("trustedCertEntry, ");
1909                 out.println(rb.getString("Certificate.fingerprint.SHA.256.")
1910                             + getCertFingerPrint("SHA-256", cert));
1911             }

1912         } else {
1913             out.println(rb.getString("Unknown.Entry.Type"));
1914         }
1915     }
1916 
1917     /**
1918      * Load the srckeystore from a stream, used in -importkeystore
1919      * @return the src KeyStore
1920      */
1921     KeyStore loadSourceKeyStore() throws Exception {
1922         boolean isPkcs11 = false;
1923 
1924         InputStream is = null;
1925         File srcksfile = null;
1926 
1927         if (P11KEYSTORE.equalsIgnoreCase(srcstoretype) ||
1928                 KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
1929             if (!NONE.equals(srcksfname)) {
1930                 System.err.println(MessageFormat.format(rb.getString
1931                     (".keystore.must.be.NONE.if.storetype.is.{0}"), srcstoretype));


1975             if (P12KEYSTORE.equalsIgnoreCase(srcstoretype)) {
1976                 if (srckeyPass != null && srcstorePass != null &&
1977                         !Arrays.equals(srcstorePass, srckeyPass)) {
1978                     MessageFormat form = new MessageFormat(rb.getString(
1979                         "Warning.Different.store.and.key.passwords.not.supported.for.PKCS12.KeyStores.Ignoring.user.specified.command.value."));
1980                     Object[] source = {"-srckeypass"};
1981                     System.err.println(form.format(source));
1982                     srckeyPass = srcstorePass;
1983                 }
1984             }
1985 
1986             store.load(is, srcstorePass);   // "is" already null in PKCS11
1987         } finally {
1988             if (is != null) {
1989                 is.close();
1990             }
1991         }
1992 
1993         if (srcstorePass == null
1994                 && !KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
1995             // anti refactoring, copied from printWarning(),
1996             // but change 2 lines
1997             System.err.println();
1998             System.err.println(rb.getString
1999                 (".WARNING.WARNING.WARNING."));
2000             System.err.println(rb.getString
2001                 (".The.integrity.of.the.information.stored.in.the.srckeystore."));
2002             System.err.println(rb.getString
2003                 (".WARNING.WARNING.WARNING."));
2004             System.err.println();
2005         }
2006 
2007         return store;
2008     }
2009 
2010     /**
2011      * import all keys and certs from importkeystore.
2012      * keep alias unchanged if no name conflict, otherwise, prompt.
2013      * keep keypass unchanged for keys
2014      */
2015     private void doImportKeyStore() throws Exception {


2098             MessageFormat form = new MessageFormat(rb.getString(
2099                     "Problem.importing.entry.for.alias.alias.exception.Entry.for.alias.alias.not.imported."));
2100             System.err.println(form.format(source2));
2101             return 2;
2102         }
2103     }
2104 
2105     private void doImportKeyStoreAll(KeyStore srckeystore) throws Exception {
2106 
2107         int ok = 0;
2108         int count = srckeystore.size();
2109         for (Enumeration<String> e = srckeystore.aliases();
2110                                         e.hasMoreElements(); ) {
2111             String alias = e.nextElement();
2112             int result = doImportKeyStoreSingle(srckeystore, alias);
2113             if (result == 1) {
2114                 ok++;
2115                 Object[] source = {alias};
2116                 MessageFormat form = new MessageFormat(rb.getString("Entry.for.alias.alias.successfully.imported."));
2117                 System.err.println(form.format(source));




2118             } else if (result == 2) {
2119                 if (!noprompt) {
2120                     String reply = getYesNoReply("Do you want to quit the import process? [no]:  ");
2121                     if ("YES".equals(reply)) {
2122                         break;
2123                     }
2124                 }
2125             }
2126         }
2127         Object[] source = {ok, count-ok};
2128         MessageFormat form = new MessageFormat(rb.getString(
2129                 "Import.command.completed.ok.entries.successfully.imported.fail.entries.failed.or.cancelled"));
2130         System.err.println(form.format(source));
2131     }
2132 
2133     /**
2134      * Prints all keystore entries.
2135      */
2136     private void doPrintEntries(PrintStream out)
2137         throws Exception
2138     {
2139         out.println(rb.getString("Keystore.type.") + keyStore.getType());
2140         out.println(rb.getString("Keystore.provider.") +
2141                 keyStore.getProvider().getName());
2142         out.println();
2143 
2144         MessageFormat form;
2145         form = (keyStore.size() == 1) ?
2146                 new MessageFormat(rb.getString
2147                         ("Your.keystore.contains.keyStore.size.entry")) :
2148                 new MessageFormat(rb.getString
2149                         ("Your.keystore.contains.keyStore.size.entries"));
2150         Object[] source = {keyStore.size()};
2151         out.println(form.format(source));
2152         out.println();
2153 
2154         for (Enumeration<String> e = keyStore.aliases();
2155                                         e.hasMoreElements(); ) {
2156             String alias = e.nextElement();
2157             doPrintEntry(alias, out);
2158             if (verbose || rfc) {
2159                 out.println(rb.getString("NEWLINE"));
2160                 out.println(rb.getString
2161                         ("STAR"));
2162                 out.println(rb.getString
2163                         ("STARNN"));
2164             }
2165         }
2166     }
2167 
2168     private static <T> Iterable<T> e2i(final Enumeration<T> e) {
2169         return new Iterable<T>() {
2170             @Override
2171             public Iterator<T> iterator() {
2172                 return new Iterator<T>() {
2173                     @Override
2174                     public boolean hasNext() {
2175                         return e.hasMoreElements();
2176                     }
2177                     @Override


2283             Certificate cert = ks.getCertificate(s);
2284             if (cert instanceof X509Certificate) {
2285                 X509Certificate xcert = (X509Certificate)cert;
2286                 if (xcert.getSubjectX500Principal().equals(issuer)) {
2287                     try {
2288                         ((X509CRLImpl)crl).verify(cert.getPublicKey());
2289                         return s;
2290                     } catch (Exception e) {
2291                     }
2292                 }
2293             }
2294         }
2295         return null;
2296     }
2297 
2298     private void doPrintCRL(String src, PrintStream out)
2299             throws Exception {
2300         for (CRL crl: loadCRLs(src)) {
2301             printCRL(crl, out);
2302             String issuer = null;

2303             if (caks != null) {
2304                 issuer = verifyCRL(caks, crl);
2305                 if (issuer != null) {

2306                     out.printf(rb.getString(
2307                             "verified.by.s.in.s"), issuer, "cacerts");



2308                     out.println();
2309                 }
2310             }
2311             if (issuer == null && keyStore != null) {
2312                 issuer = verifyCRL(keyStore, crl);
2313                 if (issuer != null) {

2314                     out.printf(rb.getString(
2315                             "verified.by.s.in.s"), issuer, "keystore");



2316                     out.println();
2317                 }
2318             }
2319             if (issuer == null) {
2320                 out.println(rb.getString
2321                         ("STAR"));
2322                 out.println(rb.getString
2323                         ("warning.not.verified.make.sure.keystore.is.correct"));
2324                 out.println(rb.getString
2325                         ("STARNN"));
2326             }

2327         }
2328     }
2329 
2330     private void printCRL(CRL crl, PrintStream out)
2331             throws Exception {
2332         if (rfc) {
2333             X509CRL xcrl = (X509CRL)crl;

2334             out.println("-----BEGIN X509 CRL-----");
2335             out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(xcrl.getEncoded()));
2336             out.println("-----END X509 CRL-----");
2337         } else {
2338             out.println(crl.toString());











2339         }
2340     }
2341 
2342     private void doPrintCertReq(InputStream in, PrintStream out)
2343             throws Exception {
2344 
2345         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
2346         StringBuffer sb = new StringBuffer();
2347         boolean started = false;
2348         while (true) {
2349             String s = reader.readLine();
2350             if (s == null) break;
2351             if (!started) {
2352                 if (s.startsWith("-----")) {
2353                     started = true;
2354                 }
2355             } else {
2356                 if (s.startsWith("-----")) {
2357                     break;
2358                 }
2359                 sb.append(s);
2360             }
2361         }
2362         PKCS10 req = new PKCS10(Pem.decode(new String(sb)));
2363 
2364         PublicKey pkey = req.getSubjectPublicKeyInfo();
2365         out.printf(rb.getString("PKCS.10.Certificate.Request.Version.1.0.Subject.s.Public.Key.s.format.s.key."),
2366                 req.getSubjectName(), pkey.getFormat(), pkey.getAlgorithm());



2367         for (PKCS10Attribute attr: req.getAttributes().getAttributes()) {
2368             ObjectIdentifier oid = attr.getAttributeId();
2369             if (oid.equals(PKCS9Attribute.EXTENSION_REQUEST_OID)) {
2370                 CertificateExtensions exts = (CertificateExtensions)attr.getAttributeValue();
2371                 if (exts != null) {
2372                     printExtensions(rb.getString("Extension.Request."), exts, out);
2373                 }
2374             } else {
2375                 out.println("Attribute: " + attr.getAttributeId());
2376                 PKCS9Attribute pkcs9Attr =
2377                         new PKCS9Attribute(attr.getAttributeId(),
2378                                            attr.getAttributeValue());
2379                 out.print(pkcs9Attr.getName() + ": ");
2380                 Object attrVal = attr.getAttributeValue();
2381                 out.println(attrVal instanceof String[] ?
2382                             Arrays.toString((String[]) attrVal) :
2383                             attrVal);
2384             }
2385         }
2386         if (debug) {
2387             out.println(req);   // Just to see more, say, public key length...
2388         }

2389     }
2390 
2391     /**
2392      * Reads a certificate (or certificate chain) and prints its contents in
2393      * a human readable format.
2394      */
2395     private void printCertFromStream(InputStream in, PrintStream out)
2396         throws Exception
2397     {
2398         Collection<? extends Certificate> c = null;
2399         try {
2400             c = cf.generateCertificates(in);
2401         } catch (CertificateException ce) {
2402             throw new Exception(rb.getString("Failed.to.parse.input"), ce);
2403         }
2404         if (c.isEmpty()) {
2405             throw new Exception(rb.getString("Empty.input"));
2406         }
2407         Certificate[] certs = c.toArray(new Certificate[c.size()]);
2408         for (int i=0; i<certs.length; i++) {
2409             X509Certificate x509Cert = null;
2410             try {
2411                 x509Cert = (X509Certificate)certs[i];
2412             } catch (ClassCastException cce) {
2413                 throw new Exception(rb.getString("Not.X.509.certificate"));
2414             }
2415             if (certs.length > 1) {
2416                 MessageFormat form = new MessageFormat
2417                         (rb.getString("Certificate.i.1."));
2418                 Object[] source = {i + 1};
2419                 out.println(form.format(source));
2420             }
2421             if (rfc)
2422                 dumpCert(x509Cert, out);
2423             else
2424                 printX509Cert(x509Cert, out);
2425             if (i < (certs.length-1)) {
2426                 out.println();
2427             }









2428         }
2429     }
2430 
2431     private void doPrintCert(final PrintStream out) throws Exception {
2432         if (jarfile != null) {
2433             // reset "jdk.certpath.disabledAlgorithms" security property
2434             // to be able to read jars which were signed with weak algorithms
2435             Security.setProperty(DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS, "");
2436 
2437             JarFile jf = new JarFile(jarfile, true);
2438             Enumeration<JarEntry> entries = jf.entries();
2439             Set<CodeSigner> ss = new HashSet<>();
2440             byte[] buffer = new byte[8192];
2441             int pos = 0;
2442             while (entries.hasMoreElements()) {
2443                 JarEntry je = entries.nextElement();
2444                 try (InputStream is = jf.getInputStream(je)) {
2445                     while (is.read(buffer) != -1) {
2446                         // we just read. this will throw a SecurityException
2447                         // if a signature/digest check fails. This also
2448                         // populate the signers
2449                     }
2450                 }
2451                 CodeSigner[] signers = je.getCodeSigners();
2452                 if (signers != null) {
2453                     for (CodeSigner signer: signers) {
2454                         if (!ss.contains(signer)) {
2455                             ss.add(signer);
2456                             out.printf(rb.getString("Signer.d."), ++pos);
2457                             out.println();
2458                             out.println();
2459                             out.println(rb.getString("Signature."));
2460                             out.println();
2461                             for (Certificate cert: signer.getSignerCertPath().getCertificates()) {




2462                                 X509Certificate x = (X509Certificate)cert;
2463                                 if (rfc) {
2464                                     out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n");
2465                                     dumpCert(x, out);
2466                                 } else {
2467                                     printX509Cert(x, out);
2468                                 }
2469                                 out.println();

2470                             }
2471                             Timestamp ts = signer.getTimestamp();
2472                             if (ts != null) {
2473                                 out.println(rb.getString("Timestamp."));
2474                                 out.println();
2475                                 for (Certificate cert: ts.getSignerCertPath().getCertificates()) {


2476                                     X509Certificate x = (X509Certificate)cert;
2477                                     if (rfc) {
2478                                         out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n");
2479                                         dumpCert(x, out);
2480                                     } else {
2481                                         printX509Cert(x, out);
2482                                     }
2483                                     out.println();

2484                                 }
2485                             }
2486                         }
2487                     }
2488                 }
2489             }
2490             jf.close();
2491             if (ss.isEmpty()) {
2492                 out.println(rb.getString("Not.a.signed.jar.file"));
2493             }
2494         } else if (sslserver != null) {
2495             CertStore cs = SSLServerCertStore.getInstance(new URI("https://" + sslserver));
2496             Collection<? extends Certificate> chain;
2497             try {
2498                 chain = cs.getCertificates(null);
2499                 if (chain.isEmpty()) {
2500                     // If the certs are not retrieved, we consider it an error
2501                     // even if the URL connection is successful.
2502                     throw new Exception(rb.getString(
2503                                         "No.certificate.from.the.SSL.server"));


2506                 if (cse.getCause() instanceof IOException) {
2507                     throw new Exception(rb.getString(
2508                                         "No.certificate.from.the.SSL.server"),
2509                                         cse.getCause());
2510                 } else {
2511                     throw cse;
2512                 }
2513             }
2514 
2515             int i = 0;
2516             for (Certificate cert : chain) {
2517                 try {
2518                     if (rfc) {
2519                         dumpCert(cert, out);
2520                     } else {
2521                         out.println("Certificate #" + i++);
2522                         out.println("====================================");
2523                         printX509Cert((X509Certificate)cert, out);
2524                         out.println();
2525                     }

2526                 } catch (Exception e) {
2527                     if (debug) {
2528                         e.printStackTrace();
2529                     }
2530                 }
2531             }
2532         } else {
2533             if (filename != null) {
2534                 try (FileInputStream inStream = new FileInputStream(filename)) {
2535                     printCertFromStream(inStream, out);
2536                 }
2537             } else {
2538                 printCertFromStream(System.in, out);
2539             }
2540         }
2541     }
2542     /**
2543      * Creates a self-signed certificate, and stores it as a single-element
2544      * certificate chain.
2545      */


2681             Object[] source = {alias};
2682             throw new Exception(form.format(source));
2683         }
2684 
2685         // Read the certificates in the reply
2686         Collection<? extends Certificate> c = cf.generateCertificates(in);
2687         if (c.isEmpty()) {
2688             throw new Exception(rb.getString("Reply.has.no.certificates"));
2689         }
2690         Certificate[] replyCerts = c.toArray(new Certificate[c.size()]);
2691         Certificate[] newChain;
2692         if (replyCerts.length == 1) {
2693             // single-cert reply
2694             newChain = establishCertChain(userCert, replyCerts[0]);
2695         } else {
2696             // cert-chain reply (e.g., PKCS#7)
2697             newChain = validateReply(alias, userCert, replyCerts);
2698         }
2699 
2700         // Now store the newly established chain in the keystore. The new
2701         // chain replaces the old one.
2702         if (newChain != null) {
2703             keyStore.setKeyEntry(alias, privKey,
2704                                  (keyPass != null) ? keyPass : storePass,
2705                                  newChain);
2706             return true;
2707         } else {
2708             return false;
2709         }
2710     }
2711 
2712     /**
2713      * Imports a certificate and adds it to the list of trusted certificates.
2714      *
2715      * @return true if the certificate was added, otherwise false.
2716      */
2717     private boolean addTrustedCert(String alias, InputStream in)
2718         throws Exception
2719     {
2720         if (alias == null) {
2721             throw new Exception(rb.getString("Must.specify.alias"));
2722         }
2723         if (keyStore.containsAlias(alias)) {
2724             MessageFormat form = new MessageFormat(rb.getString
2725                 ("Certificate.not.imported.alias.alias.already.exists"));
2726             Object[] source = {alias};
2727             throw new Exception(form.format(source));
2728         }
2729 
2730         // Read the certificate
2731         X509Certificate cert = null;
2732         try {
2733             cert = (X509Certificate)cf.generateCertificate(in);
2734         } catch (ClassCastException | CertificateException ce) {
2735             throw new Exception(rb.getString("Input.not.an.X.509.certificate"));
2736         }
2737 






2738         // if certificate is self-signed, make sure it verifies
2739         boolean selfSigned = false;
2740         if (KeyStoreUtil.isSelfSigned(cert)) {
2741             cert.verify(cert.getPublicKey());
2742             selfSigned = true;
2743         }
2744 
2745         if (noprompt) {
2746             keyStore.setCertificateEntry(alias, cert);
2747             return true;
2748         }
2749 
2750         // check if cert already exists in keystore
2751         String reply = null;
2752         String trustalias = keyStore.getCertificateAlias(cert);
2753         if (trustalias != null) {
2754             MessageFormat form = new MessageFormat(rb.getString
2755                 ("Certificate.already.exists.in.keystore.under.alias.trustalias."));
2756             Object[] source = {trustalias};
2757             System.err.println(form.format(source));


2758             reply = getYesNoReply
2759                 (rb.getString("Do.you.still.want.to.add.it.no."));
2760         } else if (selfSigned) {
2761             if (trustcacerts && (caks != null) &&
2762                     ((trustalias=caks.getCertificateAlias(cert)) != null)) {
2763                 MessageFormat form = new MessageFormat(rb.getString
2764                         ("Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias."));
2765                 Object[] source = {trustalias};
2766                 System.err.println(form.format(source));


2767                 reply = getYesNoReply
2768                         (rb.getString("Do.you.still.want.to.add.it.to.your.own.keystore.no."));
2769             }
2770             if (trustalias == null) {
2771                 // Print the cert and ask user if they really want to add
2772                 // it to their keystore
2773                 printX509Cert(cert, System.out);


2774                 reply = getYesNoReply
2775                         (rb.getString("Trust.this.certificate.no."));
2776             }
2777         }
2778         if (reply != null) {
2779             if ("YES".equals(reply)) {
2780                 keyStore.setCertificateEntry(alias, cert);
2781                 return true;
2782             } else {
2783                 return false;
2784             }
2785         }
2786 

2787         // Try to establish trust chain
2788         try {
2789             Certificate[] chain = establishCertChain(null, cert);
2790             if (chain != null) {
2791                 keyStore.setCertificateEntry(alias, cert);
2792                 return true;
2793             }
2794         } catch (Exception e) {
2795             // Print the cert and ask user if they really want to add it to
2796             // their keystore
2797             printX509Cert(cert, System.out);


2798             reply = getYesNoReply
2799                 (rb.getString("Trust.this.certificate.no."));
2800             if ("YES".equals(reply)) {
2801                 keyStore.setCertificateEntry(alias, cert);
2802                 return true;
2803             } else {
2804                 return false;
2805             }
2806         }
2807 
2808         return false;
2809     }
2810 
2811     /**
2812      * Prompts user for new password. New password must be different from
2813      * old one.
2814      *
2815      * @param prompt the message that gets prompted on the screen
2816      * @param oldPasswd the current (i.e., old) password
2817      */


2916                         ("Enter.key.password.for.alias."));
2917                 Object[] source = {alias};
2918                 System.err.print(form.format(source));
2919             }
2920             System.err.flush();
2921             keyPass = Password.readPassword(System.in);
2922             passwords.add(keyPass);
2923             if (keyPass == null) {
2924                 keyPass = otherKeyPass;
2925             }
2926             count++;
2927         } while ((keyPass == null) && count < 3);
2928 
2929         if (keyPass == null) {
2930             throw new Exception(rb.getString("Too.many.failures.try.later"));
2931         }
2932 
2933         return keyPass;
2934     }
2935 


















2936     /**
2937      * Prints a certificate in a human readable format.
2938      */
2939     private void printX509Cert(X509Certificate cert, PrintStream out)
2940         throws Exception
2941     {
2942 
2943         MessageFormat form = new MessageFormat
2944                 (rb.getString(".PATTERN.printX509Cert"));
2945         PublicKey pkey = cert.getPublicKey();
2946         Object[] source = {cert.getSubjectDN().toString(),
2947                         cert.getIssuerDN().toString(),
2948                         cert.getSerialNumber().toString(16),
2949                         cert.getNotBefore().toString(),
2950                         cert.getNotAfter().toString(),
2951                         getCertFingerPrint("SHA-1", cert),
2952                         getCertFingerPrint("SHA-256", cert),
2953                         cert.getSigAlgName(),
2954                         pkey.getAlgorithm(),
2955                         KeyUtil.getKeySize(pkey),
2956                         cert.getVersion(),
2957                         };
2958         out.println(form.format(source));
2959 
2960         if (cert instanceof X509CertImpl) {
2961             X509CertImpl impl = (X509CertImpl)cert;
2962             X509CertInfo certInfo = (X509CertInfo)impl.get(X509CertImpl.NAME
2963                                                            + "." +
2964                                                            X509CertImpl.INFO);
2965             CertificateExtensions exts = (CertificateExtensions)
2966                     certInfo.get(X509CertInfo.EXTENSIONS);
2967             if (exts != null) {
2968                 printExtensions(rb.getString("Extensions."), exts, out);
2969             }
2970         }
2971     }
2972 
2973     private static void printExtensions(String title, CertificateExtensions exts, PrintStream out)
2974             throws Exception {
2975         int extnum = 0;
2976         Iterator<Extension> i1 = exts.getAllExtensions().iterator();


3264             }
3265         }
3266 
3267         return Pair.of(entry, pkey);
3268     }
3269     /**
3270      * Gets the requested finger print of the certificate.
3271      */
3272     private String getCertFingerPrint(String mdAlg, Certificate cert)
3273         throws Exception
3274     {
3275         byte[] encCertInfo = cert.getEncoded();
3276         MessageDigest md = MessageDigest.getInstance(mdAlg);
3277         byte[] digest = md.digest(encCertInfo);
3278         return toHexString(digest);
3279     }
3280 
3281     /**
3282      * Prints warning about missing integrity check.
3283      */
3284     private void printWarning() {
3285         System.err.println();
3286         System.err.println(rb.getString
3287             (".WARNING.WARNING.WARNING."));
3288         System.err.println(rb.getString
3289             (".The.integrity.of.the.information.stored.in.your.keystore."));
3290         System.err.println(rb.getString
3291             (".WARNING.WARNING.WARNING."));
3292         System.err.println();
3293     }
3294 
3295     /**
3296      * Validates chain in certification reply, and returns the ordered
3297      * elements of the chain (with user certificate first, and root
3298      * certificate last in the array).
3299      *
3300      * @param alias the alias name
3301      * @param userCert the user certificate of the alias
3302      * @param replyCerts the chain provided in the reply
3303      */
3304     private Certificate[] validateReply(String alias,
3305                                         Certificate userCert,
3306                                         Certificate[] replyCerts)
3307         throws Exception
3308     {



3309         // order the certs in the reply (bottom-up).
3310         // we know that all certs in the reply are of type X.509, because
3311         // we parsed them using an X.509 certificate factory
3312         int i;
3313         PublicKey userPubKey = userCert.getPublicKey();
3314 
3315         // Remove duplicated certificates.
3316         HashSet<Certificate> nodup = new HashSet<>(Arrays.asList(replyCerts));
3317         replyCerts = nodup.toArray(new Certificate[nodup.size()]);
3318 
3319         for (i=0; i<replyCerts.length; i++) {
3320             if (userPubKey.equals(replyCerts[i].getPublicKey())) {
3321                 break;
3322             }
3323         }
3324         if (i == replyCerts.length) {
3325             MessageFormat form = new MessageFormat(rb.getString
3326                 ("Certificate.reply.does.not.contain.public.key.for.alias."));
3327             Object[] source = {alias};
3328             throw new Exception(form.format(source));


3352             }
3353         }
3354 
3355         if (noprompt) {
3356             return replyCerts;
3357         }
3358 
3359         // do we trust the cert at the top?
3360         Certificate topCert = replyCerts[replyCerts.length-1];
3361         Certificate root = getTrustedSigner(topCert, keyStore);
3362         if (root == null && trustcacerts && caks != null) {
3363             root = getTrustedSigner(topCert, caks);
3364         }
3365         if (root == null) {
3366             System.err.println();
3367             System.err.println
3368                     (rb.getString("Top.level.certificate.in.reply."));
3369             printX509Cert((X509Certificate)topCert, System.out);
3370             System.err.println();
3371             System.err.print(rb.getString(".is.not.trusted."));

3372             String reply = getYesNoReply
3373                     (rb.getString("Install.reply.anyway.no."));
3374             if ("NO".equals(reply)) {
3375                 return null;
3376             }
3377         } else {
3378             if (root != topCert) {
3379                 // append the root CA cert to the chain
3380                 Certificate[] tmpCerts =
3381                     new Certificate[replyCerts.length+1];
3382                 System.arraycopy(replyCerts, 0, tmpCerts, 0,
3383                                  replyCerts.length);
3384                 tmpCerts[tmpCerts.length-1] = root;
3385                 replyCerts = tmpCerts;









3386             }
3387         }
3388 
3389         return replyCerts;
3390     }
3391 
3392     /**
3393      * Establishes a certificate chain (using trusted certificates in the
3394      * keystore), starting with the user certificate
3395      * and ending at a self-signed certificate found in the keystore.
3396      *
3397      * @param userCert the user certificate of the alias
3398      * @param certToVerify the single certificate provided in the reply




3399      */
3400     private Certificate[] establishCertChain(Certificate userCert,
3401                                              Certificate certToVerify)
3402         throws Exception
3403     {
3404         if (userCert != null) {
3405             // Make sure that the public key of the certificate reply matches
3406             // the original public key in the keystore
3407             PublicKey origPubKey = userCert.getPublicKey();
3408             PublicKey replyPubKey = certToVerify.getPublicKey();
3409             if (!origPubKey.equals(replyPubKey)) {
3410                 throw new Exception(rb.getString
3411                         ("Public.keys.in.reply.and.keystore.don.t.match"));
3412             }
3413 
3414             // If the two certs are identical, we're done: no need to import
3415             // anything
3416             if (certToVerify.equals(userCert)) {
3417                 throw new Exception(rb.getString
3418                         ("Certificate.reply.and.certificate.in.keystore.are.identical"));
3419             }
3420         }
3421 
3422         // Build a hash table of all certificates in the keystore.
3423         // Use the subject distinguished name as the key into the hash table.
3424         // All certificates associated with the same subject distinguished
3425         // name are stored in the same hash table entry as a vector.
3426         Hashtable<Principal, Vector<Certificate>> certs = null;
3427         if (keyStore.size() > 0) {
3428             certs = new Hashtable<Principal, Vector<Certificate>>(11);
3429             keystorecerts2Hashtable(keyStore, certs);
3430         }
3431         if (trustcacerts) {
3432             if (caks!=null && caks.size()>0) {
3433                 if (certs == null) {
3434                     certs = new Hashtable<Principal, Vector<Certificate>>(11);
3435                 }
3436                 keystorecerts2Hashtable(caks, certs);
3437             }
3438         }
3439 
3440         // start building chain
3441         Vector<Certificate> chain = new Vector<>(2);
3442         if (buildChain((X509Certificate)certToVerify, chain, certs)) {
3443             Certificate[] newChain = new Certificate[chain.size()];
















3444             // buildChain() returns chain with self-signed root-cert first and
3445             // user-cert last, so we need to invert the chain before we store
3446             // it
3447             int j=0;
3448             for (int i=chain.size()-1; i>=0; i--) {
3449                 newChain[j] = chain.elementAt(i);
3450                 j++;
3451             }
3452             return newChain;
3453         } else {
3454             throw new Exception
3455                 (rb.getString("Failed.to.establish.chain.from.reply"));
3456         }
3457     }
3458 
3459     /**
3460      * Recursively tries to establish chain from pool of trusted certs.










3461      *
3462      * @param certToVerify the cert that needs to be verified.
3463      * @param chain the chain that's being built.
3464      * @param certs the pool of trusted certs
3465      *
3466      * @return true if successful, false otherwise.
3467      */
3468     private boolean buildChain(X509Certificate certToVerify,
3469                         Vector<Certificate> chain,
3470                         Hashtable<Principal, Vector<Certificate>> certs) {
3471         Principal issuer = certToVerify.getIssuerDN();
3472         if (KeyStoreUtil.isSelfSigned(certToVerify)) {
3473             // reached self-signed root cert;
3474             // no verification needed because it's trusted.
3475             chain.addElement(certToVerify);
3476             return true;
3477         }
3478 


3479         // Get the issuer's certificate(s)
3480         Vector<Certificate> vec = certs.get(issuer);
3481         if (vec == null) {
3482             return false;
3483         }
3484 
3485         // Try out each certificate in the vector, until we find one
3486         // whose public key verifies the signature of the certificate
3487         // in question.
3488         for (Enumeration<Certificate> issuerCerts = vec.elements();
3489              issuerCerts.hasMoreElements(); ) {
3490             X509Certificate issuerCert
3491                 = (X509Certificate)issuerCerts.nextElement();
3492             PublicKey issuerPubKey = issuerCert.getPublicKey();
3493             try {
3494                 certToVerify.verify(issuerPubKey);
3495             } catch (Exception e) {
3496                 continue;
3497             }
3498             if (buildChain(issuerCert, chain, certs)) {
3499                 chain.addElement(certToVerify);
3500                 return true;
3501             }
3502         }
3503         return false;
3504     }
3505 
3506     /**
3507      * Prompts user for yes/no decision.
3508      *
3509      * @return the user's decision, can only be "YES" or "NO"
3510      */
3511     private String getYesNoReply(String prompt)
3512         throws IOException
3513     {
3514         String reply = null;


3524                                         (System.in))).readLine();
3525             if (reply == null ||
3526                 collator.compare(reply, "") == 0 ||
3527                 collator.compare(reply, rb.getString("n")) == 0 ||
3528                 collator.compare(reply, rb.getString("no")) == 0) {
3529                 reply = "NO";
3530             } else if (collator.compare(reply, rb.getString("y")) == 0 ||
3531                        collator.compare(reply, rb.getString("yes")) == 0) {
3532                 reply = "YES";
3533             } else {
3534                 System.err.println(rb.getString("Wrong.answer.try.again"));
3535                 reply = null;
3536             }
3537         } while (reply == null);
3538         return reply;
3539     }
3540 
3541     /**
3542      * Stores the (leaf) certificates of a keystore in a hashtable.
3543      * All certs belonging to the same CA are stored in a vector that
3544      * in turn is stored in the hashtable, keyed by the CA's subject DN

3545      */
3546     private void keystorecerts2Hashtable(KeyStore ks,
3547                 Hashtable<Principal, Vector<Certificate>> hash)
3548         throws Exception {
3549 
3550         for (Enumeration<String> aliases = ks.aliases();
3551                                         aliases.hasMoreElements(); ) {
3552             String alias = aliases.nextElement();
3553             Certificate cert = ks.getCertificate(alias);
3554             if (cert != null) {
3555                 Principal subjectDN = ((X509Certificate)cert).getSubjectDN();
3556                 Vector<Certificate> vec = hash.get(subjectDN);






3557                 if (vec == null) {
3558                     vec = new Vector<Certificate>();
3559                     vec.addElement(cert);
3560                 } else {
3561                     if (!vec.contains(cert)) {
3562                         vec.addElement(cert);
3563                     }
3564                 }
3565                 hash.put(subjectDN, vec);
3566             }
3567         }
3568     }
3569 
3570     /**
3571      * Returns the issue time that's specified the -startdate option
3572      * @param s the value of -startdate option
3573      */
3574     private static Date getStartDate(String s) throws IOException {
3575         Calendar c = new GregorianCalendar();
3576         if (s != null) {
3577             IOException ioe = new IOException(
3578                     rb.getString("Illegal.startdate.value"));
3579             int len = s.length();
3580             if (len == 0) {
3581                 throw ioe;
3582             }


4138                         setExt(result, new Extension(oid, isCritical,
4139                                 new DerValue(DerValue.tag_OctetString, data)
4140                                         .toByteArray()));
4141                         break;
4142                     default:
4143                         throw new Exception(rb.getString(
4144                                 "Unknown.extension.type.") + extstr);
4145                 }
4146             }
4147             // always non-critical
4148             setExt(result, new SubjectKeyIdentifierExtension(
4149                     new KeyIdentifier(pkey).getIdentifier()));
4150             if (akey != null && !pkey.equals(akey)) {
4151                 setExt(result, new AuthorityKeyIdentifierExtension(
4152                                 new KeyIdentifier(akey), null, null));
4153             }
4154         } catch(IOException e) {
4155             throw new RuntimeException(e);
4156         }
4157         return result;



















































































4158     }
4159 
4160     /**
4161      * Prints the usage of this tool.
4162      */
4163     private void usage() {
4164         if (command != null) {
4165             System.err.println("keytool " + command +
4166                     rb.getString(".OPTION."));
4167             System.err.println();
4168             System.err.println(rb.getString(command.description));
4169             System.err.println();
4170             System.err.println(rb.getString("Options."));
4171             System.err.println();
4172 
4173             // Left and right sides of the options list. Both might
4174             // contain "\n" and span multiple lines
4175             String[] left = new String[command.options.length];
4176             String[] right = new String[command.options.length];
4177 




  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.tools.keytool;
  27 
  28 import java.io.*;
  29 import java.security.CodeSigner;
  30 import java.security.CryptoPrimitive;
  31 import java.security.KeyStore;
  32 import java.security.KeyStoreException;
  33 import java.security.MessageDigest;
  34 import java.security.Key;
  35 import java.security.PublicKey;
  36 import java.security.PrivateKey;
  37 import java.security.Signature;
  38 import java.security.Timestamp;
  39 import java.security.UnrecoverableEntryException;
  40 import java.security.UnrecoverableKeyException;
  41 import java.security.Principal;
  42 import java.security.cert.Certificate;
  43 import java.security.cert.CertificateFactory;
  44 import java.security.cert.CertStoreException;
  45 import java.security.cert.CRL;
  46 import java.security.cert.X509Certificate;
  47 import java.security.cert.CertificateException;
  48 import java.security.cert.URICertStoreParameters;
  49 
  50 


 140     private char[] storePassNew = null;
 141     private char[] keyPass = null;
 142     private char[] keyPassNew = null;
 143     private char[] newPass = null;
 144     private char[] destKeyPass = null;
 145     private char[] srckeyPass = null;
 146     private String ksfname = null;
 147     private File ksfile = null;
 148     private InputStream ksStream = null; // keystore stream
 149     private String sslserver = null;
 150     private String jarfile = null;
 151     private KeyStore keyStore = null;
 152     private boolean token = false;
 153     private boolean nullStream = false;
 154     private boolean kssave = false;
 155     private boolean noprompt = false;
 156     private boolean trustcacerts = false;
 157     private boolean protectedPath = false;
 158     private boolean srcprotectedPath = false;
 159     private boolean cacerts = false;
 160     private boolean nowarn = false;
 161     private CertificateFactory cf = null;
 162     private KeyStore caks = null; // "cacerts" keystore
 163     private char[] srcstorePass = null;
 164     private String srcstoretype = null;
 165     private Set<char[]> passwords = new HashSet<>();
 166     private String startDate = null;
 167 
 168     private List<String> ids = new ArrayList<>();   // used in GENCRL
 169     private List<String> v3ext = new ArrayList<>();
 170 
 171     // Warnings on weak algorithms
 172     private List<String> weakWarnings = new ArrayList<>();
 173 
 174     private static final DisabledAlgorithmConstraints DISABLED_CHECK =
 175             new DisabledAlgorithmConstraints(
 176                     DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
 177 
 178     private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
 179             .unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
 180 
 181     enum Command {
 182         CERTREQ("Generates.a.certificate.request",
 183             ALIAS, SIGALG, FILEOUT, KEYPASS, KEYSTORE, DNAME,
 184             STOREPASS, STORETYPE, PROVIDERNAME, ADDPROVIDER,
 185             PROVIDERCLASS, PROVIDERPATH, V, PROTECTED),
 186         CHANGEALIAS("Changes.an.entry.s.alias",
 187             ALIAS, DESTALIAS, KEYPASS, KEYSTORE, CACERTS, STOREPASS,
 188             STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
 189             PROVIDERPATH, V, PROTECTED),
 190         DELETE("Deletes.an.entry",
 191             ALIAS, KEYSTORE, CACERTS, STOREPASS, STORETYPE,
 192             PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
 193             PROVIDERPATH, V, PROTECTED),
 194         EXPORTCERT("Exports.certificate",
 195             RFC, ALIAS, FILEOUT, KEYSTORE, CACERTS, STOREPASS,
 196             STORETYPE, PROVIDERNAME, ADDPROVIDER, PROVIDERCLASS,
 197             PROVIDERPATH, V, PROTECTED),
 198         GENKEYPAIR("Generates.a.key.pair",
 199             ALIAS, KEYALG, KEYSIZE, SIGALG, DESTALIAS, DNAME,
 200             STARTDATE, EXT, VALIDITY, KEYPASS, KEYSTORE,


 346         STORETYPE("storetype", "<type>", "keystore.type"),
 347         TRUSTCACERTS("trustcacerts", null, "trust.certificates.from.cacerts"),
 348         V("v", null, "verbose.output"),
 349         VALIDITY("validity", "<days>", "validity.number.of.days");
 350 
 351         final String name, arg, description;
 352         Option(String name, String arg, String description) {
 353             this.name = name;
 354             this.arg = arg;
 355             this.description = description;
 356         }
 357         @Override
 358         public String toString() {
 359             return "-" + name;
 360         }
 361     };
 362 
 363     private static final String NONE = "NONE";
 364     private static final String P11KEYSTORE = "PKCS11";
 365     private static final String P12KEYSTORE = "PKCS12";
 366     private static final String keyAlias = "mykey";
 367 
 368     // for i18n
 369     private static final java.util.ResourceBundle rb =
 370         java.util.ResourceBundle.getBundle(
 371             "sun.security.tools.keytool.Resources");
 372     private static final Collator collator = Collator.getInstance();
 373     static {
 374         // this is for case insensitive string comparisons
 375         collator.setStrength(Collator.PRIMARY);
 376     };
 377 
 378     private Main() { }
 379 
 380     public static void main(String[] args) throws Exception {
 381         Main kt = new Main();
 382         kt.run(args, System.out);
 383     }
 384 
 385     private void run(String[] args, PrintStream out) throws Exception {
 386         try {
 387             args = parseArgs(args);
 388             if (command != null) {
 389                 doCommands(out);
 390             }
 391         } catch (Exception e) {
 392             System.out.println(rb.getString("keytool.error.") + e);
 393             if (verbose) {
 394                 e.printStackTrace(System.out);
 395             }
 396             if (!debug) {
 397                 System.exit(1);
 398             } else {
 399                 throw e;
 400             }
 401         } finally {
 402             printWeakWarningsWithoutNewLine();
 403             for (char[] pass : passwords) {
 404                 if (pass != null) {
 405                     Arrays.fill(pass, ' ');
 406                     pass = null;
 407                 }
 408             }
 409 
 410             if (ksStream != null) {
 411                 ksStream.close();
 412             }
 413         }
 414     }
 415 
 416     /**
 417      * Parse command line arguments.
 418      */
 419     String[] parseArgs(String[] args) throws Exception {
 420 
 421         int i=0;
 422         boolean help = args.length == 0;


 472              * Check modifiers
 473              */
 474             String modifier = null;
 475             int pos = flags.indexOf(':');
 476             if (pos > 0) {
 477                 modifier = flags.substring(pos+1);
 478                 flags = flags.substring(0, pos);
 479             }
 480 
 481             /*
 482              * command modes
 483              */
 484             Command c = Command.getCommand(flags);
 485 
 486             if (c != null) {
 487                 command = c;
 488             } else if (collator.compare(flags, "-help") == 0) {
 489                 help = true;
 490             } else if (collator.compare(flags, "-conf") == 0) {
 491                 i++;
 492             } else if (collator.compare(flags, "-nowarn") == 0) {
 493                 nowarn = true;
 494             } else if (collator.compare(flags, "-keystore") == 0) {
 495                 ksfname = args[++i];
 496                 if (new File(ksfname).getCanonicalPath().equals(
 497                         new File(KeyStoreUtil.getCacerts()).getCanonicalPath())) {
 498                     System.err.println(rb.getString("warning.cacerts.option"));
 499                 }
 500             } else if (collator.compare(flags, "-destkeystore") == 0) {
 501                 ksfname = args[++i];
 502             } else if (collator.compare(flags, "-cacerts") == 0) {
 503                 cacerts = true;
 504             } else if (collator.compare(flags, "-storepass") == 0 ||
 505                     collator.compare(flags, "-deststorepass") == 0) {
 506                 storePass = getPass(modifier, args[++i]);
 507                 passwords.add(storePass);
 508             } else if (collator.compare(flags, "-storetype") == 0 ||
 509                     collator.compare(flags, "-deststoretype") == 0) {
 510                 storetype = args[++i];
 511                 hasStoretypeOption = true;
 512             } else if (collator.compare(flags, "-srcstorepass") == 0) {
 513                 srcstorePass = getPass(modifier, args[++i]);


1150 
1151             doCloneEntry(alias, dest, true);  // Now everything can be cloned
1152             kssave = true;
1153         } else if (command == CHANGEALIAS) {
1154             if (alias == null) {
1155                 alias = keyAlias;
1156             }
1157             doCloneEntry(alias, dest, false);
1158             // in PKCS11, clone a PrivateKeyEntry will delete the old one
1159             if (keyStore.containsAlias(alias)) {
1160                 doDeleteEntry(alias);
1161             }
1162             kssave = true;
1163         } else if (command == KEYPASSWD) {
1164             keyPassNew = newPass;
1165             doChangeKeyPasswd(alias);
1166             kssave = true;
1167         } else if (command == LIST) {
1168             if (storePass == null
1169                     && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
1170                 printNoIntegrityWarning();
1171             }
1172 
1173             if (alias != null) {
1174                 doPrintEntry(null, alias, out);
1175             } else {
1176                 doPrintEntries(out);
1177             }
1178         } else if (command == PRINTCERT) {
1179             doPrintCert(out);
1180         } else if (command == SELFCERT) {
1181             doSelfCert(alias, dname, sigAlgName);
1182             kssave = true;
1183         } else if (command == STOREPASSWD) {
1184             storePassNew = newPass;
1185             if (storePassNew == null) {
1186                 storePassNew = getNewPasswd("keystore password", storePass);
1187             }
1188             kssave = true;
1189         } else if (command == GENCERT) {
1190             if (alias == null) {
1191                 alias = keyAlias;
1192             }
1193             InputStream inStream = System.in;
1194             if (infilename != null) {


1251                 } else {
1252                     ByteArrayOutputStream bout = new ByteArrayOutputStream();
1253                     keyStore.store(bout, pass);
1254                     try (FileOutputStream fout = new FileOutputStream(ksfname)) {
1255                         fout.write(bout.toByteArray());
1256                     }
1257                 }
1258             }
1259         }
1260     }
1261 
1262     /**
1263      * Generate a certificate: Read PKCS10 request from in, and print
1264      * certificate to out. Use alias as CA, sigAlgName as the signature
1265      * type.
1266      */
1267     private void doGenCert(String alias, String sigAlgName, InputStream in, PrintStream out)
1268             throws Exception {
1269 
1270 
1271         if (keyStore.containsAlias(alias) == false) {
1272             MessageFormat form = new MessageFormat
1273                     (rb.getString("Alias.alias.does.not.exist"));
1274             Object[] source = {alias};
1275             throw new Exception(form.format(source));
1276         }
1277         Certificate signerCert = keyStore.getCertificate(alias);
1278         byte[] encoded = signerCert.getEncoded();
1279         X509CertImpl signerCertImpl = new X509CertImpl(encoded);
1280         X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
1281                 X509CertImpl.NAME + "." + X509CertImpl.INFO);
1282         X500Name issuer = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." +
1283                                            X509CertInfo.DN_NAME);
1284 
1285         Date firstDate = getStartDate(startDate);
1286         Date lastDate = new Date();
1287         lastDate.setTime(firstDate.getTime() + validity*1000L*24L*60L*60L);
1288         CertificateValidity interval = new CertificateValidity(firstDate,
1289                                                                lastDate);
1290 
1291         PrivateKey privateKey =
1292                 (PrivateKey)recoverKey(alias, storePass, keyPass).fst;
1293         if (sigAlgName == null) {
1294             sigAlgName = getCompatibleSigAlgName(privateKey);
1295         }
1296         Signature signature = Signature.getInstance(sigAlgName);


1310         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
1311         boolean canRead = false;
1312         StringBuffer sb = new StringBuffer();
1313         while (true) {
1314             String s = reader.readLine();
1315             if (s == null) break;
1316             // OpenSSL does not use NEW
1317             //if (s.startsWith("-----BEGIN NEW CERTIFICATE REQUEST-----")) {
1318             if (s.startsWith("-----BEGIN") && s.indexOf("REQUEST") >= 0) {
1319                 canRead = true;
1320             //} else if (s.startsWith("-----END NEW CERTIFICATE REQUEST-----")) {
1321             } else if (s.startsWith("-----END") && s.indexOf("REQUEST") >= 0) {
1322                 break;
1323             } else if (canRead) {
1324                 sb.append(s);
1325             }
1326         }
1327         byte[] rawReq = Pem.decode(new String(sb));
1328         PKCS10 req = new PKCS10(rawReq);
1329 
1330         checkWeak(rb.getString("the.input"), req);
1331 
1332         info.set(X509CertInfo.KEY, new CertificateX509Key(req.getSubjectPublicKeyInfo()));
1333         info.set(X509CertInfo.SUBJECT,
1334                     dname==null?req.getSubjectName():new X500Name(dname));
1335         CertificateExtensions reqex = null;
1336         Iterator<PKCS10Attribute> attrs = req.getAttributes().getAttributes().iterator();
1337         while (attrs.hasNext()) {
1338             PKCS10Attribute attr = attrs.next();
1339             if (attr.getAttributeId().equals(PKCS9Attribute.EXTENSION_REQUEST_OID)) {
1340                 reqex = (CertificateExtensions)attr.getAttributeValue();
1341             }
1342         }
1343         CertificateExtensions ext = createV3Extensions(
1344                 reqex,
1345                 null,
1346                 v3ext,
1347                 req.getSubjectPublicKeyInfo(),
1348                 signerCert.getPublicKey());
1349         info.set(X509CertInfo.EXTENSIONS, ext);
1350         X509CertImpl cert = new X509CertImpl(info);
1351         cert.sign(privateKey, sigAlgName);
1352         dumpCert(cert, out);
1353         for (Certificate ca: keyStore.getCertificateChain(alias)) {
1354             if (ca instanceof X509Certificate) {
1355                 X509Certificate xca = (X509Certificate)ca;
1356                 if (!KeyStoreUtil.isSelfSigned(xca)) {
1357                     dumpCert(xca, out);
1358                 }
1359             }
1360         }
1361 
1362         checkWeak(rb.getString("the.issuer"), keyStore.getCertificateChain(alias));
1363         checkWeak(rb.getString("the.output"), cert);
1364     }
1365 
1366     private void doGenCRL(PrintStream out)
1367             throws Exception {
1368         if (ids == null) {
1369             throw new Exception("Must provide -id when -gencrl");
1370         }
1371         Certificate signerCert = keyStore.getCertificate(alias);
1372         byte[] encoded = signerCert.getEncoded();
1373         X509CertImpl signerCertImpl = new X509CertImpl(encoded);
1374         X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
1375                 X509CertImpl.NAME + "." + X509CertImpl.INFO);
1376         X500Name owner = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." +
1377                                                       X509CertInfo.DN_NAME);
1378 
1379         Date firstDate = getStartDate(startDate);
1380         Date lastDate = (Date) firstDate.clone();
1381         lastDate.setTime(lastDate.getTime() + validity*1000*24*60*60);
1382         CertificateValidity interval = new CertificateValidity(firstDate,
1383                                                                lastDate);


1394             String id = ids.get(i);
1395             int d = id.indexOf(':');
1396             if (d >= 0) {
1397                 CRLExtensions ext = new CRLExtensions();
1398                 ext.set("Reason", new CRLReasonCodeExtension(Integer.parseInt(id.substring(d+1))));
1399                 badCerts[i] = new X509CRLEntryImpl(new BigInteger(id.substring(0, d)),
1400                         firstDate, ext);
1401             } else {
1402                 badCerts[i] = new X509CRLEntryImpl(new BigInteger(ids.get(i)), firstDate);
1403             }
1404         }
1405         X509CRLImpl crl = new X509CRLImpl(owner, firstDate, lastDate, badCerts);
1406         crl.sign(privateKey, sigAlgName);
1407         if (rfc) {
1408             out.println("-----BEGIN X509 CRL-----");
1409             out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(crl.getEncodedInternal()));
1410             out.println("-----END X509 CRL-----");
1411         } else {
1412             out.write(crl.getEncodedInternal());
1413         }
1414         checkWeak(null, crl, privateKey);
1415     }
1416 
1417     /**
1418      * Creates a PKCS#10 cert signing request, corresponding to the
1419      * keys (and name) associated with a given alias.
1420      */
1421     private void doCertReq(String alias, String sigAlgName, PrintStream out)
1422         throws Exception
1423     {
1424         if (alias == null) {
1425             alias = keyAlias;
1426         }
1427 
1428         Pair<Key,char[]> objs = recoverKey(alias, storePass, keyPass);
1429         PrivateKey privKey = (PrivateKey)objs.fst;
1430         if (keyPass == null) {
1431             keyPass = objs.snd;
1432         }
1433 
1434         Certificate cert = keyStore.getCertificate(alias);


1441         PKCS10 request = new PKCS10(cert.getPublicKey());
1442         CertificateExtensions ext = createV3Extensions(null, null, v3ext, cert.getPublicKey(), null);
1443         // Attribute name is not significant
1444         request.getAttributes().setAttribute(X509CertInfo.EXTENSIONS,
1445                 new PKCS10Attribute(PKCS9Attribute.EXTENSION_REQUEST_OID, ext));
1446 
1447         // Construct a Signature object, so that we can sign the request
1448         if (sigAlgName == null) {
1449             sigAlgName = getCompatibleSigAlgName(privKey);
1450         }
1451 
1452         Signature signature = Signature.getInstance(sigAlgName);
1453         signature.initSign(privKey);
1454         X500Name subject = dname == null?
1455                 new X500Name(((X509Certificate)cert).getSubjectDN().toString()):
1456                 new X500Name(dname);
1457 
1458         // Sign the request and base-64 encode it
1459         request.encodeAndSign(subject, signature);
1460         request.print(out);
1461 
1462         checkWeak(null, request);
1463     }
1464 
1465     /**
1466      * Deletes an entry from the keystore.
1467      */
1468     private void doDeleteEntry(String alias) throws Exception {
1469         if (keyStore.containsAlias(alias) == false) {
1470             MessageFormat form = new MessageFormat
1471                 (rb.getString("Alias.alias.does.not.exist"));
1472             Object[] source = {alias};
1473             throw new Exception(form.format(source));
1474         }
1475         keyStore.deleteEntry(alias);
1476     }
1477 
1478     /**
1479      * Exports a certificate from the keystore.
1480      */
1481     private void doExportCert(String alias, PrintStream out)
1482         throws Exception
1483     {
1484         if (storePass == null
1485                 && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
1486             printNoIntegrityWarning();
1487         }
1488         if (alias == null) {
1489             alias = keyAlias;
1490         }
1491         if (keyStore.containsAlias(alias) == false) {
1492             MessageFormat form = new MessageFormat
1493                 (rb.getString("Alias.alias.does.not.exist"));
1494             Object[] source = {alias};
1495             throw new Exception(form.format(source));
1496         }
1497 
1498         X509Certificate cert = (X509Certificate)keyStore.getCertificate(alias);
1499         if (cert == null) {
1500             MessageFormat form = new MessageFormat
1501                 (rb.getString("Alias.alias.has.no.certificate"));
1502             Object[] source = {alias};
1503             throw new Exception(form.format(source));
1504         }
1505         dumpCert(cert, out);
1506         checkWeak(null, cert);
1507     }
1508 
1509     /**
1510      * Prompt the user for a keypass when generating a key entry.
1511      * @param alias the entry we will set password for
1512      * @param orig the original entry of doing a dup, null if generate new
1513      * @param origPass the password to copy from if user press ENTER
1514      */
1515     private char[] promptForKeyPass(String alias, String orig, char[] origPass) throws Exception{
1516         if (P12KEYSTORE.equalsIgnoreCase(storetype)) {
1517             return origPass;
1518         } else if (!token && !protectedPath) {
1519             // Prompt for key password
1520             int count;
1521             for (count = 0; count < 3; count++) {
1522                 MessageFormat form = new MessageFormat(rb.getString
1523                         ("Enter.key.password.for.alias."));
1524                 Object[] source = {alias};
1525                 System.err.println(form.format(source));
1526                 if (orig == null) {


1742 
1743         X509Certificate[] chain = new X509Certificate[1];
1744         chain[0] = keypair.getSelfCertificate(
1745                 x500Name, getStartDate(startDate), validity*24L*60L*60L, ext);
1746 
1747         if (verbose) {
1748             MessageFormat form = new MessageFormat(rb.getString
1749                 ("Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for"));
1750             Object[] source = {keysize,
1751                                 privKey.getAlgorithm(),
1752                                 chain[0].getSigAlgName(),
1753                                 validity,
1754                                 x500Name};
1755             System.err.println(form.format(source));
1756         }
1757 
1758         if (keyPass == null) {
1759             keyPass = promptForKeyPass(alias, null, storePass);
1760         }
1761         keyStore.setKeyEntry(alias, privKey, keyPass, chain);
1762 
1763         checkWeak(null, chain[0]);
1764     }
1765 
1766     /**
1767      * Clones an entry
1768      * @param orig original alias
1769      * @param dest destination alias
1770      * @changePassword if the password can be changed
1771      */
1772     private void doCloneEntry(String orig, String dest, boolean changePassword)
1773         throws Exception
1774     {
1775         if (orig == null) {
1776             orig = keyAlias;
1777         }
1778 
1779         if (keyStore.containsAlias(dest)) {
1780             MessageFormat form = new MessageFormat
1781                 (rb.getString("Destination.alias.dest.already.exists"));
1782             Object[] source = {dest};
1783             throw new Exception(form.format(source));


1825         }
1826         keyStore.setKeyEntry(alias, privKey, keyPassNew,
1827                              keyStore.getCertificateChain(alias));
1828     }
1829 
1830     /**
1831      * Imports a JDK 1.1-style identity database. We can only store one
1832      * certificate per identity, because we use the identity's name as the
1833      * alias (which references a keystore entry), and aliases must be unique.
1834      */
1835     private void doImportIdentityDatabase(InputStream in)
1836         throws Exception
1837     {
1838         System.err.println(rb.getString
1839             ("No.entries.from.identity.database.added"));
1840     }
1841 
1842     /**
1843      * Prints a single keystore entry.
1844      */
1845     private void doPrintEntry(String label, String alias, PrintStream out)
1846         throws Exception
1847     {
1848         if (keyStore.containsAlias(alias) == false) {
1849             MessageFormat form = new MessageFormat
1850                 (rb.getString("Alias.alias.does.not.exist"));
1851             Object[] source = {alias};
1852             throw new Exception(form.format(source));
1853         }
1854 
1855         if (verbose || rfc || debug) {
1856             MessageFormat form = new MessageFormat
1857                 (rb.getString("Alias.name.alias"));
1858             Object[] source = {alias};
1859             out.println(form.format(source));
1860 
1861             if (!token) {
1862                 form = new MessageFormat(rb.getString
1863                     ("Creation.date.keyStore.getCreationDate.alias."));
1864                 Object[] src = {keyStore.getCreationDate(alias)};
1865                 out.println(form.format(src));


1896             }
1897 
1898             // Get the chain
1899             Certificate[] chain = keyStore.getCertificateChain(alias);
1900             if (chain != null) {
1901                 if (verbose || rfc || debug) {
1902                     out.println(rb.getString
1903                         ("Certificate.chain.length.") + chain.length);
1904                     for (int i = 0; i < chain.length; i ++) {
1905                         MessageFormat form = new MessageFormat
1906                                 (rb.getString("Certificate.i.1."));
1907                         Object[] source = {(i + 1)};
1908                         out.println(form.format(source));
1909                         if (verbose && (chain[i] instanceof X509Certificate)) {
1910                             printX509Cert((X509Certificate)(chain[i]), out);
1911                         } else if (debug) {
1912                             out.println(chain[i].toString());
1913                         } else {
1914                             dumpCert(chain[i], out);
1915                         }
1916                         checkWeak(label, chain[i]);
1917                     }
1918                 } else {
1919                     // Print the digest of the user cert only
1920                     out.println
1921                         (rb.getString("Certificate.fingerprint.SHA.256.") +
1922                         getCertFingerPrint("SHA-256", chain[0]));
1923                     checkWeak(label, chain);
1924                 }
1925             }
1926         } else if (keyStore.entryInstanceOf(alias,
1927                 KeyStore.TrustedCertificateEntry.class)) {
1928             // We have a trusted certificate entry
1929             Certificate cert = keyStore.getCertificate(alias);
1930             Object[] source = {"trustedCertEntry"};
1931             String mf = new MessageFormat(
1932                     rb.getString("Entry.type.type.")).format(source) + "\n";
1933             if (verbose && (cert instanceof X509Certificate)) {
1934                 out.println(mf);
1935                 printX509Cert((X509Certificate)cert, out);
1936             } else if (rfc) {
1937                 out.println(mf);
1938                 dumpCert(cert, out);
1939             } else if (debug) {
1940                 out.println(cert.toString());
1941             } else {
1942                 out.println("trustedCertEntry, ");
1943                 out.println(rb.getString("Certificate.fingerprint.SHA.256.")
1944                             + getCertFingerPrint("SHA-256", cert));
1945             }
1946             checkWeak(label, cert);
1947         } else {
1948             out.println(rb.getString("Unknown.Entry.Type"));
1949         }
1950     }
1951 
1952     /**
1953      * Load the srckeystore from a stream, used in -importkeystore
1954      * @return the src KeyStore
1955      */
1956     KeyStore loadSourceKeyStore() throws Exception {
1957         boolean isPkcs11 = false;
1958 
1959         InputStream is = null;
1960         File srcksfile = null;
1961 
1962         if (P11KEYSTORE.equalsIgnoreCase(srcstoretype) ||
1963                 KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
1964             if (!NONE.equals(srcksfname)) {
1965                 System.err.println(MessageFormat.format(rb.getString
1966                     (".keystore.must.be.NONE.if.storetype.is.{0}"), srcstoretype));


2010             if (P12KEYSTORE.equalsIgnoreCase(srcstoretype)) {
2011                 if (srckeyPass != null && srcstorePass != null &&
2012                         !Arrays.equals(srcstorePass, srckeyPass)) {
2013                     MessageFormat form = new MessageFormat(rb.getString(
2014                         "Warning.Different.store.and.key.passwords.not.supported.for.PKCS12.KeyStores.Ignoring.user.specified.command.value."));
2015                     Object[] source = {"-srckeypass"};
2016                     System.err.println(form.format(source));
2017                     srckeyPass = srcstorePass;
2018                 }
2019             }
2020 
2021             store.load(is, srcstorePass);   // "is" already null in PKCS11
2022         } finally {
2023             if (is != null) {
2024                 is.close();
2025             }
2026         }
2027 
2028         if (srcstorePass == null
2029                 && !KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
2030             // anti refactoring, copied from printNoIntegrityWarning(),
2031             // but change 2 lines
2032             System.err.println();
2033             System.err.println(rb.getString
2034                 (".WARNING.WARNING.WARNING."));
2035             System.err.println(rb.getString
2036                 (".The.integrity.of.the.information.stored.in.the.srckeystore."));
2037             System.err.println(rb.getString
2038                 (".WARNING.WARNING.WARNING."));
2039             System.err.println();
2040         }
2041 
2042         return store;
2043     }
2044 
2045     /**
2046      * import all keys and certs from importkeystore.
2047      * keep alias unchanged if no name conflict, otherwise, prompt.
2048      * keep keypass unchanged for keys
2049      */
2050     private void doImportKeyStore() throws Exception {


2133             MessageFormat form = new MessageFormat(rb.getString(
2134                     "Problem.importing.entry.for.alias.alias.exception.Entry.for.alias.alias.not.imported."));
2135             System.err.println(form.format(source2));
2136             return 2;
2137         }
2138     }
2139 
2140     private void doImportKeyStoreAll(KeyStore srckeystore) throws Exception {
2141 
2142         int ok = 0;
2143         int count = srckeystore.size();
2144         for (Enumeration<String> e = srckeystore.aliases();
2145                                         e.hasMoreElements(); ) {
2146             String alias = e.nextElement();
2147             int result = doImportKeyStoreSingle(srckeystore, alias);
2148             if (result == 1) {
2149                 ok++;
2150                 Object[] source = {alias};
2151                 MessageFormat form = new MessageFormat(rb.getString("Entry.for.alias.alias.successfully.imported."));
2152                 System.err.println(form.format(source));
2153                 Certificate c = srckeystore.getCertificate(alias);
2154                 if (c != null) {
2155                     checkWeak(null, c);
2156                 }
2157             } else if (result == 2) {
2158                 if (!noprompt) {
2159                     String reply = getYesNoReply("Do you want to quit the import process? [no]:  ");
2160                     if ("YES".equals(reply)) {
2161                         break;
2162                     }
2163                 }
2164             }
2165         }
2166         Object[] source = {ok, count-ok};
2167         MessageFormat form = new MessageFormat(rb.getString(
2168                 "Import.command.completed.ok.entries.successfully.imported.fail.entries.failed.or.cancelled"));
2169         System.err.println(form.format(source));
2170     }
2171 
2172     /**
2173      * Prints all keystore entries.
2174      */
2175     private void doPrintEntries(PrintStream out)
2176         throws Exception
2177     {
2178         out.println(rb.getString("Keystore.type.") + keyStore.getType());
2179         out.println(rb.getString("Keystore.provider.") +
2180                 keyStore.getProvider().getName());
2181         out.println();
2182 
2183         MessageFormat form;
2184         form = (keyStore.size() == 1) ?
2185                 new MessageFormat(rb.getString
2186                         ("Your.keystore.contains.keyStore.size.entry")) :
2187                 new MessageFormat(rb.getString
2188                         ("Your.keystore.contains.keyStore.size.entries"));
2189         Object[] source = {keyStore.size()};
2190         out.println(form.format(source));
2191         out.println();
2192 
2193         for (Enumeration<String> e = keyStore.aliases();
2194                                         e.hasMoreElements(); ) {
2195             String alias = e.nextElement();
2196             doPrintEntry("<" + alias + ">", alias, out);
2197             if (verbose || rfc) {
2198                 out.println(rb.getString("NEWLINE"));
2199                 out.println(rb.getString
2200                         ("STAR"));
2201                 out.println(rb.getString
2202                         ("STARNN"));
2203             }
2204         }
2205     }
2206 
2207     private static <T> Iterable<T> e2i(final Enumeration<T> e) {
2208         return new Iterable<T>() {
2209             @Override
2210             public Iterator<T> iterator() {
2211                 return new Iterator<T>() {
2212                     @Override
2213                     public boolean hasNext() {
2214                         return e.hasMoreElements();
2215                     }
2216                     @Override


2322             Certificate cert = ks.getCertificate(s);
2323             if (cert instanceof X509Certificate) {
2324                 X509Certificate xcert = (X509Certificate)cert;
2325                 if (xcert.getSubjectX500Principal().equals(issuer)) {
2326                     try {
2327                         ((X509CRLImpl)crl).verify(cert.getPublicKey());
2328                         return s;
2329                     } catch (Exception e) {
2330                     }
2331                 }
2332             }
2333         }
2334         return null;
2335     }
2336 
2337     private void doPrintCRL(String src, PrintStream out)
2338             throws Exception {
2339         for (CRL crl: loadCRLs(src)) {
2340             printCRL(crl, out);
2341             String issuer = null;
2342             Certificate signer = null;
2343             if (caks != null) {
2344                 issuer = verifyCRL(caks, crl);
2345                 if (issuer != null) {
2346                     signer = caks.getCertificate(issuer);
2347                     out.printf(rb.getString(
2348                             "verified.by.s.in.s.weak"),
2349                             issuer,
2350                             "cacerts",
2351                             withWeak(signer.getPublicKey()));
2352                     out.println();
2353                 }
2354             }
2355             if (issuer == null && keyStore != null) {
2356                 issuer = verifyCRL(keyStore, crl);
2357                 if (issuer != null) {
2358                     signer = keyStore.getCertificate(issuer);
2359                     out.printf(rb.getString(
2360                             "verified.by.s.in.s.weak"),
2361                             issuer,
2362                             "keystore",
2363                             withWeak(signer.getPublicKey()));
2364                     out.println();
2365                 }
2366             }
2367             if (issuer == null) {
2368                 out.println(rb.getString
2369                         ("STAR"));
2370                 out.println(rb.getString
2371                         ("warning.not.verified.make.sure.keystore.is.correct"));
2372                 out.println(rb.getString
2373                         ("STARNN"));
2374             }
2375             checkWeak(null, crl, signer == null ? null : signer.getPublicKey());
2376         }
2377     }
2378 
2379     private void printCRL(CRL crl, PrintStream out)
2380             throws Exception {

2381         X509CRL xcrl = (X509CRL)crl;
2382         if (rfc) {
2383             out.println("-----BEGIN X509 CRL-----");
2384             out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(xcrl.getEncoded()));
2385             out.println("-----END X509 CRL-----");
2386         } else {
2387             // Hack: Inject "(weak)" into X509CRLImpl::toString.
2388             String s = xcrl.toString();
2389             String title = "Signature Algorithm: ";
2390             int pos = s.indexOf(title);
2391             int pos2 = s.indexOf(",", pos);
2392             if (pos > 0 && pos2 > 0) {
2393                 pos += title.length();
2394                 s = s.substring(0, pos)
2395                         + withWeak(s.substring(pos, pos2))
2396                         + s.substring(pos2);
2397             }
2398             out.println(s);
2399         }
2400     }
2401 
2402     private void doPrintCertReq(InputStream in, PrintStream out)
2403             throws Exception {
2404 
2405         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
2406         StringBuffer sb = new StringBuffer();
2407         boolean started = false;
2408         while (true) {
2409             String s = reader.readLine();
2410             if (s == null) break;
2411             if (!started) {
2412                 if (s.startsWith("-----")) {
2413                     started = true;
2414                 }
2415             } else {
2416                 if (s.startsWith("-----")) {
2417                     break;
2418                 }
2419                 sb.append(s);
2420             }
2421         }
2422         PKCS10 req = new PKCS10(Pem.decode(new String(sb)));
2423 
2424         PublicKey pkey = req.getSubjectPublicKeyInfo();
2425         out.printf(rb.getString("PKCS.10.with.weak"),
2426                 req.getSubjectName(),
2427                 pkey.getFormat(),
2428                 withWeak(pkey),
2429                 withWeak(req.getSigAlg()));
2430         for (PKCS10Attribute attr: req.getAttributes().getAttributes()) {
2431             ObjectIdentifier oid = attr.getAttributeId();
2432             if (oid.equals(PKCS9Attribute.EXTENSION_REQUEST_OID)) {
2433                 CertificateExtensions exts = (CertificateExtensions)attr.getAttributeValue();
2434                 if (exts != null) {
2435                     printExtensions(rb.getString("Extension.Request."), exts, out);
2436                 }
2437             } else {
2438                 out.println("Attribute: " + attr.getAttributeId());
2439                 PKCS9Attribute pkcs9Attr =
2440                         new PKCS9Attribute(attr.getAttributeId(),
2441                                            attr.getAttributeValue());
2442                 out.print(pkcs9Attr.getName() + ": ");
2443                 Object attrVal = attr.getAttributeValue();
2444                 out.println(attrVal instanceof String[] ?
2445                             Arrays.toString((String[]) attrVal) :
2446                             attrVal);
2447             }
2448         }
2449         if (debug) {
2450             out.println(req);   // Just to see more, say, public key length...
2451         }
2452         checkWeak(null, req);
2453     }
2454 
2455     /**
2456      * Reads a certificate (or certificate chain) and prints its contents in
2457      * a human readable format.
2458      */
2459     private void printCertFromStream(InputStream in, PrintStream out)
2460         throws Exception
2461     {
2462         Collection<? extends Certificate> c = null;
2463         try {
2464             c = cf.generateCertificates(in);
2465         } catch (CertificateException ce) {
2466             throw new Exception(rb.getString("Failed.to.parse.input"), ce);
2467         }
2468         if (c.isEmpty()) {
2469             throw new Exception(rb.getString("Empty.input"));
2470         }
2471         Certificate[] certs = c.toArray(new Certificate[c.size()]);
2472         for (int i=0; i<certs.length; i++) {
2473             X509Certificate x509Cert = null;
2474             try {
2475                 x509Cert = (X509Certificate)certs[i];
2476             } catch (ClassCastException cce) {
2477                 throw new Exception(rb.getString("Not.X.509.certificate"));
2478             }
2479             if (certs.length > 1) {
2480                 MessageFormat form = new MessageFormat
2481                         (rb.getString("Certificate.i.1."));
2482                 Object[] source = {i + 1};
2483                 out.println(form.format(source));
2484             }
2485             if (rfc)
2486                 dumpCert(x509Cert, out);
2487             else
2488                 printX509Cert(x509Cert, out);
2489             if (i < (certs.length-1)) {
2490                 out.println();
2491             }
2492             checkWeak(oneInMany(i, certs.length), x509Cert);
2493         }
2494     }
2495 
2496     private static String oneInMany(int i, int num) {
2497         if (num == 1) {
2498             return null;
2499         } else {
2500             return String.format(rb.getString("one.in.many"), i+1, num);
2501         }
2502     }
2503 
2504     private void doPrintCert(final PrintStream out) throws Exception {
2505         if (jarfile != null) {
2506             // reset "jdk.certpath.disabledAlgorithms" security property
2507             // to be able to read jars which were signed with weak algorithms
2508             Security.setProperty(DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS, "");
2509 
2510             JarFile jf = new JarFile(jarfile, true);
2511             Enumeration<JarEntry> entries = jf.entries();
2512             Set<CodeSigner> ss = new HashSet<>();
2513             byte[] buffer = new byte[8192];
2514             int pos = 0;
2515             while (entries.hasMoreElements()) {
2516                 JarEntry je = entries.nextElement();
2517                 try (InputStream is = jf.getInputStream(je)) {
2518                     while (is.read(buffer) != -1) {
2519                         // we just read. this will throw a SecurityException
2520                         // if a signature/digest check fails. This also
2521                         // populate the signers
2522                     }
2523                 }
2524                 CodeSigner[] signers = je.getCodeSigners();
2525                 if (signers != null) {
2526                     for (CodeSigner signer: signers) {
2527                         if (!ss.contains(signer)) {
2528                             ss.add(signer);
2529                             out.printf(rb.getString("Signer.d."), ++pos);
2530                             out.println();
2531                             out.println();
2532                             out.println(rb.getString("Signature."));
2533                             out.println();
2534 
2535                             List<? extends Certificate> certs
2536                                     = signer.getSignerCertPath().getCertificates();
2537                             int cc = 0;
2538                             for (Certificate cert: certs) {
2539                                 X509Certificate x = (X509Certificate)cert;
2540                                 if (rfc) {
2541                                     out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n");
2542                                     dumpCert(x, out);
2543                                 } else {
2544                                     printX509Cert(x, out);
2545                                 }
2546                                 out.println();
2547                                 checkWeak(oneInMany(cc++, certs.size()), x);
2548                             }
2549                             Timestamp ts = signer.getTimestamp();
2550                             if (ts != null) {
2551                                 out.println(rb.getString("Timestamp."));
2552                                 out.println();
2553                                 certs = ts.getSignerCertPath().getCertificates();
2554                                 cc = 0;
2555                                 for (Certificate cert: certs) {
2556                                     X509Certificate x = (X509Certificate)cert;
2557                                     if (rfc) {
2558                                         out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n");
2559                                         dumpCert(x, out);
2560                                     } else {
2561                                         printX509Cert(x, out);
2562                                     }
2563                                     out.println();
2564                                     checkWeak(oneInMany(cc++, certs.size()), x);
2565                                 }
2566                             }
2567                         }
2568                     }
2569                 }
2570             }
2571             jf.close();
2572             if (ss.isEmpty()) {
2573                 out.println(rb.getString("Not.a.signed.jar.file"));
2574             }
2575         } else if (sslserver != null) {
2576             CertStore cs = SSLServerCertStore.getInstance(new URI("https://" + sslserver));
2577             Collection<? extends Certificate> chain;
2578             try {
2579                 chain = cs.getCertificates(null);
2580                 if (chain.isEmpty()) {
2581                     // If the certs are not retrieved, we consider it an error
2582                     // even if the URL connection is successful.
2583                     throw new Exception(rb.getString(
2584                                         "No.certificate.from.the.SSL.server"));


2587                 if (cse.getCause() instanceof IOException) {
2588                     throw new Exception(rb.getString(
2589                                         "No.certificate.from.the.SSL.server"),
2590                                         cse.getCause());
2591                 } else {
2592                     throw cse;
2593                 }
2594             }
2595 
2596             int i = 0;
2597             for (Certificate cert : chain) {
2598                 try {
2599                     if (rfc) {
2600                         dumpCert(cert, out);
2601                     } else {
2602                         out.println("Certificate #" + i++);
2603                         out.println("====================================");
2604                         printX509Cert((X509Certificate)cert, out);
2605                         out.println();
2606                     }
2607                     checkWeak(oneInMany(i, chain.size()), cert);
2608                 } catch (Exception e) {
2609                     if (debug) {
2610                         e.printStackTrace();
2611                     }
2612                 }
2613             }
2614         } else {
2615             if (filename != null) {
2616                 try (FileInputStream inStream = new FileInputStream(filename)) {
2617                     printCertFromStream(inStream, out);
2618                 }
2619             } else {
2620                 printCertFromStream(System.in, out);
2621             }
2622         }
2623     }
2624     /**
2625      * Creates a self-signed certificate, and stores it as a single-element
2626      * certificate chain.
2627      */


2763             Object[] source = {alias};
2764             throw new Exception(form.format(source));
2765         }
2766 
2767         // Read the certificates in the reply
2768         Collection<? extends Certificate> c = cf.generateCertificates(in);
2769         if (c.isEmpty()) {
2770             throw new Exception(rb.getString("Reply.has.no.certificates"));
2771         }
2772         Certificate[] replyCerts = c.toArray(new Certificate[c.size()]);
2773         Certificate[] newChain;
2774         if (replyCerts.length == 1) {
2775             // single-cert reply
2776             newChain = establishCertChain(userCert, replyCerts[0]);
2777         } else {
2778             // cert-chain reply (e.g., PKCS#7)
2779             newChain = validateReply(alias, userCert, replyCerts);
2780         }
2781 
2782         // Now store the newly established chain in the keystore. The new
2783         // chain replaces the old one. The chain can be null if user chooses no.
2784         if (newChain != null) {
2785             keyStore.setKeyEntry(alias, privKey,
2786                                  (keyPass != null) ? keyPass : storePass,
2787                                  newChain);
2788             return true;
2789         } else {
2790             return false;
2791         }
2792     }
2793 
2794     /**
2795      * Imports a certificate and adds it to the list of trusted certificates.
2796      *
2797      * @return true if the certificate was added, otherwise false.
2798      */
2799     private boolean addTrustedCert(String alias, InputStream in)
2800         throws Exception
2801     {
2802         if (alias == null) {
2803             throw new Exception(rb.getString("Must.specify.alias"));
2804         }
2805         if (keyStore.containsAlias(alias)) {
2806             MessageFormat form = new MessageFormat(rb.getString
2807                 ("Certificate.not.imported.alias.alias.already.exists"));
2808             Object[] source = {alias};
2809             throw new Exception(form.format(source));
2810         }
2811 
2812         // Read the certificate
2813         X509Certificate cert = null;
2814         try {
2815             cert = (X509Certificate)cf.generateCertificate(in);
2816         } catch (ClassCastException | CertificateException ce) {
2817             throw new Exception(rb.getString("Input.not.an.X.509.certificate"));
2818         }
2819 
2820         if (noprompt) {
2821             keyStore.setCertificateEntry(alias, cert);
2822             checkWeak(null, cert);
2823             return true;
2824         }
2825 
2826         // if certificate is self-signed, make sure it verifies
2827         boolean selfSigned = false;
2828         if (KeyStoreUtil.isSelfSigned(cert)) {
2829             cert.verify(cert.getPublicKey());
2830             selfSigned = true;
2831         }
2832 





2833         // check if cert already exists in keystore
2834         String reply = null;
2835         String trustalias = keyStore.getCertificateAlias(cert);
2836         if (trustalias != null) {
2837             MessageFormat form = new MessageFormat(rb.getString
2838                 ("Certificate.already.exists.in.keystore.under.alias.trustalias."));
2839             Object[] source = {trustalias};
2840             System.err.println(form.format(source));
2841             checkWeak(null, cert);
2842             printWeakWarnings();
2843             reply = getYesNoReply
2844                 (rb.getString("Do.you.still.want.to.add.it.no."));
2845         } else if (selfSigned) {
2846             if (trustcacerts && (caks != null) &&
2847                     ((trustalias=caks.getCertificateAlias(cert)) != null)) {
2848                 MessageFormat form = new MessageFormat(rb.getString
2849                         ("Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias."));
2850                 Object[] source = {trustalias};
2851                 System.err.println(form.format(source));
2852                 checkWeak(null, cert);
2853                 printWeakWarnings();
2854                 reply = getYesNoReply
2855                         (rb.getString("Do.you.still.want.to.add.it.to.your.own.keystore.no."));
2856             }
2857             if (trustalias == null) {
2858                 // Print the cert and ask user if they really want to add
2859                 // it to their keystore
2860                 printX509Cert(cert, System.out);
2861                 checkWeak(null, cert);
2862                 printWeakWarnings();
2863                 reply = getYesNoReply
2864                         (rb.getString("Trust.this.certificate.no."));
2865             }
2866         }
2867         if (reply != null) {
2868             if ("YES".equals(reply)) {
2869                 keyStore.setCertificateEntry(alias, cert);
2870                 return true;
2871             } else {
2872                 return false;
2873             }
2874         }
2875 
2876         // Not found in this keystore and not self-signed
2877         // Try to establish trust chain
2878         try {
2879             Certificate[] chain = establishCertChain(null, cert);
2880             if (chain != null) {
2881                 keyStore.setCertificateEntry(alias, cert);
2882                 return true;
2883             }
2884         } catch (Exception e) {
2885             // Print the cert and ask user if they really want to add it to
2886             // their keystore
2887             printX509Cert(cert, System.out);
2888             checkWeak(null, cert);
2889             printWeakWarnings();
2890             reply = getYesNoReply
2891                 (rb.getString("Trust.this.certificate.no."));
2892             if ("YES".equals(reply)) {
2893                 keyStore.setCertificateEntry(alias, cert);
2894                 return true;
2895             } else {
2896                 return false;
2897             }
2898         }
2899 
2900         return false;
2901     }
2902 
2903     /**
2904      * Prompts user for new password. New password must be different from
2905      * old one.
2906      *
2907      * @param prompt the message that gets prompted on the screen
2908      * @param oldPasswd the current (i.e., old) password
2909      */


3008                         ("Enter.key.password.for.alias."));
3009                 Object[] source = {alias};
3010                 System.err.print(form.format(source));
3011             }
3012             System.err.flush();
3013             keyPass = Password.readPassword(System.in);
3014             passwords.add(keyPass);
3015             if (keyPass == null) {
3016                 keyPass = otherKeyPass;
3017             }
3018             count++;
3019         } while ((keyPass == null) && count < 3);
3020 
3021         if (keyPass == null) {
3022             throw new Exception(rb.getString("Too.many.failures.try.later"));
3023         }
3024 
3025         return keyPass;
3026     }
3027 
3028     private String withWeak(String alg) {
3029         if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, alg, null)) {
3030             return alg;
3031         } else {
3032             return String.format(rb.getString("with.weak"), alg);
3033         }
3034     }
3035 
3036     private String withWeak(PublicKey key) {
3037         if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
3038             return String.format(rb.getString("key.bit"),
3039                     KeyUtil.getKeySize(key), key.getAlgorithm());
3040         } else {
3041             return String.format(rb.getString("key.bit.weak"),
3042                     KeyUtil.getKeySize(key), key.getAlgorithm());
3043         }
3044     }
3045 
3046     /**
3047      * Prints a certificate in a human readable format.
3048      */
3049     private void printX509Cert(X509Certificate cert, PrintStream out)
3050         throws Exception
3051     {
3052 
3053         MessageFormat form = new MessageFormat
3054                 (rb.getString(".PATTERN.printX509Cert.with.weak"));
3055         PublicKey pkey = cert.getPublicKey();
3056         Object[] source = {cert.getSubjectDN().toString(),
3057                         cert.getIssuerDN().toString(),
3058                         cert.getSerialNumber().toString(16),
3059                         cert.getNotBefore().toString(),
3060                         cert.getNotAfter().toString(),
3061                         getCertFingerPrint("SHA-1", cert),
3062                         getCertFingerPrint("SHA-256", cert),
3063                         withWeak(cert.getSigAlgName()),
3064                         withWeak(pkey),
3065                         cert.getVersion()

3066                         };
3067         out.println(form.format(source));
3068 
3069         if (cert instanceof X509CertImpl) {
3070             X509CertImpl impl = (X509CertImpl)cert;
3071             X509CertInfo certInfo = (X509CertInfo)impl.get(X509CertImpl.NAME
3072                                                            + "." +
3073                                                            X509CertImpl.INFO);
3074             CertificateExtensions exts = (CertificateExtensions)
3075                     certInfo.get(X509CertInfo.EXTENSIONS);
3076             if (exts != null) {
3077                 printExtensions(rb.getString("Extensions."), exts, out);
3078             }
3079         }
3080     }
3081 
3082     private static void printExtensions(String title, CertificateExtensions exts, PrintStream out)
3083             throws Exception {
3084         int extnum = 0;
3085         Iterator<Extension> i1 = exts.getAllExtensions().iterator();


3373             }
3374         }
3375 
3376         return Pair.of(entry, pkey);
3377     }
3378     /**
3379      * Gets the requested finger print of the certificate.
3380      */
3381     private String getCertFingerPrint(String mdAlg, Certificate cert)
3382         throws Exception
3383     {
3384         byte[] encCertInfo = cert.getEncoded();
3385         MessageDigest md = MessageDigest.getInstance(mdAlg);
3386         byte[] digest = md.digest(encCertInfo);
3387         return toHexString(digest);
3388     }
3389 
3390     /**
3391      * Prints warning about missing integrity check.
3392      */
3393     private void printNoIntegrityWarning() {
3394         System.err.println();
3395         System.err.println(rb.getString
3396             (".WARNING.WARNING.WARNING."));
3397         System.err.println(rb.getString
3398             (".The.integrity.of.the.information.stored.in.your.keystore."));
3399         System.err.println(rb.getString
3400             (".WARNING.WARNING.WARNING."));
3401         System.err.println();
3402     }
3403 
3404     /**
3405      * Validates chain in certification reply, and returns the ordered
3406      * elements of the chain (with user certificate first, and root
3407      * certificate last in the array).
3408      *
3409      * @param alias the alias name
3410      * @param userCert the user certificate of the alias
3411      * @param replyCerts the chain provided in the reply
3412      */
3413     private Certificate[] validateReply(String alias,
3414                                         Certificate userCert,
3415                                         Certificate[] replyCerts)
3416         throws Exception
3417     {
3418 
3419         checkWeak(rb.getString("reply"), replyCerts);
3420 
3421         // order the certs in the reply (bottom-up).
3422         // we know that all certs in the reply are of type X.509, because
3423         // we parsed them using an X.509 certificate factory
3424         int i;
3425         PublicKey userPubKey = userCert.getPublicKey();
3426 
3427         // Remove duplicated certificates.
3428         HashSet<Certificate> nodup = new HashSet<>(Arrays.asList(replyCerts));
3429         replyCerts = nodup.toArray(new Certificate[nodup.size()]);
3430 
3431         for (i=0; i<replyCerts.length; i++) {
3432             if (userPubKey.equals(replyCerts[i].getPublicKey())) {
3433                 break;
3434             }
3435         }
3436         if (i == replyCerts.length) {
3437             MessageFormat form = new MessageFormat(rb.getString
3438                 ("Certificate.reply.does.not.contain.public.key.for.alias."));
3439             Object[] source = {alias};
3440             throw new Exception(form.format(source));


3464             }
3465         }
3466 
3467         if (noprompt) {
3468             return replyCerts;
3469         }
3470 
3471         // do we trust the cert at the top?
3472         Certificate topCert = replyCerts[replyCerts.length-1];
3473         Certificate root = getTrustedSigner(topCert, keyStore);
3474         if (root == null && trustcacerts && caks != null) {
3475             root = getTrustedSigner(topCert, caks);
3476         }
3477         if (root == null) {
3478             System.err.println();
3479             System.err.println
3480                     (rb.getString("Top.level.certificate.in.reply."));
3481             printX509Cert((X509Certificate)topCert, System.out);
3482             System.err.println();
3483             System.err.print(rb.getString(".is.not.trusted."));
3484             printWeakWarnings();
3485             String reply = getYesNoReply
3486                     (rb.getString("Install.reply.anyway.no."));
3487             if ("NO".equals(reply)) {
3488                 return null;
3489             }
3490         } else {
3491             if (root != topCert) {
3492                 // append the root CA cert to the chain
3493                 Certificate[] tmpCerts =
3494                     new Certificate[replyCerts.length+1];
3495                 System.arraycopy(replyCerts, 0, tmpCerts, 0,
3496                                  replyCerts.length);
3497                 tmpCerts[tmpCerts.length-1] = root;
3498                 replyCerts = tmpCerts;
3499                 checkWeak(rb.getString("root"), root);
3500             }
3501             if (!weakWarnings.isEmpty()) {
3502                 printWeakWarnings();
3503                 String reply = getYesNoReply
3504                         (rb.getString("Install.reply.anyway.no."));
3505                 if ("NO".equals(reply)) {
3506                     return null;
3507                 }
3508             }
3509         }
3510 
3511         return replyCerts;
3512     }
3513 
3514     /**
3515      * Establishes a certificate chain (using trusted certificates in the
3516      * keystore and cacerts), starting with the reply (certToVerify)
3517      * and ending at a self-signed certificate found in the keystore.
3518      *
3519      * @param userCert optional existing certificate, mostly likely be the
3520      *                 original self-signed cert created by -genkeypair.
3521      *                 It must have the same public key as certToVerify
3522      *                 but cannot be the same cert.
3523      * @param certToVerify the starting certificate to build the chain
3524      * @returns the established chain, might be null if user decides not
3525      */
3526     private Certificate[] establishCertChain(Certificate userCert,
3527                                              Certificate certToVerify)
3528         throws Exception
3529     {
3530         if (userCert != null) {
3531             // Make sure that the public key of the certificate reply matches
3532             // the original public key in the keystore
3533             PublicKey origPubKey = userCert.getPublicKey();
3534             PublicKey replyPubKey = certToVerify.getPublicKey();
3535             if (!origPubKey.equals(replyPubKey)) {
3536                 throw new Exception(rb.getString
3537                         ("Public.keys.in.reply.and.keystore.don.t.match"));
3538             }
3539 
3540             // If the two certs are identical, we're done: no need to import
3541             // anything
3542             if (certToVerify.equals(userCert)) {
3543                 throw new Exception(rb.getString
3544                         ("Certificate.reply.and.certificate.in.keystore.are.identical"));
3545             }
3546         }
3547 
3548         // Build a hash table of all certificates in the keystore.
3549         // Use the subject distinguished name as the key into the hash table.
3550         // All certificates associated with the same subject distinguished
3551         // name are stored in the same hash table entry as a vector.
3552         Hashtable<Principal, Vector<Pair<String,X509Certificate>>> certs = null;
3553         if (keyStore.size() > 0) {
3554             certs = new Hashtable<>(11);
3555             keystorecerts2Hashtable(keyStore, certs);
3556         }
3557         if (trustcacerts) {
3558             if (caks!=null && caks.size()>0) {
3559                 if (certs == null) {
3560                     certs = new Hashtable<>(11);
3561                 }
3562                 keystorecerts2Hashtable(caks, certs);
3563             }
3564         }
3565 
3566         // start building chain
3567         Vector<Pair<String,X509Certificate>> chain = new Vector<>(2);
3568         if (buildChain(
3569                 new Pair<>(rb.getString("the.input"),
3570                            (X509Certificate) certToVerify),
3571                 chain, certs)) {
3572             for (Pair<String,X509Certificate> p : chain) {
3573                 checkWeak(p.fst, p.snd);
3574             }
3575             if (!weakWarnings.isEmpty() && !noprompt) {
3576                 printWeakWarnings();
3577                 String reply = getYesNoReply
3578                         (rb.getString("Trust.this.certificate.no."));
3579                 if (!"YES".equals(reply)) {
3580                     return null;
3581                 }
3582 
3583             }
3584             Certificate[] newChain =
3585                     new Certificate[chain.size()];
3586             // buildChain() returns chain with self-signed root-cert first and
3587             // user-cert last, so we need to invert the chain before we store
3588             // it
3589             int j=0;
3590             for (int i=chain.size()-1; i>=0; i--) {
3591                 newChain[j] = chain.elementAt(i).snd;
3592                 j++;
3593             }
3594             return newChain;
3595         } else {
3596             throw new Exception
3597                 (rb.getString("Failed.to.establish.chain.from.reply"));
3598         }
3599     }
3600 
3601     /**
3602      * Recursively tries to establish chain from pool of certs starting from
3603      * certToVerify until a self-signed cert is found, and fill the certs found
3604      * into chain. Each cert in the chain signs the next one.
3605      *
3606      * This method is able to recover from an error, say, if certToVerify
3607      * is signed by certA but certA has no issuer in certs and itself is not
3608      * self-signed, the method can try another certB that also signs
3609      * certToVerify and look for signer of certB, etc, etc.
3610      *
3611      * Each cert in chain comes with a label showing its origin. The label is
3612      * used in the warning message when the cert is considered a risk.
3613      *
3614      * @param certToVerify the cert that needs to be verified.
3615      * @param chain the chain that's being built.
3616      * @param certs the pool of trusted certs
3617      *
3618      * @return true if successful, false otherwise.
3619      */
3620     private boolean buildChain(Pair<String,X509Certificate> certToVerify,
3621             Vector<Pair<String,X509Certificate>> chain,
3622             Hashtable<Principal, Vector<Pair<String,X509Certificate>>> certs) {
3623         if (KeyStoreUtil.isSelfSigned(certToVerify.snd)) {

3624             // reached self-signed root cert;
3625             // no verification needed because it's trusted.
3626             chain.addElement(certToVerify);
3627             return true;
3628         }
3629 
3630         Principal issuer = certToVerify.snd.getIssuerDN();
3631 
3632         // Get the issuer's certificate(s)
3633         Vector<Pair<String,X509Certificate>> vec = certs.get(issuer);
3634         if (vec == null) {
3635             return false;
3636         }
3637 
3638         // Try out each certificate in the vector, until we find one
3639         // whose public key verifies the signature of the certificate
3640         // in question.
3641         for (Enumeration<Pair<String,X509Certificate>> issuerCerts = vec.elements();
3642                 issuerCerts.hasMoreElements(); ) {
3643             Pair<String,X509Certificate> issuerCert = issuerCerts.nextElement();
3644             PublicKey issuerPubKey = issuerCert.snd.getPublicKey();

3645             try {
3646                 certToVerify.snd.verify(issuerPubKey);
3647             } catch (Exception e) {
3648                 continue;
3649             }
3650             if (buildChain(issuerCert, chain, certs)) {
3651                 chain.addElement(certToVerify);
3652                 return true;
3653             }
3654         }
3655         return false;
3656     }
3657 
3658     /**
3659      * Prompts user for yes/no decision.
3660      *
3661      * @return the user's decision, can only be "YES" or "NO"
3662      */
3663     private String getYesNoReply(String prompt)
3664         throws IOException
3665     {
3666         String reply = null;


3676                                         (System.in))).readLine();
3677             if (reply == null ||
3678                 collator.compare(reply, "") == 0 ||
3679                 collator.compare(reply, rb.getString("n")) == 0 ||
3680                 collator.compare(reply, rb.getString("no")) == 0) {
3681                 reply = "NO";
3682             } else if (collator.compare(reply, rb.getString("y")) == 0 ||
3683                        collator.compare(reply, rb.getString("yes")) == 0) {
3684                 reply = "YES";
3685             } else {
3686                 System.err.println(rb.getString("Wrong.answer.try.again"));
3687                 reply = null;
3688             }
3689         } while (reply == null);
3690         return reply;
3691     }
3692 
3693     /**
3694      * Stores the (leaf) certificates of a keystore in a hashtable.
3695      * All certs belonging to the same CA are stored in a vector that
3696      * in turn is stored in the hashtable, keyed by the CA's subject DN.
3697      * Each cert comes with a string label that shows its origin and alias.
3698      */
3699     private void keystorecerts2Hashtable(KeyStore ks,
3700                 Hashtable<Principal, Vector<Pair<String,X509Certificate>>> hash)
3701         throws Exception {
3702 
3703         for (Enumeration<String> aliases = ks.aliases();
3704                                         aliases.hasMoreElements(); ) {
3705             String alias = aliases.nextElement();
3706             Certificate cert = ks.getCertificate(alias);
3707             if (cert != null) {
3708                 Principal subjectDN = ((X509Certificate)cert).getSubjectDN();
3709                 Pair<String,X509Certificate> pair = new Pair<>(
3710                         ks == caks ?
3711                                 (String.format(rb.getString("alias.in.cacerts"),
3712                                         alias)) :
3713                                 ("<" + alias + ">"),
3714                         (X509Certificate)cert);
3715                 Vector<Pair<String,X509Certificate>> vec = hash.get(subjectDN);
3716                 if (vec == null) {
3717                     vec = new Vector<>();
3718                     vec.addElement(pair);
3719                 } else {
3720                     if (!vec.contains(pair)) {
3721                         vec.addElement(pair);
3722                     }
3723                 }
3724                 hash.put(subjectDN, vec);
3725             }
3726         }
3727     }
3728 
3729     /**
3730      * Returns the issue time that's specified the -startdate option
3731      * @param s the value of -startdate option
3732      */
3733     private static Date getStartDate(String s) throws IOException {
3734         Calendar c = new GregorianCalendar();
3735         if (s != null) {
3736             IOException ioe = new IOException(
3737                     rb.getString("Illegal.startdate.value"));
3738             int len = s.length();
3739             if (len == 0) {
3740                 throw ioe;
3741             }


4297                         setExt(result, new Extension(oid, isCritical,
4298                                 new DerValue(DerValue.tag_OctetString, data)
4299                                         .toByteArray()));
4300                         break;
4301                     default:
4302                         throw new Exception(rb.getString(
4303                                 "Unknown.extension.type.") + extstr);
4304                 }
4305             }
4306             // always non-critical
4307             setExt(result, new SubjectKeyIdentifierExtension(
4308                     new KeyIdentifier(pkey).getIdentifier()));
4309             if (akey != null && !pkey.equals(akey)) {
4310                 setExt(result, new AuthorityKeyIdentifierExtension(
4311                                 new KeyIdentifier(akey), null, null));
4312             }
4313         } catch(IOException e) {
4314             throw new RuntimeException(e);
4315         }
4316         return result;
4317     }
4318 
4319     private void checkWeak(String label, String sigAlg, Key key) {
4320 
4321         if (!DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, sigAlg, null)) {
4322             if (label == null) {
4323                 weakWarnings.add(String.format(
4324                         rb.getString("sigalg.risk"), sigAlg));
4325             } else {
4326                 weakWarnings.add(String.format(
4327                         rb.getString("whose.sigalg.risk"), label, sigAlg));
4328             }
4329         }
4330         if (key != null && !DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
4331             if (label == null) {
4332                 weakWarnings.add(String.format(
4333                         rb.getString("key.risk"),
4334                         String.format(rb.getString("key.bit"),
4335                                 KeyUtil.getKeySize(key), key.getAlgorithm())));
4336             } else {
4337                 weakWarnings.add(String.format(
4338                         rb.getString("whose.key.risk"),
4339                         label,
4340                         String.format(rb.getString("key.bit"),
4341                                 KeyUtil.getKeySize(key), key.getAlgorithm())));
4342             }
4343         }
4344     }
4345 
4346     private void checkWeak(String label, Certificate[] certs) {
4347         for (int i = 0; i < certs.length; i++) {
4348             Certificate cert = certs[i];
4349             if (cert instanceof X509Certificate) {
4350                 X509Certificate xc = (X509Certificate)cert;
4351                 String fullLabel = label;
4352                 if (certs.length > 1) {
4353                     fullLabel = oneInMany(i, certs.length);
4354                     if (label != null) {
4355                         fullLabel = String.format(rb.getString("label.which"), label, fullLabel);
4356                     }
4357                 }
4358                 checkWeak(fullLabel, xc.getSigAlgName(), xc.getPublicKey());
4359             }
4360         }
4361     }
4362 
4363     private void checkWeak(String label, Certificate cert) {
4364         if (cert instanceof X509Certificate) {
4365             X509Certificate xc = (X509Certificate)cert;
4366             checkWeak(label, xc.getSigAlgName(), xc.getPublicKey());
4367         }
4368     }
4369 
4370     private void checkWeak(String label, PKCS10 p10) {
4371         checkWeak(label, p10.getSigAlg(), p10.getSubjectPublicKeyInfo());
4372     }
4373 
4374     private void checkWeak(String label, CRL crl, Key key) {
4375         if (crl instanceof X509CRLImpl) {
4376             X509CRLImpl impl = (X509CRLImpl)crl;
4377             checkWeak(label, impl.getSigAlgName(), key);
4378         }
4379     }
4380 
4381     private void printWeakWarningsWithoutNewLine() {
4382         if (!weakWarnings.isEmpty() && !nowarn) {
4383             System.err.println("\nWarning:");
4384             for (String warning : weakWarnings) {
4385                 System.err.println(warning);
4386             }
4387         }
4388         weakWarnings.clear();
4389     }
4390 
4391     private void printWeakWarnings() {
4392         if (!weakWarnings.isEmpty() && !nowarn) {
4393             System.err.println("\nWarning:");
4394             for (String warning : weakWarnings) {
4395                 System.err.println(warning);
4396             }
4397             System.err.println();
4398         }
4399         weakWarnings.clear();
4400     }
4401 
4402     /**
4403      * Prints the usage of this tool.
4404      */
4405     private void usage() {
4406         if (command != null) {
4407             System.err.println("keytool " + command +
4408                     rb.getString(".OPTION."));
4409             System.err.println();
4410             System.err.println(rb.getString(command.description));
4411             System.err.println();
4412             System.err.println(rb.getString("Options."));
4413             System.err.println();
4414 
4415             // Left and right sides of the options list. Both might
4416             // contain "\n" and span multiple lines
4417             String[] left = new String[command.options.length];
4418             String[] right = new String[command.options.length];
4419 


< prev index next >