< prev index next >

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

Print this page
rev 12520 : 8029659: Keytool, print key algorithm of certificate or key entry
Reviewed-by: xuelei
rev 12521 : 8057810: New defaults for DSA keys in jarsigner and keytool
Reviewed-by: coffeys, valeriep
Contributed-by: prasadarao.koppula@oracle.com
rev 12532 : 8171319: keytool should print out warnings when reading or generating cert/cert req using weak algorithms
Reviewed-by: coffeys
rev 12537 : 8177569: keytool should not warn if signature algorithm used in cacerts is weak
Reviewed-by: mullan
rev 12543 : 8181048: Refactor existing providers to refer to the same constants for default values for key length
Reviewed-by: mullan, ahgross
rev 12549 : 8182879: Add warnings to keytool when using JKS and JCEKS
Reviewed-by: mullan, weijun
rev 12558 : 8186503: sun/security/tools/jarsigner/DefaultSigalg.java failed after backport to JDK 6/7/8
Reviewed-by: bgopularam
   1 /*
   2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  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.Security;
  37 import java.security.Signature;
  38 import java.security.Timestamp;
  39 import java.security.UnrecoverableEntryException;
  40 import java.security.UnrecoverableKeyException;
  41 import java.security.NoSuchAlgorithmException;
  42 import java.security.Principal;
  43 import java.security.Provider;
  44 import java.security.cert.Certificate;
  45 import java.security.cert.CertificateFactory;
  46 import java.security.cert.CertStoreException;
  47 import java.security.cert.CRL;
  48 import java.security.cert.X509Certificate;
  49 import java.security.cert.CertificateException;
  50 import java.text.Collator;
  51 import java.text.MessageFormat;
  52 import java.util.*;
  53 import java.util.jar.JarEntry;
  54 import java.util.jar.JarFile;
  55 import java.lang.reflect.Constructor;
  56 import java.math.BigInteger;
  57 import java.net.URI;
  58 import java.net.URL;
  59 import java.net.URLClassLoader;
  60 import java.security.cert.CertStore;
  61 
  62 import java.security.cert.X509CRL;
  63 import java.security.cert.X509CRLEntry;
  64 import java.security.cert.X509CRLSelector;
  65 import javax.security.auth.x500.X500Principal;
  66 import java.util.Base64;



  67 import sun.security.util.ObjectIdentifier;
  68 import sun.security.pkcs10.PKCS10;
  69 import sun.security.pkcs10.PKCS10Attribute;
  70 import sun.security.provider.X509Factory;
  71 import sun.security.provider.certpath.CertStoreHelper;
  72 import sun.security.util.Password;

  73 import javax.crypto.KeyGenerator;
  74 import javax.crypto.SecretKey;
  75 import javax.crypto.SecretKeyFactory;
  76 import javax.crypto.spec.PBEKeySpec;
  77 
  78 import sun.security.pkcs.PKCS9Attribute;
  79 import sun.security.tools.KeyStoreUtil;
  80 import sun.security.tools.PathList;
  81 import sun.security.util.DerValue;
  82 import sun.security.util.Pem;
  83 import sun.security.x509.*;
  84 
  85 import static java.security.KeyStore.*;
  86 import static sun.security.tools.keytool.Main.Command.*;
  87 import static sun.security.tools.keytool.Main.Option.*;
  88 
  89 /**
  90  * This tool manages keystores.
  91  *
  92  * @author Jan Luehe


 130     private String providerName = null;
 131     private String pathlist = null;
 132     private char[] storePass = null;
 133     private char[] storePassNew = null;
 134     private char[] keyPass = null;
 135     private char[] keyPassNew = null;
 136     private char[] newPass = null;
 137     private char[] destKeyPass = null;
 138     private char[] srckeyPass = null;
 139     private String ksfname = null;
 140     private File ksfile = null;
 141     private InputStream ksStream = null; // keystore stream
 142     private String sslserver = null;
 143     private String jarfile = null;
 144     private KeyStore keyStore = null;
 145     private boolean token = false;
 146     private boolean nullStream = false;
 147     private boolean kssave = false;
 148     private boolean noprompt = false;
 149     private boolean trustcacerts = false;

 150     private boolean protectedPath = false;
 151     private boolean srcprotectedPath = false;
 152     private CertificateFactory cf = null;
 153     private KeyStore caks = null; // "cacerts" keystore
 154     private char[] srcstorePass = null;
 155     private String srcstoretype = null;
 156     private Set<char[]> passwords = new HashSet<>();
 157     private String startDate = null;
 158 
 159     private List<String> ids = new ArrayList<>();   // used in GENCRL
 160     private List<String> v3ext = new ArrayList<>();
 161 















 162     enum Command {
 163         CERTREQ("Generates.a.certificate.request",
 164             ALIAS, SIGALG, FILEOUT, KEYPASS, KEYSTORE, DNAME,
 165             STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS,
 166             PROVIDERARG, PROVIDERPATH, V, PROTECTED),
 167         CHANGEALIAS("Changes.an.entry.s.alias",
 168             ALIAS, DESTALIAS, KEYPASS, KEYSTORE, STOREPASS,
 169             STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
 170             PROVIDERPATH, V, PROTECTED),
 171         DELETE("Deletes.an.entry",
 172             ALIAS, KEYSTORE, STOREPASS, STORETYPE,
 173             PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
 174             PROVIDERPATH, V, PROTECTED),
 175         EXPORTCERT("Exports.certificate",
 176             RFC, ALIAS, FILEOUT, KEYSTORE, STOREPASS,
 177             STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
 178             PROVIDERPATH, V, PROTECTED),
 179         GENKEYPAIR("Generates.a.key.pair",
 180             ALIAS, KEYALG, KEYSIZE, SIGALG, DESTALIAS, DNAME,
 181             STARTDATE, EXT, VALIDITY, KEYPASS, KEYSTORE,


 300         V("v", null, "verbose.output"),
 301         VALIDITY("validity", "<valDays>", "validity.number.of.days");
 302 
 303         final String name, arg, description;
 304         Option(String name, String arg, String description) {
 305             this.name = name;
 306             this.arg = arg;
 307             this.description = description;
 308         }
 309         @Override
 310         public String toString() {
 311             return "-" + name;
 312         }
 313     };
 314 
 315     private static final Class<?>[] PARAM_STRING = { String.class };
 316 
 317     private static final String NONE = "NONE";
 318     private static final String P11KEYSTORE = "PKCS11";
 319     private static final String P12KEYSTORE = "PKCS12";
 320     private final String keyAlias = "mykey";
 321 
 322     // for i18n
 323     private static final java.util.ResourceBundle rb =
 324         java.util.ResourceBundle.getBundle(
 325             "sun.security.tools.keytool.Resources");
 326     private static final Collator collator = Collator.getInstance();
 327     static {
 328         // this is for case insensitive string comparisons
 329         collator.setStrength(Collator.PRIMARY);
 330     };
 331 
 332     private Main() { }
 333 
 334     public static void main(String[] args) throws Exception {
 335         Main kt = new Main();
 336         kt.run(args, System.out);
 337     }
 338 
 339     private void run(String[] args, PrintStream out) throws Exception {
 340         try {
 341             parseArgs(args);
 342             if (command != null) {
 343                 doCommands(out);
 344             }
 345         } catch (Exception e) {
 346             System.out.println(rb.getString("keytool.error.") + e);
 347             if (verbose) {
 348                 e.printStackTrace(System.out);
 349             }
 350             if (!debug) {
 351                 System.exit(1);
 352             } else {
 353                 throw e;
 354             }
 355         } finally {

 356             for (char[] pass : passwords) {
 357                 if (pass != null) {
 358                     Arrays.fill(pass, ' ');
 359                     pass = null;
 360                 }
 361             }
 362 
 363             if (ksStream != null) {
 364                 ksStream.close();
 365             }
 366         }
 367     }
 368 
 369     /**
 370      * Parse command line arguments.
 371      */
 372     void parseArgs(String[] args) {
 373 
 374         int i=0;
 375         boolean help = args.length == 0;


 403              */
 404             boolean isCommand = false;
 405             for (Command c: Command.values()) {
 406                 if (collator.compare(flags, c.toString()) == 0) {
 407                     command = c;
 408                     isCommand = true;
 409                     break;
 410                 }
 411             }
 412 
 413             if (isCommand) {
 414                 // already recognized as a command
 415             } else if (collator.compare(flags, "-export") == 0) {
 416                 command = EXPORTCERT;
 417             } else if (collator.compare(flags, "-genkey") == 0) {
 418                 command = GENKEYPAIR;
 419             } else if (collator.compare(flags, "-import") == 0) {
 420                 command = IMPORTCERT;
 421             } else if (collator.compare(flags, "-importpassword") == 0) {
 422                 command = IMPORTPASS;
 423             }
 424             /*
 425              * Help
 426              */
 427             else if (collator.compare(flags, "-help") == 0) {
 428                 help = true;


 429             }
 430 
 431             /*
 432              * specifiers
 433              */
 434             else if (collator.compare(flags, "-keystore") == 0 ||
 435                     collator.compare(flags, "-destkeystore") == 0) {
 436                 ksfname = args[++i];
 437             } else if (collator.compare(flags, "-storepass") == 0 ||
 438                     collator.compare(flags, "-deststorepass") == 0) {
 439                 storePass = getPass(modifier, args[++i]);
 440                 passwords.add(storePass);
 441             } else if (collator.compare(flags, "-storetype") == 0 ||
 442                     collator.compare(flags, "-deststoretype") == 0) {
 443                 storetype = args[++i];
 444             } else if (collator.compare(flags, "-srcstorepass") == 0) {
 445                 srcstorePass = getPass(modifier, args[++i]);
 446                 passwords.add(srcstorePass);
 447             } else if (collator.compare(flags, "-srcstoretype") == 0) {
 448                 srcstoretype = args[++i];


 696         if (command == LIST && verbose && rfc) {
 697             System.err.println(rb.getString
 698                 ("Must.not.specify.both.v.and.rfc.with.list.command"));
 699             tinyHelp();
 700         }
 701 
 702         // Make sure provided passwords are at least 6 characters long
 703         if (command == GENKEYPAIR && keyPass!=null && keyPass.length < 6) {
 704             throw new Exception(rb.getString
 705                 ("Key.password.must.be.at.least.6.characters"));
 706         }
 707         if (newPass != null && newPass.length < 6) {
 708             throw new Exception(rb.getString
 709                 ("New.password.must.be.at.least.6.characters"));
 710         }
 711         if (destKeyPass != null && destKeyPass.length < 6) {
 712             throw new Exception(rb.getString
 713                 ("New.password.must.be.at.least.6.characters"));
 714         }
 715 



















 716         // Check if keystore exists.
 717         // If no keystore has been specified at the command line, try to use
 718         // the default, which is located in $HOME/.keystore.
 719         // If the command is "genkey", "identitydb", "import", or "printcert",
 720         // it is OK not to have a keystore.
 721         if (isKeyStoreRelated(command)) {
 722             if (ksfname == null) {
 723                 ksfname = System.getProperty("user.home") + File.separator
 724                     + ".keystore";
 725             }
 726 
 727             if (!nullStream) {


 728                 try {
 729                     ksfile = new File(ksfname);
 730                     // Check if keystore file is empty
 731                     if (ksfile.exists() && ksfile.length() == 0) {
 732                         throw new Exception(rb.getString
 733                         ("Keystore.file.exists.but.is.empty.") + ksfname);
 734                     }
 735                     ksStream = new FileInputStream(ksfile);
 736                 } catch (FileNotFoundException e) {
 737                     if (command != GENKEYPAIR &&
 738                         command != GENSECKEY &&
 739                         command != IDENTITYDB &&
 740                         command != IMPORTCERT &&
 741                         command != IMPORTPASS &&
 742                         command != IMPORTKEYSTORE &&
 743                         command != PRINTCRL) {
 744                         throw new Exception(rb.getString
 745                                 ("Keystore.file.does.not.exist.") + ksfname);
 746                     }
 747                 }
 748             }
 749         }
 750 
 751         if ((command == KEYCLONE || command == CHANGEALIAS)
 752                 && dest == null) {
 753             dest = getAlias("destination");
 754             if ("".equals(dest)) {
 755                 throw new Exception(rb.getString
 756                         ("Must.specify.destination.alias"));
 757             }
 758         }
 759 
 760         if (command == DELETE && alias == null) {
 761             alias = getAlias(null);
 762             if ("".equals(alias)) {
 763                 throw new Exception(rb.getString("Must.specify.alias"));
 764             }
 765         }
 766 
 767         // Create new keystore
 768         if (providerName == null) {
 769             keyStore = KeyStore.getInstance(storetype);


 775          * Load the keystore data.
 776          *
 777          * At this point, it's OK if no keystore password has been provided.
 778          * We want to make sure that we can load the keystore data, i.e.,
 779          * the keystore data has the right format. If we cannot load the
 780          * keystore, why bother asking the user for his or her password?
 781          * Only if we were able to load the keystore, and no keystore
 782          * password has been provided, will we prompt the user for the
 783          * keystore password to verify the keystore integrity.
 784          * This means that the keystore is loaded twice: first load operation
 785          * checks the keystore format, second load operation verifies the
 786          * keystore integrity.
 787          *
 788          * If the keystore password has already been provided (at the
 789          * command line), however, the keystore is loaded only once, and the
 790          * keystore format and integrity are checked "at the same time".
 791          *
 792          * Null stream keystores are loaded later.
 793          */
 794         if (!nullStream) {



 795             keyStore.load(ksStream, storePass);

 796             if (ksStream != null) {
 797                 ksStream.close();
 798             }
 799         }
 800 
 801         // All commands that create or modify the keystore require a keystore
 802         // password.
 803 
 804         if (nullStream && storePass != null) {
 805             keyStore.load(null, storePass);
 806         } else if (!nullStream && storePass != null) {
 807             // If we are creating a new non nullStream-based keystore,
 808             // insist that the password be at least 6 characters
 809             if (ksStream == null && storePass.length < 6) {
 810                 throw new Exception(rb.getString
 811                         ("Keystore.password.must.be.at.least.6.characters"));
 812             }
 813         } else if (storePass == null) {
 814 
 815             // only prompt if (protectedPath == false)


 903                 keyPass = storePass;
 904             }
 905             if (newPass != null && !Arrays.equals(storePass, newPass)) {
 906                 Object[] source = {"-new"};
 907                 System.err.println(form.format(source));
 908                 newPass = storePass;
 909             }
 910             if (destKeyPass != null && !Arrays.equals(storePass, destKeyPass)) {
 911                 Object[] source = {"-destkeypass"};
 912                 System.err.println(form.format(source));
 913                 destKeyPass = storePass;
 914             }
 915         }
 916 
 917         // Create a certificate factory
 918         if (command == PRINTCERT || command == IMPORTCERT
 919                 || command == IDENTITYDB || command == PRINTCRL) {
 920             cf = CertificateFactory.getInstance("X509");
 921         }
 922 







 923         if (trustcacerts) {
 924             caks = KeyStoreUtil.getCacertsKeyStore();
 925         }
 926 
 927         // Perform the specified command
 928         if (command == CERTREQ) {
 929             if (filename != null) {
 930                 try (PrintStream ps = new PrintStream(new FileOutputStream
 931                                                       (filename))) {
 932                     doCertReq(alias, sigAlgName, ps);
 933                 }
 934             } else {
 935                 doCertReq(alias, sigAlgName, out);
 936             }
 937             if (verbose && filename != null) {
 938                 MessageFormat form = new MessageFormat(rb.getString
 939                         ("Certification.request.stored.in.file.filename."));
 940                 Object[] source = {filename};
 941                 System.err.println(form.format(source));
 942                 System.err.println(rb.getString("Submit.this.to.your.CA"));


1004                             ("Certificate.reply.was.not.installed.in.keystore"));
1005                     }
1006                 } else if (!keyStore.containsAlias(importAlias) ||
1007                         keyStore.entryInstanceOf(importAlias,
1008                             KeyStore.TrustedCertificateEntry.class)) {
1009                     kssave = addTrustedCert(importAlias, inStream);
1010                     if (kssave) {
1011                         System.err.println(rb.getString
1012                             ("Certificate.was.added.to.keystore"));
1013                     } else {
1014                         System.err.println(rb.getString
1015                             ("Certificate.was.not.added.to.keystore"));
1016                     }
1017                 }
1018             } finally {
1019                 if (inStream != System.in) {
1020                     inStream.close();
1021                 }
1022             }
1023         } else if (command == IMPORTKEYSTORE) {
1024             doImportKeyStore();




1025             kssave = true;
1026         } else if (command == KEYCLONE) {
1027             keyPassNew = newPass;
1028 
1029             // added to make sure only key can go thru
1030             if (alias == null) {
1031                 alias = keyAlias;
1032             }
1033             if (keyStore.containsAlias(alias) == false) {
1034                 MessageFormat form = new MessageFormat
1035                     (rb.getString("Alias.alias.does.not.exist"));
1036                 Object[] source = {alias};
1037                 throw new Exception(form.format(source));
1038             }
1039             if (!keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)) {
1040                 MessageFormat form = new MessageFormat(rb.getString(
1041                         "Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key"));
1042                 Object[] source = {alias};
1043                 throw new Exception(form.format(source));
1044             }
1045 
1046             doCloneEntry(alias, dest, true);  // Now everything can be cloned
1047             kssave = true;
1048         } else if (command == CHANGEALIAS) {
1049             if (alias == null) {
1050                 alias = keyAlias;
1051             }
1052             doCloneEntry(alias, dest, false);
1053             // in PKCS11, clone a PrivateKeyEntry will delete the old one
1054             if (keyStore.containsAlias(alias)) {
1055                 doDeleteEntry(alias);
1056             }
1057             kssave = true;
1058         } else if (command == KEYPASSWD) {
1059             keyPassNew = newPass;
1060             doChangeKeyPasswd(alias);
1061             kssave = true;
1062         } else if (command == LIST) {





1063             if (alias != null) {
1064                 doPrintEntry(alias, out, true);
1065             } else {
1066                 doPrintEntries(out);
1067             }
1068         } else if (command == PRINTCERT) {
1069             doPrintCert(out);
1070         } else if (command == SELFCERT) {
1071             doSelfCert(alias, dname, sigAlgName);
1072             kssave = true;
1073         } else if (command == STOREPASSWD) {
1074             storePassNew = newPass;
1075             if (storePassNew == null) {
1076                 storePassNew = getNewPasswd("keystore password", storePass);
1077             }
1078             kssave = true;
1079         } else if (command == GENCERT) {
1080             if (alias == null) {
1081                 alias = keyAlias;
1082             }
1083             InputStream inStream = System.in;
1084             if (infilename != null) {


1130                         (rb.getString(".Storing.ksfname."));
1131                 Object[] source = {nullStream ? "keystore" : ksfname};
1132                 System.err.println(form.format(source));
1133             }
1134 
1135             if (token) {
1136                 keyStore.store(null, null);
1137             } else {
1138                 char[] pass = (storePassNew!=null) ? storePassNew : storePass;
1139                 if (nullStream) {
1140                     keyStore.store(null, pass);
1141                 } else {
1142                     ByteArrayOutputStream bout = new ByteArrayOutputStream();
1143                     keyStore.store(bout, pass);
1144                     try (FileOutputStream fout = new FileOutputStream(ksfname)) {
1145                         fout.write(bout.toByteArray());
1146                     }
1147                 }
1148             }
1149         }



























































1150     }
1151 
1152     /**
1153      * Generate a certificate: Read PKCS10 request from in, and print
1154      * certificate to out. Use alias as CA, sigAlgName as the signature
1155      * type.
1156      */
1157     private void doGenCert(String alias, String sigAlgName, InputStream in, PrintStream out)
1158             throws Exception {
1159 
1160 






1161         Certificate signerCert = keyStore.getCertificate(alias);
1162         byte[] encoded = signerCert.getEncoded();
1163         X509CertImpl signerCertImpl = new X509CertImpl(encoded);
1164         X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
1165                 X509CertImpl.NAME + "." + X509CertImpl.INFO);
1166         X500Name issuer = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." +
1167                                            X509CertInfo.DN_NAME);
1168 
1169         Date firstDate = getStartDate(startDate);
1170         Date lastDate = new Date();
1171         lastDate.setTime(firstDate.getTime() + validity*1000L*24L*60L*60L);
1172         CertificateValidity interval = new CertificateValidity(firstDate,
1173                                                                lastDate);
1174 
1175         PrivateKey privateKey =
1176                 (PrivateKey)recoverKey(alias, storePass, keyPass).fst;
1177         if (sigAlgName == null) {
1178             sigAlgName = getCompatibleSigAlgName(privateKey.getAlgorithm());
1179         }
1180         Signature signature = Signature.getInstance(sigAlgName);


1194         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
1195         boolean canRead = false;
1196         StringBuffer sb = new StringBuffer();
1197         while (true) {
1198             String s = reader.readLine();
1199             if (s == null) break;
1200             // OpenSSL does not use NEW
1201             //if (s.startsWith("-----BEGIN NEW CERTIFICATE REQUEST-----")) {
1202             if (s.startsWith("-----BEGIN") && s.indexOf("REQUEST") >= 0) {
1203                 canRead = true;
1204             //} else if (s.startsWith("-----END NEW CERTIFICATE REQUEST-----")) {
1205             } else if (s.startsWith("-----END") && s.indexOf("REQUEST") >= 0) {
1206                 break;
1207             } else if (canRead) {
1208                 sb.append(s);
1209             }
1210         }
1211         byte[] rawReq = Pem.decode(new String(sb));
1212         PKCS10 req = new PKCS10(rawReq);
1213 


1214         info.set(X509CertInfo.KEY, new CertificateX509Key(req.getSubjectPublicKeyInfo()));
1215         info.set(X509CertInfo.SUBJECT,
1216                     dname==null?req.getSubjectName():new X500Name(dname));
1217         CertificateExtensions reqex = null;
1218         Iterator<PKCS10Attribute> attrs = req.getAttributes().getAttributes().iterator();
1219         while (attrs.hasNext()) {
1220             PKCS10Attribute attr = attrs.next();
1221             if (attr.getAttributeId().equals((Object)PKCS9Attribute.EXTENSION_REQUEST_OID)) {
1222                 reqex = (CertificateExtensions)attr.getAttributeValue();
1223             }
1224         }
1225         CertificateExtensions ext = createV3Extensions(
1226                 reqex,
1227                 null,
1228                 v3ext,
1229                 req.getSubjectPublicKeyInfo(),
1230                 signerCert.getPublicKey());
1231         info.set(X509CertInfo.EXTENSIONS, ext);
1232         X509CertImpl cert = new X509CertImpl(info);
1233         cert.sign(privateKey, sigAlgName);
1234         dumpCert(cert, out);
1235         for (Certificate ca: keyStore.getCertificateChain(alias)) {
1236             if (ca instanceof X509Certificate) {
1237                 X509Certificate xca = (X509Certificate)ca;
1238                 if (!isSelfSigned(xca)) {
1239                     dumpCert(xca, out);
1240                 }
1241             }
1242         }



1243     }
1244 
1245     private void doGenCRL(PrintStream out)
1246             throws Exception {
1247         if (ids == null) {
1248             throw new Exception("Must provide -id when -gencrl");
1249         }
1250         Certificate signerCert = keyStore.getCertificate(alias);
1251         byte[] encoded = signerCert.getEncoded();
1252         X509CertImpl signerCertImpl = new X509CertImpl(encoded);
1253         X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
1254                 X509CertImpl.NAME + "." + X509CertImpl.INFO);
1255         X500Name owner = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." +
1256                                                       X509CertInfo.DN_NAME);
1257 
1258         Date firstDate = getStartDate(startDate);
1259         Date lastDate = (Date) firstDate.clone();
1260         lastDate.setTime(lastDate.getTime() + validity*1000*24*60*60);
1261         CertificateValidity interval = new CertificateValidity(firstDate,
1262                                                                lastDate);


1273             String id = ids.get(i);
1274             int d = id.indexOf(':');
1275             if (d >= 0) {
1276                 CRLExtensions ext = new CRLExtensions();
1277                 ext.set("Reason", new CRLReasonCodeExtension(Integer.parseInt(id.substring(d+1))));
1278                 badCerts[i] = new X509CRLEntryImpl(new BigInteger(id.substring(0, d)),
1279                         firstDate, ext);
1280             } else {
1281                 badCerts[i] = new X509CRLEntryImpl(new BigInteger(ids.get(i)), firstDate);
1282             }
1283         }
1284         X509CRLImpl crl = new X509CRLImpl(owner, firstDate, lastDate, badCerts);
1285         crl.sign(privateKey, sigAlgName);
1286         if (rfc) {
1287             out.println("-----BEGIN X509 CRL-----");
1288             out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(crl.getEncodedInternal()));
1289             out.println("-----END X509 CRL-----");
1290         } else {
1291             out.write(crl.getEncodedInternal());
1292         }

1293     }
1294 
1295     /**
1296      * Creates a PKCS#10 cert signing request, corresponding to the
1297      * keys (and name) associated with a given alias.
1298      */
1299     private void doCertReq(String alias, String sigAlgName, PrintStream out)
1300         throws Exception
1301     {
1302         if (alias == null) {
1303             alias = keyAlias;
1304         }
1305 
1306         Pair<Key,char[]> objs = recoverKey(alias, storePass, keyPass);
1307         PrivateKey privKey = (PrivateKey)objs.fst;
1308         if (keyPass == null) {
1309             keyPass = objs.snd;
1310         }
1311 
1312         Certificate cert = keyStore.getCertificate(alias);


1319         PKCS10 request = new PKCS10(cert.getPublicKey());
1320         CertificateExtensions ext = createV3Extensions(null, null, v3ext, cert.getPublicKey(), null);
1321         // Attribute name is not significant
1322         request.getAttributes().setAttribute(X509CertInfo.EXTENSIONS,
1323                 new PKCS10Attribute(PKCS9Attribute.EXTENSION_REQUEST_OID, ext));
1324 
1325         // Construct a Signature object, so that we can sign the request
1326         if (sigAlgName == null) {
1327             sigAlgName = getCompatibleSigAlgName(privKey.getAlgorithm());
1328         }
1329 
1330         Signature signature = Signature.getInstance(sigAlgName);
1331         signature.initSign(privKey);
1332         X500Name subject = dname == null?
1333                 new X500Name(((X509Certificate)cert).getSubjectDN().toString()):
1334                 new X500Name(dname);
1335 
1336         // Sign the request and base-64 encode it
1337         request.encodeAndSign(subject, signature);
1338         request.print(out);


1339     }
1340 
1341     /**
1342      * Deletes an entry from the keystore.
1343      */
1344     private void doDeleteEntry(String alias) throws Exception {
1345         if (keyStore.containsAlias(alias) == false) {
1346             MessageFormat form = new MessageFormat
1347                 (rb.getString("Alias.alias.does.not.exist"));
1348             Object[] source = {alias};
1349             throw new Exception(form.format(source));
1350         }
1351         keyStore.deleteEntry(alias);
1352     }
1353 
1354     /**
1355      * Exports a certificate from the keystore.
1356      */
1357     private void doExportCert(String alias, PrintStream out)
1358         throws Exception
1359     {
1360         if (storePass == null
1361                 && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
1362             printWarning();
1363         }
1364         if (alias == null) {
1365             alias = keyAlias;
1366         }
1367         if (keyStore.containsAlias(alias) == false) {
1368             MessageFormat form = new MessageFormat
1369                 (rb.getString("Alias.alias.does.not.exist"));
1370             Object[] source = {alias};
1371             throw new Exception(form.format(source));
1372         }
1373 
1374         X509Certificate cert = (X509Certificate)keyStore.getCertificate(alias);
1375         if (cert == null) {
1376             MessageFormat form = new MessageFormat
1377                 (rb.getString("Alias.alias.has.no.certificate"));
1378             Object[] source = {alias};
1379             throw new Exception(form.format(source));
1380         }
1381         dumpCert(cert, out);

1382     }
1383 
1384     /**
1385      * Prompt the user for a keypass when generating a key entry.
1386      * @param alias the entry we will set password for
1387      * @param orig the original entry of doing a dup, null if generate new
1388      * @param origPass the password to copy from if user press ENTER
1389      */
1390     private char[] promptForKeyPass(String alias, String orig, char[] origPass) throws Exception{
1391         if (P12KEYSTORE.equalsIgnoreCase(storetype)) {
1392             return origPass;
1393         } else if (!token && !protectedPath) {
1394             // Prompt for key password
1395             int count;
1396             for (count = 0; count < 3; count++) {
1397                 MessageFormat form = new MessageFormat(rb.getString
1398                         ("Enter.key.password.for.alias."));
1399                 Object[] source = {alias};
1400                 System.err.println(form.format(source));
1401                 if (orig == null) {


1542 
1543         if (keyPass == null) {
1544             keyPass = promptForKeyPass(alias, null, storePass);
1545         }
1546 
1547         if (useDefaultPBEAlgorithm) {
1548             keyStore.setKeyEntry(alias, secKey, keyPass, null);
1549         } else {
1550             keyStore.setEntry(alias, new KeyStore.SecretKeyEntry(secKey),
1551                 new KeyStore.PasswordProtection(keyPass, keyAlgName, null));
1552         }
1553     }
1554 
1555     /**
1556      * If no signature algorithm was specified at the command line,
1557      * we choose one that is compatible with the selected private key
1558      */
1559     private static String getCompatibleSigAlgName(String keyAlgName)
1560             throws Exception {
1561         if ("DSA".equalsIgnoreCase(keyAlgName)) {
1562             return "SHA1WithDSA";
1563         } else if ("RSA".equalsIgnoreCase(keyAlgName)) {
1564             return "SHA256WithRSA";
1565         } else if ("EC".equalsIgnoreCase(keyAlgName)) {
1566             return "SHA256withECDSA";
1567         } else {
1568             throw new Exception(rb.getString
1569                     ("Cannot.derive.signature.algorithm"));
1570         }
1571     }
1572     /**
1573      * Creates a new key pair and self-signed certificate.
1574      */
1575     private void doGenKeyPair(String alias, String dname, String keyAlgName,
1576                               int keysize, String sigAlgName)
1577         throws Exception
1578     {
1579         if (keysize == -1) {
1580             if ("EC".equalsIgnoreCase(keyAlgName)) {
1581                 keysize = 256;
1582             } else if ("RSA".equalsIgnoreCase(keyAlgName)) {




1583                 keysize = 2048;
1584             } else {
1585                 keysize = 1024;
1586             }
1587         }
1588 
1589         if (alias == null) {
1590             alias = keyAlias;
1591         }
1592 
1593         if (keyStore.containsAlias(alias)) {
1594             MessageFormat form = new MessageFormat(rb.getString
1595                 ("Key.pair.not.generated.alias.alias.already.exists"));
1596             Object[] source = {alias};
1597             throw new Exception(form.format(source));
1598         }
1599 
1600         if (sigAlgName == null) {
1601             sigAlgName = getCompatibleSigAlgName(keyAlgName);
1602         }
1603         CertAndKeyGen keypair =
1604                 new CertAndKeyGen(keyAlgName, sigAlgName, providerName);
1605 


1623                 null);
1624 
1625         X509Certificate[] chain = new X509Certificate[1];
1626         chain[0] = keypair.getSelfCertificate(
1627                 x500Name, getStartDate(startDate), validity*24L*60L*60L, ext);
1628 
1629         if (verbose) {
1630             MessageFormat form = new MessageFormat(rb.getString
1631                 ("Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for"));
1632             Object[] source = {new Integer(keysize),
1633                                 privKey.getAlgorithm(),
1634                                 chain[0].getSigAlgName(),
1635                                 new Long(validity),
1636                                 x500Name};
1637             System.err.println(form.format(source));
1638         }
1639 
1640         if (keyPass == null) {
1641             keyPass = promptForKeyPass(alias, null, storePass);
1642         }

1643         keyStore.setKeyEntry(alias, privKey, keyPass, chain);
1644     }
1645 
1646     /**
1647      * Clones an entry
1648      * @param orig original alias
1649      * @param dest destination alias
1650      * @changePassword if the password can be changed
1651      */
1652     private void doCloneEntry(String orig, String dest, boolean changePassword)
1653         throws Exception
1654     {
1655         if (orig == null) {
1656             orig = keyAlias;
1657         }
1658 
1659         if (keyStore.containsAlias(dest)) {
1660             MessageFormat form = new MessageFormat
1661                 (rb.getString("Destination.alias.dest.already.exists"));
1662             Object[] source = {dest};


1705         }
1706         keyStore.setKeyEntry(alias, privKey, keyPassNew,
1707                              keyStore.getCertificateChain(alias));
1708     }
1709 
1710     /**
1711      * Imports a JDK 1.1-style identity database. We can only store one
1712      * certificate per identity, because we use the identity's name as the
1713      * alias (which references a keystore entry), and aliases must be unique.
1714      */
1715     private void doImportIdentityDatabase(InputStream in)
1716         throws Exception
1717     {
1718         System.err.println(rb.getString
1719             ("No.entries.from.identity.database.added"));
1720     }
1721 
1722     /**
1723      * Prints a single keystore entry.
1724      */
1725     private void doPrintEntry(String alias, PrintStream out,
1726                               boolean printWarning)
1727         throws Exception
1728     {
1729         if (storePass == null && printWarning
1730                 && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
1731             printWarning();
1732         }
1733 
1734         if (keyStore.containsAlias(alias) == false) {
1735             MessageFormat form = new MessageFormat
1736                 (rb.getString("Alias.alias.does.not.exist"));
1737             Object[] source = {alias};
1738             throw new Exception(form.format(source));
1739         }
1740 
1741         if (verbose || rfc || debug) {
1742             MessageFormat form = new MessageFormat
1743                 (rb.getString("Alias.name.alias"));
1744             Object[] source = {alias};
1745             out.println(form.format(source));
1746 
1747             if (!token) {
1748                 form = new MessageFormat(rb.getString
1749                     ("Creation.date.keyStore.getCreationDate.alias."));
1750                 Object[] src = {keyStore.getCreationDate(alias)};
1751                 out.println(form.format(src));
1752             }
1753         } else {


1782             }
1783 
1784             // Get the chain
1785             Certificate[] chain = keyStore.getCertificateChain(alias);
1786             if (chain != null) {
1787                 if (verbose || rfc || debug) {
1788                     out.println(rb.getString
1789                         ("Certificate.chain.length.") + chain.length);
1790                     for (int i = 0; i < chain.length; i ++) {
1791                         MessageFormat form = new MessageFormat
1792                                 (rb.getString("Certificate.i.1."));
1793                         Object[] source = {new Integer((i + 1))};
1794                         out.println(form.format(source));
1795                         if (verbose && (chain[i] instanceof X509Certificate)) {
1796                             printX509Cert((X509Certificate)(chain[i]), out);
1797                         } else if (debug) {
1798                             out.println(chain[i].toString());
1799                         } else {
1800                             dumpCert(chain[i], out);
1801                         }

1802                     }
1803                 } else {
1804                     // Print the digest of the user cert only
1805                     out.println
1806                         (rb.getString("Certificate.fingerprint.SHA1.") +
1807                         getCertFingerPrint("SHA1", chain[0]));

1808                 }
1809             }
1810         } else if (keyStore.entryInstanceOf(alias,
1811                 KeyStore.TrustedCertificateEntry.class)) {
1812             // We have a trusted certificate entry
1813             Certificate cert = keyStore.getCertificate(alias);
1814             Object[] source = {"trustedCertEntry"};
1815             String mf = new MessageFormat(
1816                     rb.getString("Entry.type.type.")).format(source) + "\n";
1817             if (verbose && (cert instanceof X509Certificate)) {
1818                 out.println(mf);
1819                 printX509Cert((X509Certificate)cert, out);
1820             } else if (rfc) {
1821                 out.println(mf);
1822                 dumpCert(cert, out);
1823             } else if (debug) {
1824                 out.println(cert.toString());
1825             } else {
1826                 out.println("trustedCertEntry, ");
1827                 out.println(rb.getString("Certificate.fingerprint.SHA1.")
1828                             + getCertFingerPrint("SHA1", cert));
1829             }

1830         } else {
1831             out.println(rb.getString("Unknown.Entry.Type"));
1832         }
1833     }
1834 





























1835     /**
1836      * Load the srckeystore from a stream, used in -importkeystore
1837      * @returns the src KeyStore
1838      */
1839     KeyStore loadSourceKeyStore() throws Exception {
1840         boolean isPkcs11 = false;
1841 
1842         InputStream is = null;

1843 
1844         if (P11KEYSTORE.equalsIgnoreCase(srcstoretype) ||
1845                 KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
1846             if (!NONE.equals(srcksfname)) {
1847                 System.err.println(MessageFormat.format(rb.getString
1848                     (".keystore.must.be.NONE.if.storetype.is.{0}"), srcstoretype));
1849                 System.err.println();
1850                 tinyHelp();
1851             }
1852             isPkcs11 = true;
1853         } else {
1854             if (srcksfname != null) {
1855                 File srcksfile = new File(srcksfname);
1856                     if (srcksfile.exists() && srcksfile.length() == 0) {
1857                         throw new Exception(rb.getString
1858                                 ("Source.keystore.file.exists.but.is.empty.") +
1859                                 srcksfname);
1860                 }
1861                 is = new FileInputStream(srcksfile);
1862             } else {
1863                 throw new Exception(rb.getString
1864                         ("Please.specify.srckeystore"));
1865             }
1866         }
1867 
1868         KeyStore store;
1869         try {
1870             if (srcProviderName == null) {
1871                 store = KeyStore.getInstance(srcstoretype);
1872             } else {
1873                 store = KeyStore.getInstance(srcstoretype, srcProviderName);
1874             }
1875 
1876             if (srcstorePass == null
1877                     && !srcprotectedPath
1878                     && !KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
1879                 System.err.print(rb.getString("Enter.source.keystore.password."));
1880                 System.err.flush();
1881                 srcstorePass = Password.readPassword(System.in);
1882                 passwords.add(srcstorePass);
1883             }
1884 
1885             // always let keypass be storepass when using pkcs12
1886             if (P12KEYSTORE.equalsIgnoreCase(srcstoretype)) {
1887                 if (srckeyPass != null && srcstorePass != null &&
1888                         !Arrays.equals(srcstorePass, srckeyPass)) {
1889                     MessageFormat form = new MessageFormat(rb.getString(
1890                         "Warning.Different.store.and.key.passwords.not.supported.for.PKCS12.KeyStores.Ignoring.user.specified.command.value."));
1891                     Object[] source = {"-srckeypass"};
1892                     System.err.println(form.format(source));
1893                     srckeyPass = srcstorePass;
1894                 }
1895             }
1896 
1897             store.load(is, srcstorePass);   // "is" already null in PKCS11
1898         } finally {
1899             if (is != null) {
1900                 is.close();
1901             }
1902         }
1903 
1904         if (srcstorePass == null
1905                 && !KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
1906             // anti refactoring, copied from printWarning(),
1907             // but change 2 lines
1908             System.err.println();
1909             System.err.println(rb.getString
1910                 (".WARNING.WARNING.WARNING."));
1911             System.err.println(rb.getString
1912                 (".The.integrity.of.the.information.stored.in.the.srckeystore."));
1913             System.err.println(rb.getString
1914                 (".WARNING.WARNING.WARNING."));
1915             System.err.println();
1916         }
1917 
1918         return store;
1919     }
1920 
1921     /**
1922      * import all keys and certs from importkeystore.
1923      * keep alias unchanged if no name conflict, otherwise, prompt.
1924      * keep keypass unchanged for keys
1925      */
1926     private void doImportKeyStore() throws Exception {
1927 
1928         if (alias != null) {
1929             doImportKeyStoreSingle(loadSourceKeyStore(), alias);
1930         } else {
1931             if (dest != null || srckeyPass != null) {
1932                 throw new Exception(rb.getString(
1933                         "if.alias.not.specified.destalias.and.srckeypass.must.not.be.specified"));
1934             }
1935             doImportKeyStoreAll(loadSourceKeyStore());
1936         }















1937         /*
1938          * Information display rule of -importkeystore
1939          * 1. inside single, shows failure
1940          * 2. inside all, shows sucess
1941          * 3. inside all where there is a failure, prompt for continue
1942          * 4. at the final of all, shows summary
1943          */
1944     }
1945 
1946     /**
1947      * Import a single entry named alias from srckeystore
1948      * @returns 1 if the import action succeed
1949      *          0 if user choose to ignore an alias-dumplicated entry
1950      *          2 if setEntry throws Exception
1951      */
1952     private int doImportKeyStoreSingle(KeyStore srckeystore, String alias)
1953             throws Exception {
1954 
1955         String newAlias = (dest==null) ? alias : dest;
1956 


1977 
1978         Pair<Entry,char[]> objs = recoverEntry(srckeystore, alias, srcstorePass, srckeyPass);
1979         Entry entry = objs.fst;
1980 
1981         PasswordProtection pp = null;
1982 
1983         // According to keytool.html, "The destination entry will be protected
1984         // using destkeypass. If destkeypass is not provided, the destination
1985         // entry will be protected with the source entry password."
1986         // so always try to protect with destKeyPass.
1987         char[] newPass = null;
1988         if (destKeyPass != null) {
1989             newPass = destKeyPass;
1990             pp = new PasswordProtection(destKeyPass);
1991         } else if (objs.snd != null) {
1992             newPass = objs.snd;
1993             pp = new PasswordProtection(objs.snd);
1994         }
1995 
1996         try {




1997             keyStore.setEntry(newAlias, entry, pp);
1998             // Place the check so that only successful imports are blocked.
1999             // For example, we don't block a failed SecretEntry import.
2000             if (P12KEYSTORE.equalsIgnoreCase(storetype)) {
2001                 if (newPass != null && !Arrays.equals(newPass, storePass)) {
2002                     throw new Exception(rb.getString(
2003                             "The.destination.pkcs12.keystore.has.different.storepass.and.keypass.Please.retry.with.destkeypass.specified."));
2004                 }
2005             }
2006             return 1;
2007         } catch (KeyStoreException kse) {
2008             Object[] source2 = {alias, kse.toString()};
2009             MessageFormat form = new MessageFormat(rb.getString(
2010                     "Problem.importing.entry.for.alias.alias.exception.Entry.for.alias.alias.not.imported."));
2011             System.err.println(form.format(source2));
2012             return 2;
2013         }
2014     }
2015 
2016     private void doImportKeyStoreAll(KeyStore srckeystore) throws Exception {


2030                 if (!noprompt) {
2031                     String reply = getYesNoReply("Do you want to quit the import process? [no]:  ");
2032                     if ("YES".equals(reply)) {
2033                         break;
2034                     }
2035                 }
2036             }
2037         }
2038         Object[] source = {ok, count-ok};
2039         MessageFormat form = new MessageFormat(rb.getString(
2040                 "Import.command.completed.ok.entries.successfully.imported.fail.entries.failed.or.cancelled"));
2041         System.err.println(form.format(source));
2042     }
2043 
2044     /**
2045      * Prints all keystore entries.
2046      */
2047     private void doPrintEntries(PrintStream out)
2048         throws Exception
2049     {
2050         if (storePass == null
2051                 && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
2052             printWarning();
2053         } else {
2054             out.println();
2055         }
2056 
2057         out.println(rb.getString("Keystore.type.") + keyStore.getType());
2058         out.println(rb.getString("Keystore.provider.") +
2059                 keyStore.getProvider().getName());
2060         out.println();
2061 
2062         MessageFormat form;
2063         form = (keyStore.size() == 1) ?
2064                 new MessageFormat(rb.getString
2065                         ("Your.keystore.contains.keyStore.size.entry")) :
2066                 new MessageFormat(rb.getString
2067                         ("Your.keystore.contains.keyStore.size.entries"));
2068         Object[] source = {new Integer(keyStore.size())};
2069         out.println(form.format(source));
2070         out.println();
2071 
2072         for (Enumeration<String> e = keyStore.aliases();
2073                                         e.hasMoreElements(); ) {
2074             String alias = e.nextElement();
2075             doPrintEntry(alias, out, false);
2076             if (verbose || rfc) {
2077                 out.println(rb.getString("NEWLINE"));
2078                 out.println(rb.getString
2079                         ("STAR"));
2080                 out.println(rb.getString
2081                         ("STARNN"));
2082             }
2083         }
2084     }
2085 
2086     private static <T> Iterable<T> e2i(final Enumeration<T> e) {
2087         return new Iterable<T>() {
2088             @Override
2089             public Iterator<T> iterator() {
2090                 return new Iterator<T>() {
2091                     @Override
2092                     public boolean hasNext() {
2093                         return e.hasMoreElements();
2094                     }
2095                     @Override


2205             Certificate cert = ks.getCertificate(s);
2206             if (cert instanceof X509Certificate) {
2207                 X509Certificate xcert = (X509Certificate)cert;
2208                 if (xcert.getSubjectX500Principal().equals(issuer)) {
2209                     try {
2210                         ((X509CRLImpl)crl).verify(cert.getPublicKey());
2211                         return s;
2212                     } catch (Exception e) {
2213                     }
2214                 }
2215             }
2216         }
2217         return null;
2218     }
2219 
2220     private void doPrintCRL(String src, PrintStream out)
2221             throws Exception {
2222         for (CRL crl: loadCRLs(src)) {
2223             printCRL(crl, out);
2224             String issuer = null;

2225             if (caks != null) {
2226                 issuer = verifyCRL(caks, crl);
2227                 if (issuer != null) {

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



2230                     out.println();
2231                 }
2232             }
2233             if (issuer == null && keyStore != null) {
2234                 issuer = verifyCRL(keyStore, crl);
2235                 if (issuer != null) {

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



2238                     out.println();
2239                 }
2240             }
2241             if (issuer == null) {
2242                 out.println(rb.getString
2243                         ("STAR"));
2244                 out.println(rb.getString
2245                         ("warning.not.verified.make.sure.keystore.is.correct"));
2246                 out.println(rb.getString
2247                         ("STARNN"));
2248             }

2249         }
2250     }
2251 
2252     private void printCRL(CRL crl, PrintStream out)
2253             throws Exception {
2254         if (rfc) {
2255             X509CRL xcrl = (X509CRL)crl;

2256             out.println("-----BEGIN X509 CRL-----");
2257             out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(xcrl.getEncoded()));
2258             out.println("-----END X509 CRL-----");
2259         } else {
2260             out.println(crl.toString());







2261         }
2262     }
2263 
2264     private void doPrintCertReq(InputStream in, PrintStream out)
2265             throws Exception {
2266 
2267         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
2268         StringBuffer sb = new StringBuffer();
2269         boolean started = false;
2270         while (true) {
2271             String s = reader.readLine();
2272             if (s == null) break;
2273             if (!started) {
2274                 if (s.startsWith("-----")) {
2275                     started = true;
2276                 }
2277             } else {
2278                 if (s.startsWith("-----")) {
2279                     break;
2280                 }
2281                 sb.append(s);
2282             }
2283         }
2284         PKCS10 req = new PKCS10(Pem.decode(new String(sb)));
2285 
2286         PublicKey pkey = req.getSubjectPublicKeyInfo();
2287         out.printf(rb.getString("PKCS.10.Certificate.Request.Version.1.0.Subject.s.Public.Key.s.format.s.key."),
2288                 req.getSubjectName(), pkey.getFormat(), pkey.getAlgorithm());



2289         for (PKCS10Attribute attr: req.getAttributes().getAttributes()) {
2290             ObjectIdentifier oid = attr.getAttributeId();
2291             if (oid.equals((Object)PKCS9Attribute.EXTENSION_REQUEST_OID)) {
2292                 CertificateExtensions exts = (CertificateExtensions)attr.getAttributeValue();
2293                 if (exts != null) {
2294                     printExtensions(rb.getString("Extension.Request."), exts, out);
2295                 }
2296             } else {
2297                 out.println("Attribute: " + attr.getAttributeId());
2298                 PKCS9Attribute pkcs9Attr =
2299                         new PKCS9Attribute(attr.getAttributeId(),
2300                                            attr.getAttributeValue());
2301                 out.print(pkcs9Attr.getName() + ": ");
2302                 Object attrVal = attr.getAttributeValue();
2303                 out.println(attrVal instanceof String[] ?
2304                             Arrays.toString((String[]) attrVal) :
2305                             attrVal);
2306             }
2307         }
2308         if (debug) {
2309             out.println(req);   // Just to see more, say, public key length...
2310         }

2311     }
2312 
2313     /**
2314      * Reads a certificate (or certificate chain) and prints its contents in
2315      * a human readable format.
2316      */
2317     private void printCertFromStream(InputStream in, PrintStream out)
2318         throws Exception
2319     {
2320         Collection<? extends Certificate> c = null;
2321         try {
2322             c = cf.generateCertificates(in);
2323         } catch (CertificateException ce) {
2324             throw new Exception(rb.getString("Failed.to.parse.input"), ce);
2325         }
2326         if (c.isEmpty()) {
2327             throw new Exception(rb.getString("Empty.input"));
2328         }
2329         Certificate[] certs = c.toArray(new Certificate[c.size()]);
2330         for (int i=0; i<certs.length; i++) {
2331             X509Certificate x509Cert = null;
2332             try {
2333                 x509Cert = (X509Certificate)certs[i];
2334             } catch (ClassCastException cce) {
2335                 throw new Exception(rb.getString("Not.X.509.certificate"));
2336             }
2337             if (certs.length > 1) {
2338                 MessageFormat form = new MessageFormat
2339                         (rb.getString("Certificate.i.1."));
2340                 Object[] source = {new Integer(i + 1)};
2341                 out.println(form.format(source));
2342             }
2343             if (rfc)
2344                 dumpCert(x509Cert, out);
2345             else
2346                 printX509Cert(x509Cert, out);
2347             if (i < (certs.length-1)) {
2348                 out.println();
2349             }









2350         }
2351     }
2352 
2353     private void doPrintCert(final PrintStream out) throws Exception {
2354         if (jarfile != null) {
2355             JarFile jf = new JarFile(jarfile, true);
2356             Enumeration<JarEntry> entries = jf.entries();
2357             Set<CodeSigner> ss = new HashSet<>();
2358             byte[] buffer = new byte[8192];
2359             int pos = 0;
2360             while (entries.hasMoreElements()) {
2361                 JarEntry je = entries.nextElement();
2362                 try (InputStream is = jf.getInputStream(je)) {
2363                     while (is.read(buffer) != -1) {
2364                         // we just read. this will throw a SecurityException
2365                         // if a signature/digest check fails. This also
2366                         // populate the signers
2367                     }
2368                 }
2369                 CodeSigner[] signers = je.getCodeSigners();
2370                 if (signers != null) {
2371                     for (CodeSigner signer: signers) {
2372                         if (!ss.contains(signer)) {
2373                             ss.add(signer);
2374                             out.printf(rb.getString("Signer.d."), ++pos);
2375                             out.println();
2376                             out.println();
2377                             out.println(rb.getString("Signature."));
2378                             out.println();
2379                             for (Certificate cert: signer.getSignerCertPath().getCertificates()) {




2380                                 X509Certificate x = (X509Certificate)cert;
2381                                 if (rfc) {
2382                                     out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n");
2383                                     dumpCert(x, out);
2384                                 } else {
2385                                     printX509Cert(x, out);
2386                                 }
2387                                 out.println();

2388                             }
2389                             Timestamp ts = signer.getTimestamp();
2390                             if (ts != null) {
2391                                 out.println(rb.getString("Timestamp."));
2392                                 out.println();
2393                                 for (Certificate cert: ts.getSignerCertPath().getCertificates()) {


2394                                     X509Certificate x = (X509Certificate)cert;
2395                                     if (rfc) {
2396                                         out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n");
2397                                         dumpCert(x, out);
2398                                     } else {
2399                                         printX509Cert(x, out);
2400                                     }
2401                                     out.println();

2402                                 }
2403                             }
2404                         }
2405                     }
2406                 }
2407             }
2408             jf.close();
2409             if (ss.isEmpty()) {
2410                 out.println(rb.getString("Not.a.signed.jar.file"));
2411             }
2412         } else if (sslserver != null) {
2413             // Lazily load SSLCertStoreHelper if present
2414             CertStoreHelper helper = CertStoreHelper.getInstance("SSLServer");
2415             CertStore cs = helper.getCertStore(new URI("https://" + sslserver));
2416             Collection<? extends Certificate> chain;
2417             try {
2418                 chain = cs.getCertificates(null);
2419                 if (chain.isEmpty()) {
2420                     // If the certs are not retrieved, we consider it an error
2421                     // even if the URL connection is successful.


2426                 if (cse.getCause() instanceof IOException) {
2427                     throw new Exception(rb.getString(
2428                                         "No.certificate.from.the.SSL.server"),
2429                                         cse.getCause());
2430                 } else {
2431                     throw cse;
2432                 }
2433             }
2434 
2435             int i = 0;
2436             for (Certificate cert : chain) {
2437                 try {
2438                     if (rfc) {
2439                         dumpCert(cert, out);
2440                     } else {
2441                         out.println("Certificate #" + i++);
2442                         out.println("====================================");
2443                         printX509Cert((X509Certificate)cert, out);
2444                         out.println();
2445                     }

2446                 } catch (Exception e) {
2447                     if (debug) {
2448                         e.printStackTrace();
2449                     }
2450                 }
2451             }
2452         } else {
2453             if (filename != null) {
2454                 try (FileInputStream inStream = new FileInputStream(filename)) {
2455                     printCertFromStream(inStream, out);
2456                 }
2457             } else {
2458                 printCertFromStream(System.in, out);
2459             }
2460         }
2461     }
2462     /**
2463      * Creates a self-signed certificate, and stores it as a single-element
2464      * certificate chain.
2465      */


2601             Object[] source = {alias};
2602             throw new Exception(form.format(source));
2603         }
2604 
2605         // Read the certificates in the reply
2606         Collection<? extends Certificate> c = cf.generateCertificates(in);
2607         if (c.isEmpty()) {
2608             throw new Exception(rb.getString("Reply.has.no.certificates"));
2609         }
2610         Certificate[] replyCerts = c.toArray(new Certificate[c.size()]);
2611         Certificate[] newChain;
2612         if (replyCerts.length == 1) {
2613             // single-cert reply
2614             newChain = establishCertChain(userCert, replyCerts[0]);
2615         } else {
2616             // cert-chain reply (e.g., PKCS#7)
2617             newChain = validateReply(alias, userCert, replyCerts);
2618         }
2619 
2620         // Now store the newly established chain in the keystore. The new
2621         // chain replaces the old one.
2622         if (newChain != null) {
2623             keyStore.setKeyEntry(alias, privKey,
2624                                  (keyPass != null) ? keyPass : storePass,
2625                                  newChain);
2626             return true;
2627         } else {
2628             return false;
2629         }
2630     }
2631 
2632     /**
2633      * Imports a certificate and adds it to the list of trusted certificates.
2634      *
2635      * @return true if the certificate was added, otherwise false.
2636      */
2637     private boolean addTrustedCert(String alias, InputStream in)
2638         throws Exception
2639     {
2640         if (alias == null) {
2641             throw new Exception(rb.getString("Must.specify.alias"));
2642         }
2643         if (keyStore.containsAlias(alias)) {
2644             MessageFormat form = new MessageFormat(rb.getString
2645                 ("Certificate.not.imported.alias.alias.already.exists"));
2646             Object[] source = {alias};
2647             throw new Exception(form.format(source));
2648         }
2649 
2650         // Read the certificate
2651         X509Certificate cert = null;
2652         try {
2653             cert = (X509Certificate)cf.generateCertificate(in);
2654         } catch (ClassCastException | CertificateException ce) {
2655             throw new Exception(rb.getString("Input.not.an.X.509.certificate"));
2656         }
2657 






2658         // if certificate is self-signed, make sure it verifies
2659         boolean selfSigned = false;
2660         if (isSelfSigned(cert)) {
2661             cert.verify(cert.getPublicKey());
2662             selfSigned = true;
2663         }
2664 
2665         if (noprompt) {
2666             keyStore.setCertificateEntry(alias, cert);
2667             return true;
2668         }
2669 
2670         // check if cert already exists in keystore
2671         String reply = null;
2672         String trustalias = keyStore.getCertificateAlias(cert);
2673         if (trustalias != null) {
2674             MessageFormat form = new MessageFormat(rb.getString
2675                 ("Certificate.already.exists.in.keystore.under.alias.trustalias."));
2676             Object[] source = {trustalias};
2677             System.err.println(form.format(source));


2678             reply = getYesNoReply
2679                 (rb.getString("Do.you.still.want.to.add.it.no."));
2680         } else if (selfSigned) {
2681             if (trustcacerts && (caks != null) &&
2682                     ((trustalias=caks.getCertificateAlias(cert)) != null)) {
2683                 MessageFormat form = new MessageFormat(rb.getString
2684                         ("Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias."));
2685                 Object[] source = {trustalias};
2686                 System.err.println(form.format(source));


2687                 reply = getYesNoReply
2688                         (rb.getString("Do.you.still.want.to.add.it.to.your.own.keystore.no."));
2689             }
2690             if (trustalias == null) {
2691                 // Print the cert and ask user if they really want to add
2692                 // it to their keystore
2693                 printX509Cert(cert, System.out);


2694                 reply = getYesNoReply
2695                         (rb.getString("Trust.this.certificate.no."));
2696             }
2697         }
2698         if (reply != null) {
2699             if ("YES".equals(reply)) {
2700                 keyStore.setCertificateEntry(alias, cert);
2701                 return true;
2702             } else {
2703                 return false;
2704             }
2705         }
2706 

2707         // Try to establish trust chain
2708         try {
2709             Certificate[] chain = establishCertChain(null, cert);
2710             if (chain != null) {
2711                 keyStore.setCertificateEntry(alias, cert);
2712                 return true;
2713             }
2714         } catch (Exception e) {
2715             // Print the cert and ask user if they really want to add it to
2716             // their keystore
2717             printX509Cert(cert, System.out);


2718             reply = getYesNoReply
2719                 (rb.getString("Trust.this.certificate.no."));
2720             if ("YES".equals(reply)) {
2721                 keyStore.setCertificateEntry(alias, cert);
2722                 return true;
2723             } else {
2724                 return false;
2725             }
2726         }
2727 
2728         return false;
2729     }
2730 
2731     /**
2732      * Prompts user for new password. New password must be different from
2733      * old one.
2734      *
2735      * @param prompt the message that gets prompted on the screen
2736      * @param oldPasswd the current (i.e., old) password
2737      */


2836                         ("Enter.key.password.for.alias."));
2837                 Object[] source = {alias};
2838                 System.err.print(form.format(source));
2839             }
2840             System.err.flush();
2841             keyPass = Password.readPassword(System.in);
2842             passwords.add(keyPass);
2843             if (keyPass == null) {
2844                 keyPass = otherKeyPass;
2845             }
2846             count++;
2847         } while ((keyPass == null) && count < 3);
2848 
2849         if (keyPass == null) {
2850             throw new Exception(rb.getString("Too.many.failures.try.later"));
2851         }
2852 
2853         return keyPass;
2854     }
2855 


















2856     /**
2857      * Prints a certificate in a human readable format.
2858      */
2859     private void printX509Cert(X509Certificate cert, PrintStream out)
2860         throws Exception
2861     {
2862         /*
2863         out.println("Owner: "
2864                     + cert.getSubjectDN().toString()
2865                     + "\n"
2866                     + "Issuer: "
2867                     + cert.getIssuerDN().toString()
2868                     + "\n"
2869                     + "Serial number: " + cert.getSerialNumber().toString(16)
2870                     + "\n"
2871                     + "Valid from: " + cert.getNotBefore().toString()
2872                     + " until: " + cert.getNotAfter().toString()
2873                     + "\n"
2874                     + "Certificate fingerprints:\n"
2875                     + "\t MD5:  " + getCertFingerPrint("MD5", cert)
2876                     + "\n"
2877                     + "\t SHA1: " + getCertFingerPrint("SHA1", cert));
2878         */
2879 
2880         MessageFormat form = new MessageFormat
2881                 (rb.getString(".PATTERN.printX509Cert"));






2882         Object[] source = {cert.getSubjectDN().toString(),
2883                         cert.getIssuerDN().toString(),
2884                         cert.getSerialNumber().toString(16),
2885                         cert.getNotBefore().toString(),
2886                         cert.getNotAfter().toString(),
2887                         getCertFingerPrint("MD5", cert),
2888                         getCertFingerPrint("SHA1", cert),
2889                         getCertFingerPrint("SHA-256", cert),
2890                         cert.getSigAlgName(),

2891                         cert.getVersion()
2892                         };
2893         out.println(form.format(source));
2894 
2895         if (cert instanceof X509CertImpl) {
2896             X509CertImpl impl = (X509CertImpl)cert;
2897             X509CertInfo certInfo = (X509CertInfo)impl.get(X509CertImpl.NAME
2898                                                            + "." +
2899                                                            X509CertImpl.INFO);
2900             CertificateExtensions exts = (CertificateExtensions)
2901                     certInfo.get(X509CertInfo.EXTENSIONS);
2902             if (exts != null) {
2903                 printExtensions(rb.getString("Extensions."), exts, out);
2904             }
2905         }
2906     }
2907 
2908     private static void printExtensions(String title, CertificateExtensions exts, PrintStream out)
2909             throws Exception {
2910         int extnum = 0;


2940 
2941     private boolean signedBy(X509Certificate end, X509Certificate ca) {
2942         if (!ca.getSubjectDN().equals(end.getIssuerDN())) {
2943             return false;
2944         }
2945         try {
2946             end.verify(ca.getPublicKey());
2947             return true;
2948         } catch (Exception e) {
2949             return false;
2950         }
2951     }
2952 
2953     /**
2954      * Locates a signer for a given certificate from a given keystore and
2955      * returns the signer's certificate.
2956      * @param cert the certificate whose signer is searched, not null
2957      * @param ks the keystore to search with, not null
2958      * @return <code>cert</code> itself if it's already inside <code>ks</code>,
2959      * or a certificate inside <code>ks</code> who signs <code>cert</code>,
2960      * or null otherwise.
2961      */
2962     private static Certificate getTrustedSigner(Certificate cert, KeyStore ks)
2963             throws Exception {
2964         if (ks.getCertificateAlias(cert) != null) {
2965             return cert;
2966         }
2967         for (Enumeration<String> aliases = ks.aliases();
2968                 aliases.hasMoreElements(); ) {
2969             String name = aliases.nextElement();
2970             Certificate trustedCert = ks.getCertificate(name);
2971             if (trustedCert != null) {
2972                 try {
2973                     cert.verify(trustedCert.getPublicKey());
2974                     return trustedCert;
2975                 } catch (Exception e) {
2976                     // Not verified, skip to the next one
2977                 }
2978             }
2979         }
2980         return null;
2981     }
2982 
2983     /**
2984      * Gets an X.500 name suitable for inclusion in a certification request.
2985      */
2986     private X500Name getX500Name() throws IOException {
2987         BufferedReader in;
2988         in = new BufferedReader(new InputStreamReader(System.in));
2989         String commonName = "Unknown";
2990         String organizationalUnit = "Unknown";
2991         String organization = "Unknown";
2992         String city = "Unknown";
2993         String state = "Unknown";
2994         String country = "Unknown";


3218             }
3219         }
3220 
3221         return Pair.of(entry, pkey);
3222     }
3223     /**
3224      * Gets the requested finger print of the certificate.
3225      */
3226     private String getCertFingerPrint(String mdAlg, Certificate cert)
3227         throws Exception
3228     {
3229         byte[] encCertInfo = cert.getEncoded();
3230         MessageDigest md = MessageDigest.getInstance(mdAlg);
3231         byte[] digest = md.digest(encCertInfo);
3232         return toHexString(digest);
3233     }
3234 
3235     /**
3236      * Prints warning about missing integrity check.
3237      */
3238     private void printWarning() {
3239         System.err.println();
3240         System.err.println(rb.getString
3241             (".WARNING.WARNING.WARNING."));
3242         System.err.println(rb.getString
3243             (".The.integrity.of.the.information.stored.in.your.keystore."));
3244         System.err.println(rb.getString
3245             (".WARNING.WARNING.WARNING."));
3246         System.err.println();
3247     }
3248 
3249     /**
3250      * Validates chain in certification reply, and returns the ordered
3251      * elements of the chain (with user certificate first, and root
3252      * certificate last in the array).
3253      *
3254      * @param alias the alias name
3255      * @param userCert the user certificate of the alias
3256      * @param replyCerts the chain provided in the reply
3257      */
3258     private Certificate[] validateReply(String alias,
3259                                         Certificate userCert,
3260                                         Certificate[] replyCerts)
3261         throws Exception
3262     {



3263         // order the certs in the reply (bottom-up).
3264         // we know that all certs in the reply are of type X.509, because
3265         // we parsed them using an X.509 certificate factory
3266         int i;
3267         PublicKey userPubKey = userCert.getPublicKey();
3268         for (i=0; i<replyCerts.length; i++) {
3269             if (userPubKey.equals(replyCerts[i].getPublicKey())) {
3270                 break;
3271             }
3272         }
3273         if (i == replyCerts.length) {
3274             MessageFormat form = new MessageFormat(rb.getString
3275                 ("Certificate.reply.does.not.contain.public.key.for.alias."));
3276             Object[] source = {alias};
3277             throw new Exception(form.format(source));
3278         }
3279 
3280         Certificate tmpCert = replyCerts[0];
3281         replyCerts[0] = replyCerts[i];
3282         replyCerts[i] = tmpCert;


3290                 if (signedBy(thisCert, (X509Certificate)replyCerts[j])) {
3291                     tmpCert = replyCerts[i];
3292                     replyCerts[i] = replyCerts[j];
3293                     replyCerts[j] = tmpCert;
3294                     thisCert = (X509Certificate)replyCerts[i];
3295                     break;
3296                 }
3297             }
3298             if (j == replyCerts.length) {
3299                 throw new Exception
3300                     (rb.getString("Incomplete.certificate.chain.in.reply"));
3301             }
3302         }
3303 
3304         if (noprompt) {
3305             return replyCerts;
3306         }
3307 
3308         // do we trust the cert at the top?
3309         Certificate topCert = replyCerts[replyCerts.length-1];
3310         Certificate root = getTrustedSigner(topCert, keyStore);

3311         if (root == null && trustcacerts && caks != null) {
3312             root = getTrustedSigner(topCert, caks);

3313         }
3314         if (root == null) {
3315             System.err.println();
3316             System.err.println
3317                     (rb.getString("Top.level.certificate.in.reply."));
3318             printX509Cert((X509Certificate)topCert, System.out);
3319             System.err.println();
3320             System.err.print(rb.getString(".is.not.trusted."));

3321             String reply = getYesNoReply
3322                     (rb.getString("Install.reply.anyway.no."));
3323             if ("NO".equals(reply)) {
3324                 return null;
3325             }
3326         } else {
3327             if (root != topCert) {
3328                 // append the root CA cert to the chain
3329                 Certificate[] tmpCerts =
3330                     new Certificate[replyCerts.length+1];
3331                 System.arraycopy(replyCerts, 0, tmpCerts, 0,
3332                                  replyCerts.length);
3333                 tmpCerts[tmpCerts.length-1] = root;
3334                 replyCerts = tmpCerts;





3335             }
3336         }
3337 
3338         return replyCerts;
3339     }
3340 
3341     /**
3342      * Establishes a certificate chain (using trusted certificates in the
3343      * keystore), starting with the user certificate
3344      * and ending at a self-signed certificate found in the keystore.
3345      *
3346      * @param userCert the user certificate of the alias
3347      * @param certToVerify the single certificate provided in the reply




3348      */
3349     private Certificate[] establishCertChain(Certificate userCert,
3350                                              Certificate certToVerify)
3351         throws Exception
3352     {
3353         if (userCert != null) {
3354             // Make sure that the public key of the certificate reply matches
3355             // the original public key in the keystore
3356             PublicKey origPubKey = userCert.getPublicKey();
3357             PublicKey replyPubKey = certToVerify.getPublicKey();
3358             if (!origPubKey.equals(replyPubKey)) {
3359                 throw new Exception(rb.getString
3360                         ("Public.keys.in.reply.and.keystore.don.t.match"));
3361             }
3362 
3363             // If the two certs are identical, we're done: no need to import
3364             // anything
3365             if (certToVerify.equals(userCert)) {
3366                 throw new Exception(rb.getString
3367                         ("Certificate.reply.and.certificate.in.keystore.are.identical"));
3368             }
3369         }
3370 
3371         // Build a hash table of all certificates in the keystore.
3372         // Use the subject distinguished name as the key into the hash table.
3373         // All certificates associated with the same subject distinguished
3374         // name are stored in the same hash table entry as a vector.
3375         Hashtable<Principal, Vector<Certificate>> certs = null;
3376         if (keyStore.size() > 0) {
3377             certs = new Hashtable<Principal, Vector<Certificate>>(11);
3378             keystorecerts2Hashtable(keyStore, certs);
3379         }
3380         if (trustcacerts) {
3381             if (caks!=null && caks.size()>0) {
3382                 if (certs == null) {
3383                     certs = new Hashtable<Principal, Vector<Certificate>>(11);
3384                 }
3385                 keystorecerts2Hashtable(caks, certs);
3386             }
3387         }
3388 
3389         // start building chain
3390         Vector<Certificate> chain = new Vector<>(2);
3391         if (buildChain((X509Certificate)certToVerify, chain, certs)) {
3392             Certificate[] newChain = new Certificate[chain.size()];







3393             // buildChain() returns chain with self-signed root-cert first and
3394             // user-cert last, so we need to invert the chain before we store
3395             // it
3396             int j=0;
3397             for (int i=chain.size()-1; i>=0; i--) {
3398                 newChain[j] = chain.elementAt(i);
3399                 j++;
3400             }
3401             return newChain;
3402         } else {
3403             throw new Exception
3404                 (rb.getString("Failed.to.establish.chain.from.reply"));
3405         }
3406     }
3407 
3408     /**
3409      * Recursively tries to establish chain from pool of trusted certs.










3410      *
3411      * @param certToVerify the cert that needs to be verified.
3412      * @param chain the chain that's being built.
3413      * @param certs the pool of trusted certs
3414      *
3415      * @return true if successful, false otherwise.
3416      */
3417     private boolean buildChain(X509Certificate certToVerify,
3418                         Vector<Certificate> chain,
3419                         Hashtable<Principal, Vector<Certificate>> certs) {
3420         Principal issuer = certToVerify.getIssuerDN();
3421         if (isSelfSigned(certToVerify)) {
3422             // reached self-signed root cert;
3423             // no verification needed because it's trusted.
3424             chain.addElement(certToVerify);
3425             return true;
3426         }
3427 


3428         // Get the issuer's certificate(s)
3429         Vector<Certificate> vec = certs.get(issuer);
3430         if (vec == null) {
3431             return false;
3432         }
3433 
3434         // Try out each certificate in the vector, until we find one
3435         // whose public key verifies the signature of the certificate
3436         // in question.
3437         for (Enumeration<Certificate> issuerCerts = vec.elements();
3438              issuerCerts.hasMoreElements(); ) {
3439             X509Certificate issuerCert
3440                 = (X509Certificate)issuerCerts.nextElement();
3441             PublicKey issuerPubKey = issuerCert.getPublicKey();
3442             try {
3443                 certToVerify.verify(issuerPubKey);
3444             } catch (Exception e) {
3445                 continue;
3446             }
3447             if (buildChain(issuerCert, chain, certs)) {
3448                 chain.addElement(certToVerify);
3449                 return true;
3450             }
3451         }
3452         return false;
3453     }
3454 
3455     /**
3456      * Prompts user for yes/no decision.
3457      *
3458      * @return the user's decision, can only be "YES" or "NO"
3459      */
3460     private String getYesNoReply(String prompt)
3461         throws IOException
3462     {
3463         String reply = null;


3472             reply = (new BufferedReader(new InputStreamReader
3473                                         (System.in))).readLine();
3474             if (collator.compare(reply, "") == 0 ||
3475                 collator.compare(reply, rb.getString("n")) == 0 ||
3476                 collator.compare(reply, rb.getString("no")) == 0) {
3477                 reply = "NO";
3478             } else if (collator.compare(reply, rb.getString("y")) == 0 ||
3479                        collator.compare(reply, rb.getString("yes")) == 0) {
3480                 reply = "YES";
3481             } else {
3482                 System.err.println(rb.getString("Wrong.answer.try.again"));
3483                 reply = null;
3484             }
3485         } while (reply == null);
3486         return reply;
3487     }
3488 
3489     /**
3490      * Stores the (leaf) certificates of a keystore in a hashtable.
3491      * All certs belonging to the same CA are stored in a vector that
3492      * in turn is stored in the hashtable, keyed by the CA's subject DN

3493      */
3494     private void keystorecerts2Hashtable(KeyStore ks,
3495                 Hashtable<Principal, Vector<Certificate>> hash)
3496         throws Exception {
3497 
3498         for (Enumeration<String> aliases = ks.aliases();
3499                                         aliases.hasMoreElements(); ) {
3500             String alias = aliases.nextElement();
3501             Certificate cert = ks.getCertificate(alias);
3502             if (cert != null) {
3503                 Principal subjectDN = ((X509Certificate)cert).getSubjectDN();
3504                 Vector<Certificate> vec = hash.get(subjectDN);







3505                 if (vec == null) {
3506                     vec = new Vector<Certificate>();
3507                     vec.addElement(cert);
3508                 } else {
3509                     if (!vec.contains(cert)) {
3510                         vec.addElement(cert);
3511                     }
3512                 }
3513                 hash.put(subjectDN, vec);
3514             }
3515         }
3516     }
3517 
3518     /**
3519      * Returns the issue time that's specified the -startdate option
3520      * @param s the value of -startdate option
3521      */
3522     private static Date getStartDate(String s) throws IOException {
3523         Calendar c = new GregorianCalendar();
3524         if (s != null) {
3525             IOException ioe = new IOException(
3526                     rb.getString("Illegal.startdate.value"));
3527             int len = s.length();
3528             if (len == 0) {
3529                 throw ioe;
3530             }


4061                                         .toByteArray()));
4062                         break;
4063                     default:
4064                         throw new Exception(rb.getString(
4065                                 "Unknown.extension.type.") + extstr);
4066                 }
4067             }
4068             // always non-critical
4069             ext.set(SubjectKeyIdentifierExtension.NAME,
4070                     new SubjectKeyIdentifierExtension(
4071                         new KeyIdentifier(pkey).getIdentifier()));
4072             if (akey != null && !pkey.equals(akey)) {
4073                 ext.set(AuthorityKeyIdentifierExtension.NAME,
4074                         new AuthorityKeyIdentifierExtension(
4075                         new KeyIdentifier(akey), null, null));
4076             }
4077         } catch(IOException e) {
4078             throw new RuntimeException(e);
4079         }
4080         return ext;











































































4081     }
4082 
4083     /**
4084      * Prints the usage of this tool.
4085      */
4086     private void usage() {
4087         if (command != null) {
4088             System.err.println("keytool " + command +
4089                     rb.getString(".OPTION."));
4090             System.err.println();
4091             System.err.println(rb.getString(command.description));
4092             System.err.println();
4093             System.err.println(rb.getString("Options."));
4094             System.err.println();
4095 
4096             // Left and right sides of the options list
4097             String[] left = new String[command.options.length];
4098             String[] right = new String[command.options.length];
4099 
4100             // Check if there's an unknown option


   1 /*
   2  * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  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.nio.file.Files;
  30 import java.nio.file.Paths;
  31 import java.security.CodeSigner;
  32 import java.security.CryptoPrimitive;
  33 import java.security.KeyStore;
  34 import java.security.KeyStoreException;
  35 import java.security.MessageDigest;
  36 import java.security.Key;
  37 import java.security.PublicKey;
  38 import java.security.PrivateKey;
  39 import java.security.Security;
  40 import java.security.Signature;
  41 import java.security.Timestamp;
  42 import java.security.UnrecoverableEntryException;
  43 import java.security.UnrecoverableKeyException;
  44 import java.security.NoSuchAlgorithmException;
  45 import java.security.Principal;
  46 import java.security.Provider;
  47 import java.security.cert.Certificate;
  48 import java.security.cert.CertificateFactory;
  49 import java.security.cert.CertStoreException;
  50 import java.security.cert.CRL;
  51 import java.security.cert.X509Certificate;
  52 import java.security.cert.CertificateException;
  53 import java.text.Collator;
  54 import java.text.MessageFormat;
  55 import java.util.*;
  56 import java.util.jar.JarEntry;
  57 import java.util.jar.JarFile;
  58 import java.lang.reflect.Constructor;
  59 import java.math.BigInteger;
  60 import java.net.URI;
  61 import java.net.URL;
  62 import java.net.URLClassLoader;
  63 import java.security.cert.CertStore;
  64 
  65 import java.security.cert.X509CRL;
  66 import java.security.cert.X509CRLEntry;
  67 import java.security.cert.X509CRLSelector;
  68 import javax.security.auth.x500.X500Principal;
  69 import java.util.Base64;
  70 
  71 import sun.security.util.DisabledAlgorithmConstraints;
  72 import sun.security.util.KeyUtil;
  73 import sun.security.util.ObjectIdentifier;
  74 import sun.security.pkcs10.PKCS10;
  75 import sun.security.pkcs10.PKCS10Attribute;
  76 import sun.security.provider.X509Factory;
  77 import sun.security.provider.certpath.CertStoreHelper;
  78 import sun.security.util.Password;
  79 import sun.security.util.SecurityProviderConstants;
  80 import javax.crypto.KeyGenerator;
  81 import javax.crypto.SecretKey;
  82 import javax.crypto.SecretKeyFactory;
  83 import javax.crypto.spec.PBEKeySpec;
  84 
  85 import sun.security.pkcs.PKCS9Attribute;
  86 import sun.security.tools.KeyStoreUtil;
  87 import sun.security.tools.PathList;
  88 import sun.security.util.DerValue;
  89 import sun.security.util.Pem;
  90 import sun.security.x509.*;
  91 
  92 import static java.security.KeyStore.*;
  93 import static sun.security.tools.keytool.Main.Command.*;
  94 import static sun.security.tools.keytool.Main.Option.*;
  95 
  96 /**
  97  * This tool manages keystores.
  98  *
  99  * @author Jan Luehe


 137     private String providerName = null;
 138     private String pathlist = null;
 139     private char[] storePass = null;
 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 nowarn = false;
 158     private boolean protectedPath = false;
 159     private boolean srcprotectedPath = false;
 160     private CertificateFactory cf = null;
 161     private KeyStore caks = null; // "cacerts" keystore
 162     private char[] srcstorePass = null;
 163     private String srcstoretype = null;
 164     private Set<char[]> passwords = new HashSet<>();
 165     private String startDate = null;
 166 
 167     private List<String> ids = new ArrayList<>();   // used in GENCRL
 168     private List<String> v3ext = new ArrayList<>();
 169 
 170     // In-place importkeystore is special.
 171     // A backup is needed, and no need to prompt for deststorepass.
 172     private boolean inplaceImport = false;
 173     private String inplaceBackupName = null;
 174 
 175     // Warnings on weak algorithms etc
 176     private List<String> weakWarnings = new ArrayList<>();
 177 
 178     private static final DisabledAlgorithmConstraints DISABLED_CHECK =
 179             new DisabledAlgorithmConstraints(
 180                     DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
 181 
 182     private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET = Collections
 183             .unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
 184 
 185     enum Command {
 186         CERTREQ("Generates.a.certificate.request",
 187             ALIAS, SIGALG, FILEOUT, KEYPASS, KEYSTORE, DNAME,
 188             STOREPASS, STORETYPE, PROVIDERNAME, PROVIDERCLASS,
 189             PROVIDERARG, PROVIDERPATH, V, PROTECTED),
 190         CHANGEALIAS("Changes.an.entry.s.alias",
 191             ALIAS, DESTALIAS, KEYPASS, KEYSTORE, STOREPASS,
 192             STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
 193             PROVIDERPATH, V, PROTECTED),
 194         DELETE("Deletes.an.entry",
 195             ALIAS, KEYSTORE, STOREPASS, STORETYPE,
 196             PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
 197             PROVIDERPATH, V, PROTECTED),
 198         EXPORTCERT("Exports.certificate",
 199             RFC, ALIAS, FILEOUT, KEYSTORE, STOREPASS,
 200             STORETYPE, PROVIDERNAME, PROVIDERCLASS, PROVIDERARG,
 201             PROVIDERPATH, V, PROTECTED),
 202         GENKEYPAIR("Generates.a.key.pair",
 203             ALIAS, KEYALG, KEYSIZE, SIGALG, DESTALIAS, DNAME,
 204             STARTDATE, EXT, VALIDITY, KEYPASS, KEYSTORE,


 323         V("v", null, "verbose.output"),
 324         VALIDITY("validity", "<valDays>", "validity.number.of.days");
 325 
 326         final String name, arg, description;
 327         Option(String name, String arg, String description) {
 328             this.name = name;
 329             this.arg = arg;
 330             this.description = description;
 331         }
 332         @Override
 333         public String toString() {
 334             return "-" + name;
 335         }
 336     };
 337 
 338     private static final Class<?>[] PARAM_STRING = { String.class };
 339 
 340     private static final String NONE = "NONE";
 341     private static final String P11KEYSTORE = "PKCS11";
 342     private static final String P12KEYSTORE = "PKCS12";
 343     private static final String keyAlias = "mykey";
 344 
 345     // for i18n
 346     private static final java.util.ResourceBundle rb =
 347         java.util.ResourceBundle.getBundle(
 348             "sun.security.tools.keytool.Resources");
 349     private static final Collator collator = Collator.getInstance();
 350     static {
 351         // this is for case insensitive string comparisons
 352         collator.setStrength(Collator.PRIMARY);
 353     };
 354 
 355     private Main() { }
 356 
 357     public static void main(String[] args) throws Exception {
 358         Main kt = new Main();
 359         kt.run(args, System.out);
 360     }
 361 
 362     private void run(String[] args, PrintStream out) throws Exception {
 363         try {
 364             parseArgs(args);
 365             if (command != null) {
 366                 doCommands(out);
 367             }
 368         } catch (Exception e) {
 369             System.out.println(rb.getString("keytool.error.") + e);
 370             if (verbose) {
 371                 e.printStackTrace(System.out);
 372             }
 373             if (!debug) {
 374                 System.exit(1);
 375             } else {
 376                 throw e;
 377             }
 378         } finally {
 379             printWeakWarnings(false);
 380             for (char[] pass : passwords) {
 381                 if (pass != null) {
 382                     Arrays.fill(pass, ' ');
 383                     pass = null;
 384                 }
 385             }
 386 
 387             if (ksStream != null) {
 388                 ksStream.close();
 389             }
 390         }
 391     }
 392 
 393     /**
 394      * Parse command line arguments.
 395      */
 396     void parseArgs(String[] args) {
 397 
 398         int i=0;
 399         boolean help = args.length == 0;


 427              */
 428             boolean isCommand = false;
 429             for (Command c: Command.values()) {
 430                 if (collator.compare(flags, c.toString()) == 0) {
 431                     command = c;
 432                     isCommand = true;
 433                     break;
 434                 }
 435             }
 436 
 437             if (isCommand) {
 438                 // already recognized as a command
 439             } else if (collator.compare(flags, "-export") == 0) {
 440                 command = EXPORTCERT;
 441             } else if (collator.compare(flags, "-genkey") == 0) {
 442                 command = GENKEYPAIR;
 443             } else if (collator.compare(flags, "-import") == 0) {
 444                 command = IMPORTCERT;
 445             } else if (collator.compare(flags, "-importpassword") == 0) {
 446                 command = IMPORTPASS;
 447             } else if (collator.compare(flags, "-help") == 0) {




 448                 help = true;
 449             } else if (collator.compare(flags, "-nowarn") == 0) {
 450                 nowarn = true;
 451             }
 452 
 453             /*
 454              * specifiers
 455              */
 456             else if (collator.compare(flags, "-keystore") == 0 ||
 457                     collator.compare(flags, "-destkeystore") == 0) {
 458                 ksfname = args[++i];
 459             } else if (collator.compare(flags, "-storepass") == 0 ||
 460                     collator.compare(flags, "-deststorepass") == 0) {
 461                 storePass = getPass(modifier, args[++i]);
 462                 passwords.add(storePass);
 463             } else if (collator.compare(flags, "-storetype") == 0 ||
 464                     collator.compare(flags, "-deststoretype") == 0) {
 465                 storetype = args[++i];
 466             } else if (collator.compare(flags, "-srcstorepass") == 0) {
 467                 srcstorePass = getPass(modifier, args[++i]);
 468                 passwords.add(srcstorePass);
 469             } else if (collator.compare(flags, "-srcstoretype") == 0) {
 470                 srcstoretype = args[++i];


 718         if (command == LIST && verbose && rfc) {
 719             System.err.println(rb.getString
 720                 ("Must.not.specify.both.v.and.rfc.with.list.command"));
 721             tinyHelp();
 722         }
 723 
 724         // Make sure provided passwords are at least 6 characters long
 725         if (command == GENKEYPAIR && keyPass!=null && keyPass.length < 6) {
 726             throw new Exception(rb.getString
 727                 ("Key.password.must.be.at.least.6.characters"));
 728         }
 729         if (newPass != null && newPass.length < 6) {
 730             throw new Exception(rb.getString
 731                 ("New.password.must.be.at.least.6.characters"));
 732         }
 733         if (destKeyPass != null && destKeyPass.length < 6) {
 734             throw new Exception(rb.getString
 735                 ("New.password.must.be.at.least.6.characters"));
 736         }
 737 
 738         // Set this before inplaceImport check so we can compare name.
 739         if (ksfname == null) {
 740             ksfname = System.getProperty("user.home") + File.separator
 741                     + ".keystore";
 742         }
 743 
 744         KeyStore srcKeyStore = null;
 745         if (command == IMPORTKEYSTORE) {
 746             inplaceImport = inplaceImportCheck();
 747             if (inplaceImport) {
 748                 // We load srckeystore first so we have srcstorePass that
 749                 // can be assigned to storePass
 750                 srcKeyStore = loadSourceKeyStore();
 751                 if (storePass == null) {
 752                     storePass = srcstorePass;
 753                 }
 754             }
 755         }
 756 
 757         // Check if keystore exists.
 758         // If no keystore has been specified at the command line, try to use
 759         // the default, which is located in $HOME/.keystore.
 760         // If the command is "genkey", "identitydb", "import", or "printcert",
 761         // it is OK not to have a keystore.





 762 
 763         // DO NOT open the existing keystore if this is an in-place import.
 764         // The keystore should be created as brand new.
 765         if (isKeyStoreRelated(command) && !nullStream && !inplaceImport) {
 766                 try {
 767                     ksfile = new File(ksfname);
 768                     // Check if keystore file is empty
 769                     if (ksfile.exists() && ksfile.length() == 0) {
 770                         throw new Exception(rb.getString
 771                         ("Keystore.file.exists.but.is.empty.") + ksfname);
 772                     }
 773                     ksStream = new FileInputStream(ksfile);
 774                 } catch (FileNotFoundException e) {
 775                     if (command != GENKEYPAIR &&
 776                         command != GENSECKEY &&
 777                         command != IDENTITYDB &&
 778                         command != IMPORTCERT &&
 779                         command != IMPORTPASS &&
 780                         command != IMPORTKEYSTORE &&
 781                         command != PRINTCRL) {
 782                         throw new Exception(rb.getString
 783                                 ("Keystore.file.does.not.exist.") + ksfname);
 784                     }
 785                 }
 786             }

 787 
 788         if ((command == KEYCLONE || command == CHANGEALIAS)
 789                 && dest == null) {
 790             dest = getAlias("destination");
 791             if ("".equals(dest)) {
 792                 throw new Exception(rb.getString
 793                         ("Must.specify.destination.alias"));
 794             }
 795         }
 796 
 797         if (command == DELETE && alias == null) {
 798             alias = getAlias(null);
 799             if ("".equals(alias)) {
 800                 throw new Exception(rb.getString("Must.specify.alias"));
 801             }
 802         }
 803 
 804         // Create new keystore
 805         if (providerName == null) {
 806             keyStore = KeyStore.getInstance(storetype);


 812          * Load the keystore data.
 813          *
 814          * At this point, it's OK if no keystore password has been provided.
 815          * We want to make sure that we can load the keystore data, i.e.,
 816          * the keystore data has the right format. If we cannot load the
 817          * keystore, why bother asking the user for his or her password?
 818          * Only if we were able to load the keystore, and no keystore
 819          * password has been provided, will we prompt the user for the
 820          * keystore password to verify the keystore integrity.
 821          * This means that the keystore is loaded twice: first load operation
 822          * checks the keystore format, second load operation verifies the
 823          * keystore integrity.
 824          *
 825          * If the keystore password has already been provided (at the
 826          * command line), however, the keystore is loaded only once, and the
 827          * keystore format and integrity are checked "at the same time".
 828          *
 829          * Null stream keystores are loaded later.
 830          */
 831         if (!nullStream) {
 832             if (inplaceImport) {
 833                 keyStore.load(null, storePass);
 834             } else {
 835             keyStore.load(ksStream, storePass);
 836             }
 837             if (ksStream != null) {
 838                 ksStream.close();
 839             }
 840         }
 841 
 842         // All commands that create or modify the keystore require a keystore
 843         // password.
 844 
 845         if (nullStream && storePass != null) {
 846             keyStore.load(null, storePass);
 847         } else if (!nullStream && storePass != null) {
 848             // If we are creating a new non nullStream-based keystore,
 849             // insist that the password be at least 6 characters
 850             if (ksStream == null && storePass.length < 6) {
 851                 throw new Exception(rb.getString
 852                         ("Keystore.password.must.be.at.least.6.characters"));
 853             }
 854         } else if (storePass == null) {
 855 
 856             // only prompt if (protectedPath == false)


 944                 keyPass = storePass;
 945             }
 946             if (newPass != null && !Arrays.equals(storePass, newPass)) {
 947                 Object[] source = {"-new"};
 948                 System.err.println(form.format(source));
 949                 newPass = storePass;
 950             }
 951             if (destKeyPass != null && !Arrays.equals(storePass, destKeyPass)) {
 952                 Object[] source = {"-destkeypass"};
 953                 System.err.println(form.format(source));
 954                 destKeyPass = storePass;
 955             }
 956         }
 957 
 958         // Create a certificate factory
 959         if (command == PRINTCERT || command == IMPORTCERT
 960                 || command == IDENTITYDB || command == PRINTCRL) {
 961             cf = CertificateFactory.getInstance("X509");
 962         }
 963 
 964         // -trustcacerts can only be specified on -importcert.
 965         // Reset it so that warnings on CA cert will remain for
 966         // -printcert, etc.
 967         if (command != IMPORTCERT) {
 968             trustcacerts = false;
 969         }
 970 
 971         if (trustcacerts) {
 972             caks = KeyStoreUtil.getCacertsKeyStore();
 973         }
 974 
 975         // Perform the specified command
 976         if (command == CERTREQ) {
 977             if (filename != null) {
 978                 try (PrintStream ps = new PrintStream(new FileOutputStream
 979                                                       (filename))) {
 980                     doCertReq(alias, sigAlgName, ps);
 981                 }
 982             } else {
 983                 doCertReq(alias, sigAlgName, out);
 984             }
 985             if (verbose && filename != null) {
 986                 MessageFormat form = new MessageFormat(rb.getString
 987                         ("Certification.request.stored.in.file.filename."));
 988                 Object[] source = {filename};
 989                 System.err.println(form.format(source));
 990                 System.err.println(rb.getString("Submit.this.to.your.CA"));


1052                             ("Certificate.reply.was.not.installed.in.keystore"));
1053                     }
1054                 } else if (!keyStore.containsAlias(importAlias) ||
1055                         keyStore.entryInstanceOf(importAlias,
1056                             KeyStore.TrustedCertificateEntry.class)) {
1057                     kssave = addTrustedCert(importAlias, inStream);
1058                     if (kssave) {
1059                         System.err.println(rb.getString
1060                             ("Certificate.was.added.to.keystore"));
1061                     } else {
1062                         System.err.println(rb.getString
1063                             ("Certificate.was.not.added.to.keystore"));
1064                     }
1065                 }
1066             } finally {
1067                 if (inStream != System.in) {
1068                     inStream.close();
1069                 }
1070             }
1071         } else if (command == IMPORTKEYSTORE) {
1072             // When not in-place import, srcKeyStore is not loaded yet.
1073             if (srcKeyStore == null) {
1074                 srcKeyStore = loadSourceKeyStore();
1075             }
1076             doImportKeyStore(srcKeyStore);
1077             kssave = true;
1078         } else if (command == KEYCLONE) {
1079             keyPassNew = newPass;
1080 
1081             // added to make sure only key can go thru
1082             if (alias == null) {
1083                 alias = keyAlias;
1084             }
1085             if (keyStore.containsAlias(alias) == false) {
1086                 MessageFormat form = new MessageFormat
1087                     (rb.getString("Alias.alias.does.not.exist"));
1088                 Object[] source = {alias};
1089                 throw new Exception(form.format(source));
1090             }
1091             if (!keyStore.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)) {
1092                 MessageFormat form = new MessageFormat(rb.getString(
1093                         "Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key"));
1094                 Object[] source = {alias};
1095                 throw new Exception(form.format(source));
1096             }
1097 
1098             doCloneEntry(alias, dest, true);  // Now everything can be cloned
1099             kssave = true;
1100         } else if (command == CHANGEALIAS) {
1101             if (alias == null) {
1102                 alias = keyAlias;
1103             }
1104             doCloneEntry(alias, dest, false);
1105             // in PKCS11, clone a PrivateKeyEntry will delete the old one
1106             if (keyStore.containsAlias(alias)) {
1107                 doDeleteEntry(alias);
1108             }
1109             kssave = true;
1110         } else if (command == KEYPASSWD) {
1111             keyPassNew = newPass;
1112             doChangeKeyPasswd(alias);
1113             kssave = true;
1114         } else if (command == LIST) {
1115             if (storePass == null
1116                     && !KeyStoreUtil.isWindowsKeyStore(storetype)) {
1117                 printNoIntegrityWarning();
1118             }
1119 
1120             if (alias != null) {
1121                 doPrintEntry(rb.getString("the.certificate"), alias, out);
1122             } else {
1123                 doPrintEntries(out);
1124             }
1125         } else if (command == PRINTCERT) {
1126             doPrintCert(out);
1127         } else if (command == SELFCERT) {
1128             doSelfCert(alias, dname, sigAlgName);
1129             kssave = true;
1130         } else if (command == STOREPASSWD) {
1131             storePassNew = newPass;
1132             if (storePassNew == null) {
1133                 storePassNew = getNewPasswd("keystore password", storePass);
1134             }
1135             kssave = true;
1136         } else if (command == GENCERT) {
1137             if (alias == null) {
1138                 alias = keyAlias;
1139             }
1140             InputStream inStream = System.in;
1141             if (infilename != null) {


1187                         (rb.getString(".Storing.ksfname."));
1188                 Object[] source = {nullStream ? "keystore" : ksfname};
1189                 System.err.println(form.format(source));
1190             }
1191 
1192             if (token) {
1193                 keyStore.store(null, null);
1194             } else {
1195                 char[] pass = (storePassNew!=null) ? storePassNew : storePass;
1196                 if (nullStream) {
1197                     keyStore.store(null, pass);
1198                 } else {
1199                     ByteArrayOutputStream bout = new ByteArrayOutputStream();
1200                     keyStore.store(bout, pass);
1201                     try (FileOutputStream fout = new FileOutputStream(ksfname)) {
1202                         fout.write(bout.toByteArray());
1203                     }
1204                 }
1205             }
1206         }
1207 
1208         if (isKeyStoreRelated(command)
1209                 && !token && !nullStream && ksfname != null) {
1210 
1211             // JKS storetype warning on the final result keystore
1212             File f = new File(ksfname);
1213             if (f.exists()) {
1214                 // Read the first 4 bytes to determine
1215                 // if we're dealing with JKS/JCEKS type store
1216                 String realType = keyStoreType(f);
1217                 if (realType.equalsIgnoreCase("JKS")
1218                     || realType.equalsIgnoreCase("JCEKS")) {
1219                     boolean allCerts = true;
1220                     for (String a : Collections.list(keyStore.aliases())) {
1221                         if (!keyStore.entryInstanceOf(
1222                                 a, TrustedCertificateEntry.class)) {
1223                             allCerts = false;
1224                             break;
1225                         }
1226                     }
1227                     // Don't warn for "cacerts" style keystore.
1228                     if (!allCerts) {
1229                         weakWarnings.add(String.format(
1230                                 rb.getString("jks.storetype.warning"),
1231                                 realType, ksfname));
1232                     }
1233                 }
1234                 if (inplaceImport) {
1235                     String realSourceStoreType =
1236                         keyStoreType(new File(inplaceBackupName));
1237                     String format =
1238                             realType.equalsIgnoreCase(realSourceStoreType) ?
1239                             rb.getString("backup.keystore.warning") :
1240                             rb.getString("migrate.keystore.warning");
1241                     weakWarnings.add(
1242                             String.format(format,
1243                                     srcksfname,
1244                                     realSourceStoreType,
1245                                     inplaceBackupName,
1246                                     realType));
1247                 }
1248             }
1249         }
1250     }
1251 
1252     private String keyStoreType(File f) throws IOException {
1253         int MAGIC = 0xfeedfeed;
1254         int JCEKS_MAGIC = 0xcececece;
1255         try (DataInputStream dis = new DataInputStream(
1256             new FileInputStream(f))) {
1257             int xMagic = dis.readInt();
1258             if (xMagic == MAGIC) {
1259                 return "JKS";
1260             } else if (xMagic == JCEKS_MAGIC) {
1261                 return "JCEKS";
1262             } else {
1263                 return "Non JKS/JCEKS";
1264             }
1265         }
1266     }
1267 
1268     /**
1269      * Generate a certificate: Read PKCS10 request from in, and print
1270      * certificate to out. Use alias as CA, sigAlgName as the signature
1271      * type.
1272      */
1273     private void doGenCert(String alias, String sigAlgName, InputStream in, PrintStream out)
1274             throws Exception {
1275 
1276 
1277         if (keyStore.containsAlias(alias) == false) {
1278             MessageFormat form = new MessageFormat
1279                     (rb.getString("Alias.alias.does.not.exist"));
1280             Object[] source = {alias};
1281             throw new Exception(form.format(source));
1282         }
1283         Certificate signerCert = keyStore.getCertificate(alias);
1284         byte[] encoded = signerCert.getEncoded();
1285         X509CertImpl signerCertImpl = new X509CertImpl(encoded);
1286         X509CertInfo signerCertInfo = (X509CertInfo)signerCertImpl.get(
1287                 X509CertImpl.NAME + "." + X509CertImpl.INFO);
1288         X500Name issuer = (X500Name)signerCertInfo.get(X509CertInfo.SUBJECT + "." +
1289                                            X509CertInfo.DN_NAME);
1290 
1291         Date firstDate = getStartDate(startDate);
1292         Date lastDate = new Date();
1293         lastDate.setTime(firstDate.getTime() + validity*1000L*24L*60L*60L);
1294         CertificateValidity interval = new CertificateValidity(firstDate,
1295                                                                lastDate);
1296 
1297         PrivateKey privateKey =
1298                 (PrivateKey)recoverKey(alias, storePass, keyPass).fst;
1299         if (sigAlgName == null) {
1300             sigAlgName = getCompatibleSigAlgName(privateKey.getAlgorithm());
1301         }
1302         Signature signature = Signature.getInstance(sigAlgName);


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


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


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


1673 
1674         if (keyPass == null) {
1675             keyPass = promptForKeyPass(alias, null, storePass);
1676         }
1677 
1678         if (useDefaultPBEAlgorithm) {
1679             keyStore.setKeyEntry(alias, secKey, keyPass, null);
1680         } else {
1681             keyStore.setEntry(alias, new KeyStore.SecretKeyEntry(secKey),
1682                 new KeyStore.PasswordProtection(keyPass, keyAlgName, null));
1683         }
1684     }
1685 
1686     /**
1687      * If no signature algorithm was specified at the command line,
1688      * we choose one that is compatible with the selected private key
1689      */
1690     private static String getCompatibleSigAlgName(String keyAlgName)
1691             throws Exception {
1692         if ("DSA".equalsIgnoreCase(keyAlgName)) {
1693             return "SHA256WithDSA";
1694         } else if ("RSA".equalsIgnoreCase(keyAlgName)) {
1695             return "SHA256WithRSA";
1696         } else if ("EC".equalsIgnoreCase(keyAlgName)) {
1697             return "SHA256withECDSA";
1698         } else {
1699             throw new Exception(rb.getString
1700                     ("Cannot.derive.signature.algorithm"));
1701         }
1702     }
1703     /**
1704      * Creates a new key pair and self-signed certificate.
1705      */
1706     private void doGenKeyPair(String alias, String dname, String keyAlgName,
1707                               int keysize, String sigAlgName)
1708         throws Exception
1709     {
1710         if (keysize == -1) {
1711             if ("EC".equalsIgnoreCase(keyAlgName)) {
1712                 keysize = SecurityProviderConstants.DEF_EC_KEY_SIZE;
1713             } else if ("RSA".equalsIgnoreCase(keyAlgName)) {
1714                 // hardcode for now as DEF_RSA_KEY_SIZE is still 1024
1715                 keysize = 2048; // SecurityProviderConstants.DEF_RSA_KEY_SIZE;
1716             } else if ("DSA".equalsIgnoreCase(keyAlgName)) {
1717                 // hardcode for now as DEF_DSA_KEY_SIZE is still 1024
1718                 keysize = 2048;


1719             }
1720         }
1721 
1722         if (alias == null) {
1723             alias = keyAlias;
1724         }
1725 
1726         if (keyStore.containsAlias(alias)) {
1727             MessageFormat form = new MessageFormat(rb.getString
1728                 ("Key.pair.not.generated.alias.alias.already.exists"));
1729             Object[] source = {alias};
1730             throw new Exception(form.format(source));
1731         }
1732 
1733         if (sigAlgName == null) {
1734             sigAlgName = getCompatibleSigAlgName(keyAlgName);
1735         }
1736         CertAndKeyGen keypair =
1737                 new CertAndKeyGen(keyAlgName, sigAlgName, providerName);
1738 


1756                 null);
1757 
1758         X509Certificate[] chain = new X509Certificate[1];
1759         chain[0] = keypair.getSelfCertificate(
1760                 x500Name, getStartDate(startDate), validity*24L*60L*60L, ext);
1761 
1762         if (verbose) {
1763             MessageFormat form = new MessageFormat(rb.getString
1764                 ("Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for"));
1765             Object[] source = {new Integer(keysize),
1766                                 privKey.getAlgorithm(),
1767                                 chain[0].getSigAlgName(),
1768                                 new Long(validity),
1769                                 x500Name};
1770             System.err.println(form.format(source));
1771         }
1772 
1773         if (keyPass == null) {
1774             keyPass = promptForKeyPass(alias, null, storePass);
1775         }
1776         checkWeak(rb.getString("the.generated.certificate"), chain[0]);
1777         keyStore.setKeyEntry(alias, privKey, keyPass, chain);
1778     }
1779 
1780     /**
1781      * Clones an entry
1782      * @param orig original alias
1783      * @param dest destination alias
1784      * @changePassword if the password can be changed
1785      */
1786     private void doCloneEntry(String orig, String dest, boolean changePassword)
1787         throws Exception
1788     {
1789         if (orig == null) {
1790             orig = keyAlias;
1791         }
1792 
1793         if (keyStore.containsAlias(dest)) {
1794             MessageFormat form = new MessageFormat
1795                 (rb.getString("Destination.alias.dest.already.exists"));
1796             Object[] source = {dest};


1839         }
1840         keyStore.setKeyEntry(alias, privKey, keyPassNew,
1841                              keyStore.getCertificateChain(alias));
1842     }
1843 
1844     /**
1845      * Imports a JDK 1.1-style identity database. We can only store one
1846      * certificate per identity, because we use the identity's name as the
1847      * alias (which references a keystore entry), and aliases must be unique.
1848      */
1849     private void doImportIdentityDatabase(InputStream in)
1850         throws Exception
1851     {
1852         System.err.println(rb.getString
1853             ("No.entries.from.identity.database.added"));
1854     }
1855 
1856     /**
1857      * Prints a single keystore entry.
1858      */
1859     private void doPrintEntry(String label, String alias, PrintStream out)

1860         throws Exception
1861     {





1862         if (keyStore.containsAlias(alias) == false) {
1863             MessageFormat form = new MessageFormat
1864                 (rb.getString("Alias.alias.does.not.exist"));
1865             Object[] source = {alias};
1866             throw new Exception(form.format(source));
1867         }
1868 
1869         if (verbose || rfc || debug) {
1870             MessageFormat form = new MessageFormat
1871                 (rb.getString("Alias.name.alias"));
1872             Object[] source = {alias};
1873             out.println(form.format(source));
1874 
1875             if (!token) {
1876                 form = new MessageFormat(rb.getString
1877                     ("Creation.date.keyStore.getCreationDate.alias."));
1878                 Object[] src = {keyStore.getCreationDate(alias)};
1879                 out.println(form.format(src));
1880             }
1881         } else {


1910             }
1911 
1912             // Get the chain
1913             Certificate[] chain = keyStore.getCertificateChain(alias);
1914             if (chain != null) {
1915                 if (verbose || rfc || debug) {
1916                     out.println(rb.getString
1917                         ("Certificate.chain.length.") + chain.length);
1918                     for (int i = 0; i < chain.length; i ++) {
1919                         MessageFormat form = new MessageFormat
1920                                 (rb.getString("Certificate.i.1."));
1921                         Object[] source = {new Integer((i + 1))};
1922                         out.println(form.format(source));
1923                         if (verbose && (chain[i] instanceof X509Certificate)) {
1924                             printX509Cert((X509Certificate)(chain[i]), out);
1925                         } else if (debug) {
1926                             out.println(chain[i].toString());
1927                         } else {
1928                             dumpCert(chain[i], out);
1929                         }
1930                         checkWeak(label, chain[i]);
1931                     }
1932                 } else {
1933                     // Print the digest of the user cert only
1934                     out.println
1935                         (rb.getString("Certificate.fingerprint.SHA1.") +
1936                         getCertFingerPrint("SHA1", chain[0]));
1937                     checkWeak(label, chain[0]);
1938                 }
1939             }
1940         } else if (keyStore.entryInstanceOf(alias,
1941                 KeyStore.TrustedCertificateEntry.class)) {
1942             // We have a trusted certificate entry
1943             Certificate cert = keyStore.getCertificate(alias);
1944             Object[] source = {"trustedCertEntry"};
1945             String mf = new MessageFormat(
1946                     rb.getString("Entry.type.type.")).format(source) + "\n";
1947             if (verbose && (cert instanceof X509Certificate)) {
1948                 out.println(mf);
1949                 printX509Cert((X509Certificate)cert, out);
1950             } else if (rfc) {
1951                 out.println(mf);
1952                 dumpCert(cert, out);
1953             } else if (debug) {
1954                 out.println(cert.toString());
1955             } else {
1956                 out.println("trustedCertEntry, ");
1957                 out.println(rb.getString("Certificate.fingerprint.SHA1.")
1958                             + getCertFingerPrint("SHA1", cert));
1959             }
1960             checkWeak(label, cert);
1961         } else {
1962             out.println(rb.getString("Unknown.Entry.Type"));
1963         }
1964     }
1965 
1966     boolean inplaceImportCheck() throws Exception {
1967         if (P11KEYSTORE.equalsIgnoreCase(srcstoretype) ||
1968                 KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
1969             return false;
1970         }
1971 
1972         if (srcksfname != null) {
1973             File srcksfile = new File(srcksfname);
1974             if (srcksfile.exists() && srcksfile.length() == 0) {
1975                 throw new Exception(rb.getString
1976                         ("Source.keystore.file.exists.but.is.empty.") +
1977                         srcksfname);
1978             }
1979             if (srcksfile.getCanonicalFile()
1980                     .equals(new File(ksfname).getCanonicalFile())) {
1981                 return true;
1982             } else {
1983                 // Informational, especially if destkeystore is not
1984                 // provided, which default to ~/.keystore.
1985                 System.err.println(String.format(rb.getString(
1986                         "importing.keystore.status"), srcksfname, ksfname));
1987                 return false;
1988             }
1989         } else {
1990             throw new Exception(rb.getString
1991                     ("Please.specify.srckeystore"));
1992         }
1993     }
1994 
1995     /**
1996      * Load the srckeystore from a stream, used in -importkeystore
1997      * @returns the src KeyStore
1998      */
1999     KeyStore loadSourceKeyStore() throws Exception {

2000 
2001         InputStream is = null;
2002         File srcksfile = null;
2003 
2004         if (P11KEYSTORE.equalsIgnoreCase(srcstoretype) ||
2005                 KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
2006             if (!NONE.equals(srcksfname)) {
2007                 System.err.println(MessageFormat.format(rb.getString
2008                     (".keystore.must.be.NONE.if.storetype.is.{0}"), srcstoretype));
2009                 System.err.println();
2010                 tinyHelp();
2011             }

2012         } else {
2013             srcksfile = new File(srcksfname);






2014                 is = new FileInputStream(srcksfile);




2015         }
2016 
2017         KeyStore store;
2018         try {
2019             if (srcProviderName == null) {
2020                 store = KeyStore.getInstance(srcstoretype);
2021             } else {
2022                 store = KeyStore.getInstance(srcstoretype, srcProviderName);
2023             }
2024 
2025             if (srcstorePass == null
2026                     && !srcprotectedPath
2027                     && !KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
2028                 System.err.print(rb.getString("Enter.source.keystore.password."));
2029                 System.err.flush();
2030                 srcstorePass = Password.readPassword(System.in);
2031                 passwords.add(srcstorePass);
2032             }
2033 
2034             // always let keypass be storepass when using pkcs12
2035             if (P12KEYSTORE.equalsIgnoreCase(srcstoretype)) {
2036                 if (srckeyPass != null && srcstorePass != null &&
2037                         !Arrays.equals(srcstorePass, srckeyPass)) {
2038                     MessageFormat form = new MessageFormat(rb.getString(
2039                         "Warning.Different.store.and.key.passwords.not.supported.for.PKCS12.KeyStores.Ignoring.user.specified.command.value."));
2040                     Object[] source = {"-srckeypass"};
2041                     System.err.println(form.format(source));
2042                     srckeyPass = srcstorePass;
2043                 }
2044             }
2045 
2046             store.load(is, srcstorePass);   // "is" already null in PKCS11
2047         } finally {
2048             if (is != null) {
2049                 is.close();
2050             }
2051         }
2052 
2053         if (srcstorePass == null
2054                 && !KeyStoreUtil.isWindowsKeyStore(srcstoretype)) {
2055             // anti refactoring, copied from printNoIntegrityWarning(),
2056             // but change 2 lines
2057             System.err.println();
2058             System.err.println(rb.getString
2059                 (".WARNING.WARNING.WARNING."));
2060             System.err.println(rb.getString
2061                 (".The.integrity.of.the.information.stored.in.the.srckeystore."));
2062             System.err.println(rb.getString
2063                 (".WARNING.WARNING.WARNING."));
2064             System.err.println();
2065         }
2066 
2067         return store;
2068     }
2069 
2070     /**
2071      * import all keys and certs from importkeystore.
2072      * keep alias unchanged if no name conflict, otherwise, prompt.
2073      * keep keypass unchanged for keys
2074      */
2075     private void doImportKeyStore(KeyStore srcKS) throws Exception {
2076 
2077         if (alias != null) {
2078             doImportKeyStoreSingle(srcKS, alias);
2079         } else {
2080             if (dest != null || srckeyPass != null) {
2081                 throw new Exception(rb.getString(
2082                         "if.alias.not.specified.destalias.and.srckeypass.must.not.be.specified"));
2083             }
2084             doImportKeyStoreAll(srcKS);
2085         }
2086 
2087         if (inplaceImport) {
2088             // Backup to file.old or file.old2...
2089             // The keystore is not rewritten yet now.
2090             for (int n = 1; /* forever */; n++) {
2091                 inplaceBackupName = srcksfname + ".old" + (n == 1 ? "" : n);
2092                 File bkFile = new File(inplaceBackupName);
2093                 if (!bkFile.exists()) {
2094                     Files.copy(Paths.get(srcksfname), bkFile.toPath());
2095                     break;
2096                 }
2097             }
2098 
2099         }
2100 
2101         /*
2102          * Information display rule of -importkeystore
2103          * 1. inside single, shows failure
2104          * 2. inside all, shows sucess
2105          * 3. inside all where there is a failure, prompt for continue
2106          * 4. at the final of all, shows summary
2107          */
2108     }
2109 
2110     /**
2111      * Import a single entry named alias from srckeystore
2112      * @returns 1 if the import action succeed
2113      *          0 if user choose to ignore an alias-dumplicated entry
2114      *          2 if setEntry throws Exception
2115      */
2116     private int doImportKeyStoreSingle(KeyStore srckeystore, String alias)
2117             throws Exception {
2118 
2119         String newAlias = (dest==null) ? alias : dest;
2120 


2141 
2142         Pair<Entry,char[]> objs = recoverEntry(srckeystore, alias, srcstorePass, srckeyPass);
2143         Entry entry = objs.fst;
2144 
2145         PasswordProtection pp = null;
2146 
2147         // According to keytool.html, "The destination entry will be protected
2148         // using destkeypass. If destkeypass is not provided, the destination
2149         // entry will be protected with the source entry password."
2150         // so always try to protect with destKeyPass.
2151         char[] newPass = null;
2152         if (destKeyPass != null) {
2153             newPass = destKeyPass;
2154             pp = new PasswordProtection(destKeyPass);
2155         } else if (objs.snd != null) {
2156             newPass = objs.snd;
2157             pp = new PasswordProtection(objs.snd);
2158         }
2159 
2160         try {
2161             Certificate c = srckeystore.getCertificate(alias);
2162             if (c != null) {
2163                 checkWeak("<" + newAlias + ">", c);
2164             }
2165             keyStore.setEntry(newAlias, entry, pp);
2166             // Place the check so that only successful imports are blocked.
2167             // For example, we don't block a failed SecretEntry import.
2168             if (P12KEYSTORE.equalsIgnoreCase(storetype)) {
2169                 if (newPass != null && !Arrays.equals(newPass, storePass)) {
2170                     throw new Exception(rb.getString(
2171                             "The.destination.pkcs12.keystore.has.different.storepass.and.keypass.Please.retry.with.destkeypass.specified."));
2172                 }
2173             }
2174             return 1;
2175         } catch (KeyStoreException kse) {
2176             Object[] source2 = {alias, kse.toString()};
2177             MessageFormat form = new MessageFormat(rb.getString(
2178                     "Problem.importing.entry.for.alias.alias.exception.Entry.for.alias.alias.not.imported."));
2179             System.err.println(form.format(source2));
2180             return 2;
2181         }
2182     }
2183 
2184     private void doImportKeyStoreAll(KeyStore srckeystore) throws Exception {


2198                 if (!noprompt) {
2199                     String reply = getYesNoReply("Do you want to quit the import process? [no]:  ");
2200                     if ("YES".equals(reply)) {
2201                         break;
2202                     }
2203                 }
2204             }
2205         }
2206         Object[] source = {ok, count-ok};
2207         MessageFormat form = new MessageFormat(rb.getString(
2208                 "Import.command.completed.ok.entries.successfully.imported.fail.entries.failed.or.cancelled"));
2209         System.err.println(form.format(source));
2210     }
2211 
2212     /**
2213      * Prints all keystore entries.
2214      */
2215     private void doPrintEntries(PrintStream out)
2216         throws Exception
2217     {







2218         out.println(rb.getString("Keystore.type.") + keyStore.getType());
2219         out.println(rb.getString("Keystore.provider.") +
2220                 keyStore.getProvider().getName());
2221         out.println();
2222 
2223         MessageFormat form;
2224         form = (keyStore.size() == 1) ?
2225                 new MessageFormat(rb.getString
2226                         ("Your.keystore.contains.keyStore.size.entry")) :
2227                 new MessageFormat(rb.getString
2228                         ("Your.keystore.contains.keyStore.size.entries"));
2229         Object[] source = {new Integer(keyStore.size())};
2230         out.println(form.format(source));
2231         out.println();
2232 
2233         for (Enumeration<String> e = keyStore.aliases();
2234                                         e.hasMoreElements(); ) {
2235             String alias = e.nextElement();
2236             doPrintEntry("<" + alias + ">", alias, out);
2237             if (verbose || rfc) {
2238                 out.println(rb.getString("NEWLINE"));
2239                 out.println(rb.getString
2240                         ("STAR"));
2241                 out.println(rb.getString
2242                         ("STARNN"));
2243             }
2244         }
2245     }
2246 
2247     private static <T> Iterable<T> e2i(final Enumeration<T> e) {
2248         return new Iterable<T>() {
2249             @Override
2250             public Iterator<T> iterator() {
2251                 return new Iterator<T>() {
2252                     @Override
2253                     public boolean hasNext() {
2254                         return e.hasMoreElements();
2255                     }
2256                     @Override


2366             Certificate cert = ks.getCertificate(s);
2367             if (cert instanceof X509Certificate) {
2368                 X509Certificate xcert = (X509Certificate)cert;
2369                 if (xcert.getSubjectX500Principal().equals(issuer)) {
2370                     try {
2371                         ((X509CRLImpl)crl).verify(cert.getPublicKey());
2372                         return s;
2373                     } catch (Exception e) {
2374                     }
2375                 }
2376             }
2377         }
2378         return null;
2379     }
2380 
2381     private void doPrintCRL(String src, PrintStream out)
2382             throws Exception {
2383         for (CRL crl: loadCRLs(src)) {
2384             printCRL(crl, out);
2385             String issuer = null;
2386             Certificate signer = null;
2387             if (caks != null) {
2388                 issuer = verifyCRL(caks, crl);
2389                 if (issuer != null) {
2390                     signer = caks.getCertificate(issuer);
2391                     out.printf(rb.getString(
2392                             "verified.by.s.in.s.weak"),
2393                             issuer,
2394                             "cacerts",
2395                             withWeak(signer.getPublicKey()));
2396                     out.println();
2397                 }
2398             }
2399             if (issuer == null && keyStore != null) {
2400                 issuer = verifyCRL(keyStore, crl);
2401                 if (issuer != null) {
2402                     signer = keyStore.getCertificate(issuer);
2403                     out.printf(rb.getString(
2404                             "verified.by.s.in.s.weak"),
2405                             issuer,
2406                             "keystore",
2407                             withWeak(signer.getPublicKey()));
2408                     out.println();
2409                 }
2410             }
2411             if (issuer == null) {
2412                 out.println(rb.getString
2413                         ("STAR"));
2414                 out.println(rb.getString
2415                         ("warning.not.verified.make.sure.keystore.is.correct"));
2416                 out.println(rb.getString
2417                         ("STARNN"));
2418             }
2419             checkWeak(rb.getString("the.crl"), crl, signer == null ? null : signer.getPublicKey());
2420         }
2421     }
2422 
2423     private void printCRL(CRL crl, PrintStream out)
2424             throws Exception {

2425         X509CRL xcrl = (X509CRL)crl;
2426         if (rfc) {
2427             out.println("-----BEGIN X509 CRL-----");
2428             out.println(Base64.getMimeEncoder(64, CRLF).encodeToString(xcrl.getEncoded()));
2429             out.println("-----END X509 CRL-----");
2430         } else {
2431             String s;
2432             if (crl instanceof X509CRLImpl) {
2433                 X509CRLImpl x509crl = (X509CRLImpl) crl;
2434                 s = x509crl.toStringWithAlgName(withWeak("" + x509crl.getSigAlgId()));
2435             } else {
2436                 s = crl.toString();
2437             }
2438             out.println(s);
2439         }
2440     }
2441 
2442     private void doPrintCertReq(InputStream in, PrintStream out)
2443             throws Exception {
2444 
2445         BufferedReader reader = new BufferedReader(new InputStreamReader(in));
2446         StringBuffer sb = new StringBuffer();
2447         boolean started = false;
2448         while (true) {
2449             String s = reader.readLine();
2450             if (s == null) break;
2451             if (!started) {
2452                 if (s.startsWith("-----")) {
2453                     started = true;
2454                 }
2455             } else {
2456                 if (s.startsWith("-----")) {
2457                     break;
2458                 }
2459                 sb.append(s);
2460             }
2461         }
2462         PKCS10 req = new PKCS10(Pem.decode(new String(sb)));
2463 
2464         PublicKey pkey = req.getSubjectPublicKeyInfo();
2465         out.printf(rb.getString("PKCS.10.with.weak"),
2466                 req.getSubjectName(),
2467                 pkey.getFormat(),
2468                 withWeak(pkey),
2469                 withWeak(req.getSigAlg()));
2470         for (PKCS10Attribute attr: req.getAttributes().getAttributes()) {
2471             ObjectIdentifier oid = attr.getAttributeId();
2472             if (oid.equals((Object)PKCS9Attribute.EXTENSION_REQUEST_OID)) {
2473                 CertificateExtensions exts = (CertificateExtensions)attr.getAttributeValue();
2474                 if (exts != null) {
2475                     printExtensions(rb.getString("Extension.Request."), exts, out);
2476                 }
2477             } else {
2478                 out.println("Attribute: " + attr.getAttributeId());
2479                 PKCS9Attribute pkcs9Attr =
2480                         new PKCS9Attribute(attr.getAttributeId(),
2481                                            attr.getAttributeValue());
2482                 out.print(pkcs9Attr.getName() + ": ");
2483                 Object attrVal = attr.getAttributeValue();
2484                 out.println(attrVal instanceof String[] ?
2485                             Arrays.toString((String[]) attrVal) :
2486                             attrVal);
2487             }
2488         }
2489         if (debug) {
2490             out.println(req);   // Just to see more, say, public key length...
2491         }
2492         checkWeak(rb.getString("the.certificate.request"), req);
2493     }
2494 
2495     /**
2496      * Reads a certificate (or certificate chain) and prints its contents in
2497      * a human readable format.
2498      */
2499     private void printCertFromStream(InputStream in, PrintStream out)
2500         throws Exception
2501     {
2502         Collection<? extends Certificate> c = null;
2503         try {
2504             c = cf.generateCertificates(in);
2505         } catch (CertificateException ce) {
2506             throw new Exception(rb.getString("Failed.to.parse.input"), ce);
2507         }
2508         if (c.isEmpty()) {
2509             throw new Exception(rb.getString("Empty.input"));
2510         }
2511         Certificate[] certs = c.toArray(new Certificate[c.size()]);
2512         for (int i=0; i<certs.length; i++) {
2513             X509Certificate x509Cert = null;
2514             try {
2515                 x509Cert = (X509Certificate)certs[i];
2516             } catch (ClassCastException cce) {
2517                 throw new Exception(rb.getString("Not.X.509.certificate"));
2518             }
2519             if (certs.length > 1) {
2520                 MessageFormat form = new MessageFormat
2521                         (rb.getString("Certificate.i.1."));
2522                 Object[] source = {new Integer(i + 1)};
2523                 out.println(form.format(source));
2524             }
2525             if (rfc)
2526                 dumpCert(x509Cert, out);
2527             else
2528                 printX509Cert(x509Cert, out);
2529             if (i < (certs.length-1)) {
2530                 out.println();
2531             }
2532             checkWeak(oneInMany(rb.getString("the.certificate"), i, certs.length), x509Cert);
2533         }
2534     }
2535 
2536     private static String oneInMany(String label, int i, int num) {
2537         if (num == 1) {
2538             return label;
2539         } else {
2540             return String.format(rb.getString("one.in.many"), label, i+1, num);
2541         }
2542     }
2543 
2544     private void doPrintCert(final PrintStream out) throws Exception {
2545         if (jarfile != null) {
2546             JarFile jf = new JarFile(jarfile, true);
2547             Enumeration<JarEntry> entries = jf.entries();
2548             Set<CodeSigner> ss = new HashSet<>();
2549             byte[] buffer = new byte[8192];
2550             int pos = 0;
2551             while (entries.hasMoreElements()) {
2552                 JarEntry je = entries.nextElement();
2553                 try (InputStream is = jf.getInputStream(je)) {
2554                     while (is.read(buffer) != -1) {
2555                         // we just read. this will throw a SecurityException
2556                         // if a signature/digest check fails. This also
2557                         // populate the signers
2558                     }
2559                 }
2560                 CodeSigner[] signers = je.getCodeSigners();
2561                 if (signers != null) {
2562                     for (CodeSigner signer: signers) {
2563                         if (!ss.contains(signer)) {
2564                             ss.add(signer);
2565                             out.printf(rb.getString("Signer.d."), ++pos);
2566                             out.println();
2567                             out.println();
2568                             out.println(rb.getString("Signature."));
2569                             out.println();
2570 
2571                             List<? extends Certificate> certs
2572                                     = signer.getSignerCertPath().getCertificates();
2573                             int cc = 0;
2574                             for (Certificate cert: certs) {
2575                                 X509Certificate x = (X509Certificate)cert;
2576                                 if (rfc) {
2577                                     out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n");
2578                                     dumpCert(x, out);
2579                                 } else {
2580                                     printX509Cert(x, out);
2581                                 }
2582                                 out.println();
2583                                 checkWeak(oneInMany(rb.getString("the.certificate"), cc++, certs.size()), x);
2584                             }
2585                             Timestamp ts = signer.getTimestamp();
2586                             if (ts != null) {
2587                                 out.println(rb.getString("Timestamp."));
2588                                 out.println();
2589                                 certs = ts.getSignerCertPath().getCertificates();
2590                                 cc = 0;
2591                                 for (Certificate cert: certs) {
2592                                     X509Certificate x = (X509Certificate)cert;
2593                                     if (rfc) {
2594                                         out.println(rb.getString("Certificate.owner.") + x.getSubjectDN() + "\n");
2595                                         dumpCert(x, out);
2596                                     } else {
2597                                         printX509Cert(x, out);
2598                                     }
2599                                     out.println();
2600                                     checkWeak(oneInMany(rb.getString("the.tsa.certificate"), cc++, certs.size()), x);
2601                                 }
2602                             }
2603                         }
2604                     }
2605                 }
2606             }
2607             jf.close();
2608             if (ss.isEmpty()) {
2609                 out.println(rb.getString("Not.a.signed.jar.file"));
2610             }
2611         } else if (sslserver != null) {
2612             // Lazily load SSLCertStoreHelper if present
2613             CertStoreHelper helper = CertStoreHelper.getInstance("SSLServer");
2614             CertStore cs = helper.getCertStore(new URI("https://" + sslserver));
2615             Collection<? extends Certificate> chain;
2616             try {
2617                 chain = cs.getCertificates(null);
2618                 if (chain.isEmpty()) {
2619                     // If the certs are not retrieved, we consider it an error
2620                     // even if the URL connection is successful.


2625                 if (cse.getCause() instanceof IOException) {
2626                     throw new Exception(rb.getString(
2627                                         "No.certificate.from.the.SSL.server"),
2628                                         cse.getCause());
2629                 } else {
2630                     throw cse;
2631                 }
2632             }
2633 
2634             int i = 0;
2635             for (Certificate cert : chain) {
2636                 try {
2637                     if (rfc) {
2638                         dumpCert(cert, out);
2639                     } else {
2640                         out.println("Certificate #" + i++);
2641                         out.println("====================================");
2642                         printX509Cert((X509Certificate)cert, out);
2643                         out.println();
2644                     }
2645                     checkWeak(oneInMany(rb.getString("the.certificate"), i, chain.size()), cert);
2646                 } catch (Exception e) {
2647                     if (debug) {
2648                         e.printStackTrace();
2649                     }
2650                 }
2651             }
2652         } else {
2653             if (filename != null) {
2654                 try (FileInputStream inStream = new FileInputStream(filename)) {
2655                     printCertFromStream(inStream, out);
2656                 }
2657             } else {
2658                 printCertFromStream(System.in, out);
2659             }
2660         }
2661     }
2662     /**
2663      * Creates a self-signed certificate, and stores it as a single-element
2664      * certificate chain.
2665      */


2801             Object[] source = {alias};
2802             throw new Exception(form.format(source));
2803         }
2804 
2805         // Read the certificates in the reply
2806         Collection<? extends Certificate> c = cf.generateCertificates(in);
2807         if (c.isEmpty()) {
2808             throw new Exception(rb.getString("Reply.has.no.certificates"));
2809         }
2810         Certificate[] replyCerts = c.toArray(new Certificate[c.size()]);
2811         Certificate[] newChain;
2812         if (replyCerts.length == 1) {
2813             // single-cert reply
2814             newChain = establishCertChain(userCert, replyCerts[0]);
2815         } else {
2816             // cert-chain reply (e.g., PKCS#7)
2817             newChain = validateReply(alias, userCert, replyCerts);
2818         }
2819 
2820         // Now store the newly established chain in the keystore. The new
2821         // chain replaces the old one. The chain can be null if user chooses no.
2822         if (newChain != null) {
2823             keyStore.setKeyEntry(alias, privKey,
2824                                  (keyPass != null) ? keyPass : storePass,
2825                                  newChain);
2826             return true;
2827         } else {
2828             return false;
2829         }
2830     }
2831 
2832     /**
2833      * Imports a certificate and adds it to the list of trusted certificates.
2834      *
2835      * @return true if the certificate was added, otherwise false.
2836      */
2837     private boolean addTrustedCert(String alias, InputStream in)
2838         throws Exception
2839     {
2840         if (alias == null) {
2841             throw new Exception(rb.getString("Must.specify.alias"));
2842         }
2843         if (keyStore.containsAlias(alias)) {
2844             MessageFormat form = new MessageFormat(rb.getString
2845                 ("Certificate.not.imported.alias.alias.already.exists"));
2846             Object[] source = {alias};
2847             throw new Exception(form.format(source));
2848         }
2849 
2850         // Read the certificate
2851         X509Certificate cert = null;
2852         try {
2853             cert = (X509Certificate)cf.generateCertificate(in);
2854         } catch (ClassCastException | CertificateException ce) {
2855             throw new Exception(rb.getString("Input.not.an.X.509.certificate"));
2856         }
2857 
2858         if (noprompt) {
2859             checkWeak(rb.getString("the.input"), cert);
2860             keyStore.setCertificateEntry(alias, cert);
2861             return true;
2862         }
2863 
2864         // if certificate is self-signed, make sure it verifies
2865         boolean selfSigned = false;
2866         if (isSelfSigned(cert)) {
2867             cert.verify(cert.getPublicKey());
2868             selfSigned = true;
2869         }
2870 





2871         // check if cert already exists in keystore
2872         String reply = null;
2873         String trustalias = keyStore.getCertificateAlias(cert);
2874         if (trustalias != null) {
2875             MessageFormat form = new MessageFormat(rb.getString
2876                 ("Certificate.already.exists.in.keystore.under.alias.trustalias."));
2877             Object[] source = {trustalias};
2878             System.err.println(form.format(source));
2879             checkWeak(rb.getString("the.input"), cert);
2880             printWeakWarnings(true);
2881             reply = getYesNoReply
2882                 (rb.getString("Do.you.still.want.to.add.it.no."));
2883         } else if (selfSigned) {
2884             if (trustcacerts && (caks != null) &&
2885                     ((trustalias=caks.getCertificateAlias(cert)) != null)) {
2886                 MessageFormat form = new MessageFormat(rb.getString
2887                         ("Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias."));
2888                 Object[] source = {trustalias};
2889                 System.err.println(form.format(source));
2890                 checkWeak(rb.getString("the.input"), cert);
2891                 printWeakWarnings(true);
2892                 reply = getYesNoReply
2893                         (rb.getString("Do.you.still.want.to.add.it.to.your.own.keystore.no."));
2894             }
2895             if (trustalias == null) {
2896                 // Print the cert and ask user if they really want to add
2897                 // it to their keystore
2898                 printX509Cert(cert, System.out);
2899                 checkWeak(rb.getString("the.input"), cert);
2900                 printWeakWarnings(true);
2901                 reply = getYesNoReply
2902                         (rb.getString("Trust.this.certificate.no."));
2903             }
2904         }
2905         if (reply != null) {
2906             if ("YES".equals(reply)) {
2907                 keyStore.setCertificateEntry(alias, cert);
2908                 return true;
2909             } else {
2910                 return false;
2911             }
2912         }
2913 
2914         // Not found in this keystore and not self-signed
2915         // Try to establish trust chain
2916         try {
2917             Certificate[] chain = establishCertChain(null, cert);
2918             if (chain != null) {
2919                 keyStore.setCertificateEntry(alias, cert);
2920                 return true;
2921             }
2922         } catch (Exception e) {
2923             // Print the cert and ask user if they really want to add it to
2924             // their keystore
2925             printX509Cert(cert, System.out);
2926             checkWeak(rb.getString("the.input"), cert);
2927             printWeakWarnings(true);
2928             reply = getYesNoReply
2929                 (rb.getString("Trust.this.certificate.no."));
2930             if ("YES".equals(reply)) {
2931                 keyStore.setCertificateEntry(alias, cert);
2932                 return true;
2933             } else {
2934                 return false;
2935             }
2936         }
2937 
2938         return false;
2939     }
2940 
2941     /**
2942      * Prompts user for new password. New password must be different from
2943      * old one.
2944      *
2945      * @param prompt the message that gets prompted on the screen
2946      * @param oldPasswd the current (i.e., old) password
2947      */


3046                         ("Enter.key.password.for.alias."));
3047                 Object[] source = {alias};
3048                 System.err.print(form.format(source));
3049             }
3050             System.err.flush();
3051             keyPass = Password.readPassword(System.in);
3052             passwords.add(keyPass);
3053             if (keyPass == null) {
3054                 keyPass = otherKeyPass;
3055             }
3056             count++;
3057         } while ((keyPass == null) && count < 3);
3058 
3059         if (keyPass == null) {
3060             throw new Exception(rb.getString("Too.many.failures.try.later"));
3061         }
3062 
3063         return keyPass;
3064     }
3065 
3066     private String withWeak(String alg) {
3067         if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, alg, null)) {
3068             return alg;
3069         } else {
3070             return String.format(rb.getString("with.weak"), alg);
3071         }
3072     }
3073 
3074     private String withWeak(PublicKey key) {
3075         if (DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
3076             return String.format(rb.getString("key.bit"),
3077                     KeyUtil.getKeySize(key), key.getAlgorithm());
3078         } else {
3079             return String.format(rb.getString("key.bit.weak"),
3080                     KeyUtil.getKeySize(key), key.getAlgorithm());
3081         }
3082     }
3083 
3084     /**
3085      * Prints a certificate in a human readable format.
3086      */
3087     private void printX509Cert(X509Certificate cert, PrintStream out)
3088         throws Exception
3089     {
3090         /*
3091         out.println("Owner: "
3092                     + cert.getSubjectDN().toString()
3093                     + "\n"
3094                     + "Issuer: "
3095                     + cert.getIssuerDN().toString()
3096                     + "\n"
3097                     + "Serial number: " + cert.getSerialNumber().toString(16)
3098                     + "\n"
3099                     + "Valid from: " + cert.getNotBefore().toString()
3100                     + " until: " + cert.getNotAfter().toString()
3101                     + "\n"
3102                     + "Certificate fingerprints:\n"
3103                     + "\t MD5:  " + getCertFingerPrint("MD5", cert)
3104                     + "\n"
3105                     + "\t SHA1: " + getCertFingerPrint("SHA1", cert));
3106         */
3107 
3108         MessageFormat form = new MessageFormat
3109                 (rb.getString(".PATTERN.printX509Cert.with.weak"));
3110         PublicKey pkey = cert.getPublicKey();
3111         String sigName = cert.getSigAlgName();
3112         // No need to warn about sigalg of a trust anchor
3113         if (!isTrustedCert(cert)) {
3114             sigName = withWeak(sigName);
3115         }
3116         Object[] source = {cert.getSubjectDN().toString(),
3117                         cert.getIssuerDN().toString(),
3118                         cert.getSerialNumber().toString(16),
3119                         cert.getNotBefore().toString(),
3120                         cert.getNotAfter().toString(),
3121                         getCertFingerPrint("MD5", cert),
3122                         getCertFingerPrint("SHA1", cert),
3123                         getCertFingerPrint("SHA-256", cert),
3124                         sigName,
3125                         withWeak(pkey),
3126                         cert.getVersion()
3127                         };
3128         out.println(form.format(source));
3129 
3130         if (cert instanceof X509CertImpl) {
3131             X509CertImpl impl = (X509CertImpl)cert;
3132             X509CertInfo certInfo = (X509CertInfo)impl.get(X509CertImpl.NAME
3133                                                            + "." +
3134                                                            X509CertImpl.INFO);
3135             CertificateExtensions exts = (CertificateExtensions)
3136                     certInfo.get(X509CertInfo.EXTENSIONS);
3137             if (exts != null) {
3138                 printExtensions(rb.getString("Extensions."), exts, out);
3139             }
3140         }
3141     }
3142 
3143     private static void printExtensions(String title, CertificateExtensions exts, PrintStream out)
3144             throws Exception {
3145         int extnum = 0;


3175 
3176     private boolean signedBy(X509Certificate end, X509Certificate ca) {
3177         if (!ca.getSubjectDN().equals(end.getIssuerDN())) {
3178             return false;
3179         }
3180         try {
3181             end.verify(ca.getPublicKey());
3182             return true;
3183         } catch (Exception e) {
3184             return false;
3185         }
3186     }
3187 
3188     /**
3189      * Locates a signer for a given certificate from a given keystore and
3190      * returns the signer's certificate.
3191      * @param cert the certificate whose signer is searched, not null
3192      * @param ks the keystore to search with, not null
3193      * @return <code>cert</code> itself if it's already inside <code>ks</code>,
3194      * or a certificate inside <code>ks</code> who signs <code>cert</code>,
3195      * or null otherwise. A label is added.
3196      */
3197     private static Pair<String,Certificate>
3198             getSigner(Certificate cert, KeyStore ks) throws Exception {
3199         if (ks.getCertificateAlias(cert) != null) {
3200             return new Pair<>("", cert);
3201         }
3202         for (Enumeration<String> aliases = ks.aliases();
3203                 aliases.hasMoreElements(); ) {
3204             String name = aliases.nextElement();
3205             Certificate trustedCert = ks.getCertificate(name);
3206             if (trustedCert != null) {
3207                 try {
3208                     cert.verify(trustedCert.getPublicKey());
3209                     return new Pair<>(name, trustedCert);
3210                 } catch (Exception e) {
3211                     // Not verified, skip to the next one
3212                 }
3213             }
3214         }
3215         return null;
3216     }
3217 
3218     /**
3219      * Gets an X.500 name suitable for inclusion in a certification request.
3220      */
3221     private X500Name getX500Name() throws IOException {
3222         BufferedReader in;
3223         in = new BufferedReader(new InputStreamReader(System.in));
3224         String commonName = "Unknown";
3225         String organizationalUnit = "Unknown";
3226         String organization = "Unknown";
3227         String city = "Unknown";
3228         String state = "Unknown";
3229         String country = "Unknown";


3453             }
3454         }
3455 
3456         return Pair.of(entry, pkey);
3457     }
3458     /**
3459      * Gets the requested finger print of the certificate.
3460      */
3461     private String getCertFingerPrint(String mdAlg, Certificate cert)
3462         throws Exception
3463     {
3464         byte[] encCertInfo = cert.getEncoded();
3465         MessageDigest md = MessageDigest.getInstance(mdAlg);
3466         byte[] digest = md.digest(encCertInfo);
3467         return toHexString(digest);
3468     }
3469 
3470     /**
3471      * Prints warning about missing integrity check.
3472      */
3473     private void printNoIntegrityWarning() {
3474         System.err.println();
3475         System.err.println(rb.getString
3476             (".WARNING.WARNING.WARNING."));
3477         System.err.println(rb.getString
3478             (".The.integrity.of.the.information.stored.in.your.keystore."));
3479         System.err.println(rb.getString
3480             (".WARNING.WARNING.WARNING."));
3481         System.err.println();
3482     }
3483 
3484     /**
3485      * Validates chain in certification reply, and returns the ordered
3486      * elements of the chain (with user certificate first, and root
3487      * certificate last in the array).
3488      *
3489      * @param alias the alias name
3490      * @param userCert the user certificate of the alias
3491      * @param replyCerts the chain provided in the reply
3492      */
3493     private Certificate[] validateReply(String alias,
3494                                         Certificate userCert,
3495                                         Certificate[] replyCerts)
3496         throws Exception
3497     {
3498 
3499         checkWeak(rb.getString("reply"), replyCerts);
3500 
3501         // order the certs in the reply (bottom-up).
3502         // we know that all certs in the reply are of type X.509, because
3503         // we parsed them using an X.509 certificate factory
3504         int i;
3505         PublicKey userPubKey = userCert.getPublicKey();
3506         for (i=0; i<replyCerts.length; i++) {
3507             if (userPubKey.equals(replyCerts[i].getPublicKey())) {
3508                 break;
3509             }
3510         }
3511         if (i == replyCerts.length) {
3512             MessageFormat form = new MessageFormat(rb.getString
3513                 ("Certificate.reply.does.not.contain.public.key.for.alias."));
3514             Object[] source = {alias};
3515             throw new Exception(form.format(source));
3516         }
3517 
3518         Certificate tmpCert = replyCerts[0];
3519         replyCerts[0] = replyCerts[i];
3520         replyCerts[i] = tmpCert;


3528                 if (signedBy(thisCert, (X509Certificate)replyCerts[j])) {
3529                     tmpCert = replyCerts[i];
3530                     replyCerts[i] = replyCerts[j];
3531                     replyCerts[j] = tmpCert;
3532                     thisCert = (X509Certificate)replyCerts[i];
3533                     break;
3534                 }
3535             }
3536             if (j == replyCerts.length) {
3537                 throw new Exception
3538                     (rb.getString("Incomplete.certificate.chain.in.reply"));
3539             }
3540         }
3541 
3542         if (noprompt) {
3543             return replyCerts;
3544         }
3545 
3546         // do we trust the cert at the top?
3547         Certificate topCert = replyCerts[replyCerts.length-1];
3548         boolean fromKeyStore = true;
3549         Pair<String,Certificate> root = getSigner(topCert, keyStore);
3550         if (root == null && trustcacerts && caks != null) {
3551             root = getSigner(topCert, caks);
3552             fromKeyStore = false;
3553         }
3554         if (root == null) {
3555             System.err.println();
3556             System.err.println
3557                     (rb.getString("Top.level.certificate.in.reply."));
3558             printX509Cert((X509Certificate)topCert, System.out);
3559             System.err.println();
3560             System.err.print(rb.getString(".is.not.trusted."));
3561             printWeakWarnings(true);
3562             String reply = getYesNoReply
3563                     (rb.getString("Install.reply.anyway.no."));
3564             if ("NO".equals(reply)) {
3565                 return null;
3566             }
3567         } else {
3568             if (root.snd != topCert) {
3569                 // append the root CA cert to the chain
3570                 Certificate[] tmpCerts =
3571                     new Certificate[replyCerts.length+1];
3572                 System.arraycopy(replyCerts, 0, tmpCerts, 0,
3573                                  replyCerts.length);
3574                 tmpCerts[tmpCerts.length-1] = root.snd;
3575                 replyCerts = tmpCerts;
3576                 checkWeak(String.format(rb.getString(fromKeyStore ?
3577                                             "alias.in.keystore" :
3578                                             "alias.in.cacerts"),
3579                                         root.fst),
3580                           root.snd);
3581             }
3582         }

3583         return replyCerts;
3584     }
3585 
3586     /**
3587      * Establishes a certificate chain (using trusted certificates in the
3588      * keystore and cacerts), starting with the reply (certToVerify)
3589      * and ending at a self-signed certificate found in the keystore.
3590      *
3591      * @param userCert optional existing certificate, mostly likely be the
3592      *                 original self-signed cert created by -genkeypair.
3593      *                 It must have the same public key as certToVerify
3594      *                 but cannot be the same cert.
3595      * @param certToVerify the starting certificate to build the chain
3596      * @returns the established chain, might be null if user decides not
3597      */
3598     private Certificate[] establishCertChain(Certificate userCert,
3599                                              Certificate certToVerify)
3600         throws Exception
3601     {
3602         if (userCert != null) {
3603             // Make sure that the public key of the certificate reply matches
3604             // the original public key in the keystore
3605             PublicKey origPubKey = userCert.getPublicKey();
3606             PublicKey replyPubKey = certToVerify.getPublicKey();
3607             if (!origPubKey.equals(replyPubKey)) {
3608                 throw new Exception(rb.getString
3609                         ("Public.keys.in.reply.and.keystore.don.t.match"));
3610             }
3611 
3612             // If the two certs are identical, we're done: no need to import
3613             // anything
3614             if (certToVerify.equals(userCert)) {
3615                 throw new Exception(rb.getString
3616                         ("Certificate.reply.and.certificate.in.keystore.are.identical"));
3617             }
3618         }
3619 
3620         // Build a hash table of all certificates in the keystore.
3621         // Use the subject distinguished name as the key into the hash table.
3622         // All certificates associated with the same subject distinguished
3623         // name are stored in the same hash table entry as a vector.
3624         Hashtable<Principal, Vector<Pair<String,X509Certificate>>> certs = null;
3625         if (keyStore.size() > 0) {
3626             certs = new Hashtable<>(11);
3627             keystorecerts2Hashtable(keyStore, certs);
3628         }
3629         if (trustcacerts) {
3630             if (caks!=null && caks.size()>0) {
3631                 if (certs == null) {
3632                     certs = new Hashtable<>(11);
3633                 }
3634                 keystorecerts2Hashtable(caks, certs);
3635             }
3636         }
3637 
3638         // start building chain
3639         Vector<Pair<String,X509Certificate>> chain = new Vector<>(2);
3640         if (buildChain(
3641                 new Pair<>(rb.getString("the.input"),
3642                            (X509Certificate) certToVerify),
3643                 chain, certs)) {
3644             for (Pair<String,X509Certificate> p : chain) {
3645                 checkWeak(p.fst, p.snd);
3646             }
3647             Certificate[] newChain =
3648                     new Certificate[chain.size()];
3649             // buildChain() returns chain with self-signed root-cert first and
3650             // user-cert last, so we need to invert the chain before we store
3651             // it
3652             int j=0;
3653             for (int i=chain.size()-1; i>=0; i--) {
3654                 newChain[j] = chain.elementAt(i).snd;
3655                 j++;
3656             }
3657             return newChain;
3658         } else {
3659             throw new Exception
3660                 (rb.getString("Failed.to.establish.chain.from.reply"));
3661         }
3662     }
3663 
3664     /**
3665      * Recursively tries to establish chain from pool of certs starting from
3666      * certToVerify until a self-signed cert is found, and fill the certs found
3667      * into chain. Each cert in the chain signs the next one.
3668      *
3669      * This method is able to recover from an error, say, if certToVerify
3670      * is signed by certA but certA has no issuer in certs and itself is not
3671      * self-signed, the method can try another certB that also signs
3672      * certToVerify and look for signer of certB, etc, etc.
3673      *
3674      * Each cert in chain comes with a label showing its origin. The label is
3675      * used in the warning message when the cert is considered a risk.
3676      *
3677      * @param certToVerify the cert that needs to be verified.
3678      * @param chain the chain that's being built.
3679      * @param certs the pool of trusted certs
3680      *
3681      * @return true if successful, false otherwise.
3682      */
3683     private boolean buildChain(Pair<String,X509Certificate> certToVerify,
3684             Vector<Pair<String,X509Certificate>> chain,
3685             Hashtable<Principal, Vector<Pair<String,X509Certificate>>> certs) {
3686         if (isSelfSigned(certToVerify.snd)) {

3687             // reached self-signed root cert;
3688             // no verification needed because it's trusted.
3689             chain.addElement(certToVerify);
3690             return true;
3691         }
3692 
3693         Principal issuer = certToVerify.snd.getIssuerDN();
3694 
3695         // Get the issuer's certificate(s)
3696         Vector<Pair<String,X509Certificate>> vec = certs.get(issuer);
3697         if (vec == null) {
3698             return false;
3699         }
3700 
3701         // Try out each certificate in the vector, until we find one
3702         // whose public key verifies the signature of the certificate
3703         // in question.
3704         for (Enumeration<Pair<String,X509Certificate>> issuerCerts = vec.elements();
3705              issuerCerts.hasMoreElements(); ) {
3706             Pair<String,X509Certificate> issuerCert = issuerCerts.nextElement();
3707             PublicKey issuerPubKey = issuerCert.snd.getPublicKey();

3708             try {
3709                 certToVerify.snd.verify(issuerPubKey);
3710             } catch (Exception e) {
3711                 continue;
3712             }
3713             if (buildChain(issuerCert, chain, certs)) {
3714                 chain.addElement(certToVerify);
3715                 return true;
3716             }
3717         }
3718         return false;
3719     }
3720 
3721     /**
3722      * Prompts user for yes/no decision.
3723      *
3724      * @return the user's decision, can only be "YES" or "NO"
3725      */
3726     private String getYesNoReply(String prompt)
3727         throws IOException
3728     {
3729         String reply = null;


3738             reply = (new BufferedReader(new InputStreamReader
3739                                         (System.in))).readLine();
3740             if (collator.compare(reply, "") == 0 ||
3741                 collator.compare(reply, rb.getString("n")) == 0 ||
3742                 collator.compare(reply, rb.getString("no")) == 0) {
3743                 reply = "NO";
3744             } else if (collator.compare(reply, rb.getString("y")) == 0 ||
3745                        collator.compare(reply, rb.getString("yes")) == 0) {
3746                 reply = "YES";
3747             } else {
3748                 System.err.println(rb.getString("Wrong.answer.try.again"));
3749                 reply = null;
3750             }
3751         } while (reply == null);
3752         return reply;
3753     }
3754 
3755     /**
3756      * Stores the (leaf) certificates of a keystore in a hashtable.
3757      * All certs belonging to the same CA are stored in a vector that
3758      * in turn is stored in the hashtable, keyed by the CA's subject DN.
3759      * Each cert comes with a string label that shows its origin and alias.
3760      */
3761     private void keystorecerts2Hashtable(KeyStore ks,
3762                 Hashtable<Principal, Vector<Pair<String,X509Certificate>>> hash)
3763         throws Exception {
3764 
3765         for (Enumeration<String> aliases = ks.aliases();
3766                                         aliases.hasMoreElements(); ) {
3767             String alias = aliases.nextElement();
3768             Certificate cert = ks.getCertificate(alias);
3769             if (cert != null) {
3770                 Principal subjectDN = ((X509Certificate)cert).getSubjectDN();
3771                 Pair<String,X509Certificate> pair = new Pair<>(
3772                         String.format(
3773                                 rb.getString(ks == caks ?
3774                                         "alias.in.cacerts" :
3775                                         "alias.in.keystore"),
3776                                 alias),
3777                         (X509Certificate)cert);
3778                 Vector<Pair<String,X509Certificate>> vec = hash.get(subjectDN);
3779                 if (vec == null) {
3780                     vec = new Vector<>();
3781                     vec.addElement(pair);
3782                 } else {
3783                     if (!vec.contains(pair)) {
3784                         vec.addElement(pair);
3785                     }
3786                 }
3787                 hash.put(subjectDN, vec);
3788             }
3789         }
3790     }
3791 
3792     /**
3793      * Returns the issue time that's specified the -startdate option
3794      * @param s the value of -startdate option
3795      */
3796     private static Date getStartDate(String s) throws IOException {
3797         Calendar c = new GregorianCalendar();
3798         if (s != null) {
3799             IOException ioe = new IOException(
3800                     rb.getString("Illegal.startdate.value"));
3801             int len = s.length();
3802             if (len == 0) {
3803                 throw ioe;
3804             }


4335                                         .toByteArray()));
4336                         break;
4337                     default:
4338                         throw new Exception(rb.getString(
4339                                 "Unknown.extension.type.") + extstr);
4340                 }
4341             }
4342             // always non-critical
4343             ext.set(SubjectKeyIdentifierExtension.NAME,
4344                     new SubjectKeyIdentifierExtension(
4345                         new KeyIdentifier(pkey).getIdentifier()));
4346             if (akey != null && !pkey.equals(akey)) {
4347                 ext.set(AuthorityKeyIdentifierExtension.NAME,
4348                         new AuthorityKeyIdentifierExtension(
4349                         new KeyIdentifier(akey), null, null));
4350             }
4351         } catch(IOException e) {
4352             throw new RuntimeException(e);
4353         }
4354         return ext;
4355     }
4356 
4357     private boolean isTrustedCert(Certificate cert) throws KeyStoreException {
4358         if (caks != null && caks.getCertificateAlias(cert) != null) {
4359             return true;
4360         } else {
4361             String inKS = keyStore.getCertificateAlias(cert);
4362             return inKS != null && keyStore.isCertificateEntry(inKS);
4363         }
4364     }
4365 
4366     private void checkWeak(String label, String sigAlg, Key key) {
4367 
4368         if (sigAlg != null && !DISABLED_CHECK.permits(
4369                 SIG_PRIMITIVE_SET, sigAlg, null)) {
4370             weakWarnings.add(String.format(
4371                     rb.getString("whose.sigalg.risk"), label, sigAlg));
4372         }
4373         if (key != null && !DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
4374             weakWarnings.add(String.format(
4375                     rb.getString("whose.key.risk"),
4376                     label,
4377                     String.format(rb.getString("key.bit"),
4378                             KeyUtil.getKeySize(key), key.getAlgorithm())));
4379         }
4380     }
4381 
4382     private void checkWeak(String label, Certificate[] certs)
4383             throws KeyStoreException {
4384         for (int i = 0; i < certs.length; i++) {
4385             Certificate cert = certs[i];
4386             if (cert instanceof X509Certificate) {
4387                 X509Certificate xc = (X509Certificate)cert;
4388                 String fullLabel = label;
4389                 if (certs.length > 1) {
4390                     fullLabel = oneInMany(label, i, certs.length);
4391                 }
4392                 checkWeak(fullLabel, xc);
4393             }
4394         }
4395     }
4396 
4397     private void checkWeak(String label, Certificate cert)
4398             throws KeyStoreException {
4399         if (cert instanceof X509Certificate) {
4400             X509Certificate xc = (X509Certificate)cert;
4401             // No need to check the sigalg of a trust anchor
4402             String sigAlg = isTrustedCert(cert) ? null : xc.getSigAlgName();
4403             checkWeak(label, sigAlg, xc.getPublicKey());
4404         }
4405     }
4406 
4407     private void checkWeak(String label, PKCS10 p10) {
4408         checkWeak(label, p10.getSigAlg(), p10.getSubjectPublicKeyInfo());
4409     }
4410 
4411     private void checkWeak(String label, CRL crl, Key key) {
4412         if (crl instanceof X509CRLImpl) {
4413             X509CRLImpl impl = (X509CRLImpl)crl;
4414             checkWeak(label, impl.getSigAlgName(), key);
4415         }
4416     }
4417 
4418     private void printWeakWarnings(boolean newLine) {
4419         if (!weakWarnings.isEmpty() && !nowarn) {
4420             System.err.println("\nWarning:");
4421             for (String warning : weakWarnings) {
4422                 System.err.println(warning);
4423             }
4424             if (newLine) {
4425                 // When calling before a yes/no prompt, add a new line
4426                 System.err.println();
4427             }
4428         }
4429         weakWarnings.clear();
4430     }
4431 
4432     /**
4433      * Prints the usage of this tool.
4434      */
4435     private void usage() {
4436         if (command != null) {
4437             System.err.println("keytool " + command +
4438                     rb.getString(".OPTION."));
4439             System.err.println();
4440             System.err.println(rb.getString(command.description));
4441             System.err.println();
4442             System.err.println(rb.getString("Options."));
4443             System.err.println();
4444 
4445             // Left and right sides of the options list
4446             String[] left = new String[command.options.length];
4447             String[] right = new String[command.options.length];
4448 
4449             // Check if there's an unknown option


< prev index next >