/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* This tool manages keystores.
*
* @author Jan Luehe
*
*
* @see java.security.KeyStore
* @see sun.security.provider.KeyProtector
* @see sun.security.provider.JavaKeyStore
*
* @since 1.2
*/
public final class KeyTool {
private boolean debug = false;
private boolean verbose = false;
private boolean rfc = false;
// User-specified providers are added before any command is called.
// However, they are not removed before the end of the main() method.
// If you're calling KeyTool.main() directly in your own Java program,
// please programtically add any providers you need and do not specify
// them through the command line.
private boolean token = false;
private boolean nullStream = false;
private boolean kssave = false;
private boolean noprompt = false;
private boolean trustcacerts = false;
private boolean protectedPath = false;
private boolean srcprotectedPath = false;
enum Command {
PROVIDERPATH, V, PROTECTED),
PROVIDERPATH, V, PROTECTED),
PROVIDERPATH, V, PROTECTED),
PROVIDERPATH, V),
V),
PROVIDERPATH, V),
PROVIDERPATH, V, PROTECTED),
FILEIN, V),
FILEIN, V),
// Undocumented start here, KEYCLONE is used a marker in -help;
PROVIDERARG, PROVIDERPATH, V),
description = d;
options = o;
}
}
};
enum Option {
this.description = description;
}
return "-" + name;
}
};
// for i18n
static {
// this is for case insensitive string comparisons
};
private KeyTool() { }
}
try {
}
} catch (Exception e) {
if (verbose) {
}
if (!debug) {
} else {
throw e;
}
} finally {
}
}
}
}
}
/**
* Parse command line arguments.
*/
int i=0;
// Check if the last option needs an arg
// Only options with an arg need to be checked
break;
}
}
}
/*
* Check modifiers
*/
if (pos > 0) {
}
/*
* command modes
*/
boolean isCommand = false;
command = c;
isCommand = true;
break;
}
}
if (isCommand) {
// already recognized as a command
}
/*
* Help
*/
help = true;
}
/*
* specifiers
*/
srcstoretype = args[++i];
srcProviderName = args[++i];
providerName = args[++i];
keyAlgName = args[++i];
sigAlgName = args[++i];
infilename = args[++i];
outfilename = args[++i];
srcksfname = args[++i];
}
i += 2;
}
}
}
/*
* options
*/
verbose = true;
debug = true;
rfc = true;
noprompt = true;
trustcacerts = true;
protectedPath = true;
srcprotectedPath = true;
} else {
tinyHelp();
}
}
tinyHelp();
}
if (help) {
usage();
} else {
tinyHelp();
}
} else if (help) {
usage();
}
}
}
/**
* Execute the commands.
*/
}
if (srcstoretype == null) {
}
token = true;
}
}
nullStream = true;
}
if (token && !nullStream) {
(".keystore.must.be.NONE.if.storetype.is.{0}"), storetype));
tinyHelp();
}
if (token &&
(".storepasswd.and.keypasswd.commands.not.supported.if.storetype.is.{0}"), storetype));
}
(".keypasswd.commands.not.supported.if.storetype.is.PKCS12"));
}
(".keypass.and.new.can.not.be.specified.if.storetype.is.{0}"), storetype));
}
if (protectedPath) {
("if.protected.is.specified.then.storepass.keypass.and.new.must.not.be.specified"));
}
}
if (srcprotectedPath) {
("if.srcprotected.is.specified.then.srcstorepass.and.srckeypass.must.not.be.specified"));
}
}
("if.keystore.is.not.password.protected.then.storepass.keypass.and.new.must.not.be.specified"));
}
}
("if.source.keystore.is.not.password.protected.then.srcstorepass.and.srckeypass.must.not.be.specified"));
}
}
if (validity <= (long)0) {
throw new Exception
}
// Try to load and install specified provider
} else {
}
} else {
}
} else {
}
}
}
}
("Must.not.specify.both.v.and.rfc.with.list.command"));
tinyHelp();
}
// Make sure provided passwords are at least 6 characters long
("Key.password.must.be.at.least.6.characters"));
}
("New.password.must.be.at.least.6.characters"));
}
("New.password.must.be.at.least.6.characters"));
}
// Check if keystore exists.
// If no keystore has been specified at the command line, try to use
// the default, which is located in $HOME/.keystore.
// If the command is "genkey", "identitydb", "import", or "printcert",
// it is OK not to have a keystore.
if (isKeyStoreRelated(command)) {
+ ".keystore";
}
if (!nullStream) {
try {
// Check if keystore file is empty
("Keystore.file.exists.but.is.empty.") + ksfname);
}
} catch (FileNotFoundException e) {
if (command != GENKEYPAIR &&
command != IDENTITYDB &&
command != IMPORTCERT &&
command != IMPORTKEYSTORE &&
("Keystore.file.does.not.exist.") + ksfname);
}
}
}
}
("Must.specify.destination.alias"));
}
}
}
}
// Create new keystore
if (providerName == null) {
} else {
}
/*
* Load the keystore data.
*
* At this point, it's OK if no keystore password has been provided.
* We want to make sure that we can load the keystore data, i.e.,
* the keystore data has the right format. If we cannot load the
* keystore, why bother asking the user for his or her password?
* Only if we were able to load the keystore, and no keystore
* password has been provided, will we prompt the user for the
* keystore password to verify the keystore integrity.
* This means that the keystore is loaded twice: first load operation
* checks the keystore format, second load operation verifies the
* keystore integrity.
*
* If the keystore password has already been provided (at the
* command line), however, the keystore is loaded only once, and the
* keystore format and integrity are checked "at the same time".
*
* Null stream keystores are loaded later.
*/
if (!nullStream) {
}
}
// All commands that create or modify the keystore require a keystore
// password.
// If we are creating a new non nullStream-based keystore,
// insist that the password be at least 6 characters
("Keystore.password.must.be.at.least.6.characters"));
}
// only prompt if (protectedPath == false)
command == GENKEYPAIR ||
command == IMPORTCERT ||
command == IMPORTKEYSTORE ||
command == CHANGEALIAS ||
command == STOREPASSWD ||
command == IDENTITYDB)) {
int count = 0;
do {
if (command == IMPORTKEYSTORE) {
} else {
}
// If we are creating a new non nullStream-based keystore,
// insist that the password be at least 6 characters
("Keystore.password.is.too.short.must.be.at.least.6.characters"));
}
// If the keystore file does not exist and needs to be
// created, the storepass should be prompted twice.
}
}
count++;
return;
}
} else if (!protectedPath
&& isKeyStoreRelated(command)) {
// here we have EXPORTCERT and LIST (info valid until STOREPASSWD)
}
}
// Now load a nullStream-based keystore,
// or verify the integrity of an input stream-based keystore
if (nullStream) {
}
}
"Warning.Different.store.and.key.passwords.not.supported.for.PKCS12.KeyStores.Ignoring.user.specified.command.value."));
}
}
}
}
// Create a certificate factory
}
if (trustcacerts) {
caks = getCacertsKeyStore();
}
// Perform the specified command
(filename));
}
try {
} finally {
}
}
("Certification.request.stored.in.file.filename."));
}
kssave = true;
} else if (command == EXPORTCERT) {
(filename));
}
try {
} finally {
}
}
("Certificate.stored.in.file.filename."));
}
} else if (command == GENKEYPAIR) {
if (keyAlgName == null) {
keyAlgName = "DSA";
}
kssave = true;
if (keyAlgName == null) {
keyAlgName = "DES";
}
kssave = true;
} else if (command == IDENTITYDB) {
}
try {
} finally {
}
}
} else if (command == IMPORTCERT) {
}
try {
if (keyStore.entryInstanceOf(
if (kssave) {
("Certificate.reply.was.installed.in.keystore"));
} else {
("Certificate.reply.was.not.installed.in.keystore"));
}
KeyStore.TrustedCertificateEntry.class)) {
if (kssave) {
("Certificate.was.added.to.keystore"));
} else {
("Certificate.was.not.added.to.keystore"));
}
}
} finally {
}
}
} else if (command == IMPORTKEYSTORE) {
kssave = true;
// added to make sure only key can go thru
}
}
"Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key"));
}
kssave = true;
} else if (command == CHANGEALIAS) {
}
// in PKCS11, clone a PrivateKeyEntry will delete the old one
}
kssave = true;
kssave = true;
} else {
}
kssave = true;
} else if (command == STOREPASSWD) {
if (storePassNew == null) {
}
kssave = true;
}
if (infilename != null) {
}
if (outfilename != null) {
}
try {
} finally {
}
}
}
}
}
try {
} finally {
}
}
} else if (command == PRINTCERTREQ) {
}
try {
} finally {
}
}
}
// If we need to save the keystore, do so.
if (kssave) {
if (verbose) {
}
if (token) {
} else {
if (nullStream) {
} else {
}
}
}
}
}
/**
* Generate a certificate: Read PKCS10 request from in, and print
* certificate to out. Use alias as CA, sigAlgName as the signature
* type.
*/
throws Exception {
lastDate);
if (sigAlgName == null) {
}
boolean canRead = false;
while (true) {
if (s == null) break;
// OpenSSL does not use NEW
//if (s.startsWith("-----BEGIN NEW CERTIFICATE REQUEST-----")) {
canRead = true;
//} else if (s.startsWith("-----END NEW CERTIFICATE REQUEST-----")) {
break;
} else if (canRead) {
}
}
}
}
null,
if (ca instanceof X509Certificate) {
if (!isSelfSigned(xca)) {
}
}
}
}
throws Exception {
throw new Exception("Must provide -id when -gencrl");
}
lastDate);
if (sigAlgName == null) {
}
if (d >= 0) {
} else {
}
}
if (rfc) {
} else {
}
}
/**
* Creates a PKCS#10 cert signing request, corresponding to the
* keys (and name) associated with a given alias.
*/
throws Exception
{
}
}
}
// Attribute name is not significant
// Construct a Signature object, so that we can sign the request
if (sigAlgName == null) {
}
// Sign the request and base-64 encode it
}
/**
* Deletes an entry from the keystore.
*/
}
}
/**
* Exports a certificate from the keystore.
*/
throws Exception
{
printWarning();
}
}
}
}
}
/**
* Prompt the user for a keypass when generating a key entry.
* @param alias the entry we will set password for
* @param orig the original entry of doing a dup, null if generate new
* @param origPass the password to copy from if user press ENTER
*/
return origPass;
} else if (!token && !protectedPath) {
// Prompt for key password
int count;
("Enter.key.password.for.alias."));
(".RETURN.if.same.as.keystore.password."));
} else {
(".RETURN.if.same.as.for.otherAlias."));
}
return origPass;
continue;
}
return entered;
} else {
("Key.password.is.too.short.must.be.at.least.6.characters"));
}
}
if (count == 3) {
("Too.many.failures.Key.entry.not.cloned"));
} else {
("Too.many.failures.key.not.added.to.keystore"));
}
}
}
return null; // PKCS11, MSCAPI, or -protected
}
/**
* Creates a new secret key.
*/
int keysize)
throws Exception
{
}
("Secret.key.not.generated.alias.alias.already.exists"));
}
if (keysize != -1) {
} else {
("Please.provide.keysize.for.secret.key.generation"));
}
}
}
/**
* If no signature algorithm was specified at the command line,
* we choose one that is compatible with the selected private key
*/
throws Exception {
return "SHA1WithDSA";
return "SHA256WithRSA";
return "SHA256withECDSA";
} else {
("Cannot.derive.signature.algorithm"));
}
}
/**
* Creates a new key pair and self-signed certificate.
*/
throws Exception
{
if (keysize == -1) {
keysize = 256;
keysize = 2048;
} else {
keysize = 1024;
}
}
}
("Key.pair.not.generated.alias.alias.already.exists"));
}
if (sigAlgName == null) {
}
// If DN is provided, parse it. Otherwise, prompt the user for it.
x500Name = getX500Name();
} else {
}
null,
null,
null);
if (verbose) {
("Generating.keysize.bit.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.validality.days.for"));
x500Name};
}
}
}
/**
* Clones an entry
* @param orig original alias
* @param dest destination alias
* @changePassword if the password can be changed
*/
throws Exception
{
}
}
} else {
if (keyPassNew == null) {
}
}
}
}
/**
* Changes a key password.
*/
{
}
}
if (keyPassNew == null) {
}
}
/**
* Imports a JDK 1.1-style identity database. We can only store one
* certificate per identity, because we use the identity's name as the
* alias (which references a keystore entry), and aliases must be unique.
*/
throws Exception
{
("No.entries.from.identity.database.added"));
}
/**
* Prints a single keystore entry.
*/
boolean printWarning)
throws Exception
{
printWarning();
}
}
if (!token) {
("Creation.date.keyStore.getCreationDate.alias."));
}
} else {
if (!token) {
} else {
}
}
} else {
}
} else {
}
// Get the chain
} else if (debug) {
} else {
}
}
} else {
// Print the digest of the user cert only
}
}
KeyStore.TrustedCertificateEntry.class)) {
// We have a trusted certificate entry
} else if (rfc) {
} else if (debug) {
} else {
}
} else {
}
}
/**
* Load the srckeystore from a stream, used in -importkeystore
* @returns the src KeyStore
*/
boolean isPkcs11 = false;
(".keystore.must.be.NONE.if.storetype.is.{0}"), srcstoretype));
tinyHelp();
}
isPkcs11 = true;
} else {
if (srcksfname != null) {
("Source.keystore.file.exists.but.is.empty.") +
}
} else {
("Please.specify.srckeystore"));
}
}
try {
if (srcProviderName == null) {
} else {
}
if (srcstorePass == null
&& !srcprotectedPath
}
// always let keypass be storepass when using pkcs12
"Warning.Different.store.and.key.passwords.not.supported.for.PKCS12.KeyStores.Ignoring.user.specified.command.value."));
}
}
} finally {
}
}
if (srcstorePass == null
// anti refactoring, copied from printWarning(),
// but change 2 lines
(".WARNING.WARNING.WARNING."));
(".The.integrity.of.the.information.stored.in.the.srckeystore."));
(".WARNING.WARNING.WARNING."));
}
return store;
}
/**
* import all keys and certs from importkeystore.
* keep alias unchanged if no name conflict, otherwise, prompt.
* keep keypass unchanged for keys
*/
} else {
"if.alias.not.specified.destalias.srckeypass.and.destkeypass.must.not.be.specified"));
}
}
/*
* Information display rule of -importkeystore
* 1. inside single, shows failure
* 2. inside all, shows sucess
* 3. inside all where there is a failure, prompt for continue
* 4. at the final of all, shows summary
*/
}
/**
* Import a single entry named alias from srckeystore
* @returns 1 if the import action succeed
* 0 if user choose to ignore an alias-dumplicated entry
* 2 if setEntry throws Exception
*/
throws Exception {
if (noprompt) {
} else {
("Enter.new.alias.name.RETURN.to.cancel.import.for.this.entry."));
"Entry.for.alias.alias.not.imported.")).format(
source));
return 0;
}
}
}
}
// According to keytool.html, "The destination entry will be protected
// using destkeypass. If destkeypass is not provided, the destination
// entry will be protected with the source entry password."
// so always try to protect with destKeyPass.
if (destKeyPass != null) {
}
try {
return 1;
} catch (KeyStoreException kse) {
"Problem.importing.entry.for.alias.alias.exception.Entry.for.alias.alias.not.imported."));
return 2;
}
}
int ok = 0;
e.hasMoreElements(); ) {
if (result == 1) {
ok++;
MessageFormat form = new MessageFormat(rb.getString("Entry.for.alias.alias.successfully.imported."));
} else if (result == 2) {
if (!noprompt) {
break;
}
}
}
}
"Import.command.completed.ok.entries.successfully.imported.fail.entries.failed.or.cancelled"));
}
/**
* Prints all keystore entries.
*/
throws Exception
{
printWarning();
} else {
}
("Your.keystore.contains.keyStore.size.entry")) :
("Your.keystore.contains.keyStore.size.entries"));
e.hasMoreElements(); ) {
("STAR"));
("STARNN"));
}
}
}
return new Iterable<T>() {
return new Iterator<T>() {
public boolean hasNext() {
return e.hasMoreElements();
}
public T next() {
return e.nextElement();
}
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
};
}
};
}
/**
* Loads CRLs from a source. This method is also called in JarSigner.
* @param src the source, which means System.in if null, or a URI,
* or a bare file path name
*/
} else {
try {
// No input stream for LDAP
} else {
}
} catch (Exception e) {
try {
throw e2; // More likely a bare file path
} else {
throw e; // More likely a protocol or network problem
}
}
}
}
try {
// Read the full stream before feeding to X509Factory,
// otherwise, keytool -gencrl | keytool -printcrl
// might not work properly, since -gencrl is slow
// and there's no data in the pipe at the beginning.
byte[] b = new byte[4096];
while (true) {
if (len < 0) break;
}
} finally {
}
}
} else { // must be LDAP, and uri is not null
LDAPCertStoreHelper h = new LDAPCertStoreHelper();
}
}
/**
* Returns CRLs described in a X509Certificate's CRLDistributionPoints
* Extension. Only those containing a general name of type URI are read.
*/
throws Exception {
}
}
break; // Different name should point to same CRL
}
}
}
}
return crls;
}
throws Exception {
if (cert instanceof X509Certificate) {
try {
return s;
} catch (Exception e) {
}
}
}
}
return null;
}
throws Exception {
}
}
}
}
("STAR"));
("STARNN"));
}
}
}
throws Exception {
if (rfc) {
} else {
}
}
throws Exception {
boolean started = false;
while (true) {
if (s == null) break;
if (!started) {
if (s.startsWith("-----")) {
started = true;
}
} else {
if (s.startsWith("-----")) {
break;
}
}
}
out.printf(rb.getString("PKCS.10.Certificate.Request.Version.1.0.Subject.s.Public.Key.s.format.s.key."),
}
} else {
}
}
if (debug) {
}
}
/**
* Reads a certificate (or certificate chain) and prints its contents in
* a human readable format.
*/
throws Exception
{
try {
} catch (CertificateException ce) {
}
if (c.isEmpty()) {
}
try {
} catch (ClassCastException cce) {
}
}
}
}
}
byte[] buffer = new byte[8192];
int pos = 0;
while (entries.hasMoreElements()) {
try {
// we just read. this will throw a SecurityException
// populate the signers
}
} finally {
}
}
if (rfc) {
} else {
printX509Cert(x, out);
}
}
if (rfc) {
} else {
printX509Cert(x, out);
}
}
}
}
}
}
}
}
final boolean[] certPrinted = new boolean[1];
new X509ExtendedTrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(
throw new UnsupportedOperationException();
}
throws CertificateException {
throw new UnsupportedOperationException();
}
throw new UnsupportedOperationException();
}
public void checkServerTrusted(
try {
if (rfc) {
} else {
}
} catch (Exception e) {
if (debug) {
e.printStackTrace();
}
}
}
// Set to true where there's something to print
certPrinted[0] = true;
}
}
throws CertificateException {
}
throws CertificateException {
}
}
}, null);
new HostnameVerifier() {
return true;
}
});
// HTTPS instead of raw SSL, so that -Dhttps.proxyHost and
// -Dhttps.proxyPort can be used. Since we only go through
// the handshake process, an HTTPS server is not needed.
// This program should be able to deal with any SSL-based
// network service.
try {
} catch (Exception e) {
ex = e;
}
// If the certs are not printed out, we consider it an error even
// if the URL connection is successful.
if (!certPrinted[0]) {
}
throw e;
}
} else {
}
try {
} finally {
}
}
}
}
/**
* Creates a self-signed certificate, and stores it as a single-element
* certificate chain.
*/
throws Exception
{
}
// Determine the signature algorithm
if (sigAlgName == null) {
}
// Get the old certificate
}
if (!(oldCert instanceof X509Certificate)) {
}
// convert to X509CertImpl, so that we can modify selected fields
// (no public APIs available yet)
+ "." +
// Extend its validity
lastDate);
// Make new serial number
// Set owner and issuer fields
// Get the owner name from the certificate
} else {
// Use the owner name specified at the command line
}
// Make issuer same as owner (self-signed!)
// The inner and outer signature algorithms have to match.
// The way we achieve that is really ugly, but there seems to be no
// other solution: We first sign the cert, then retrieve the
// outer sigalg and use it to set the inner sigalg
null,
null);
// Sign the new certificate
// Store the new certificate as a single-element certificate chain
new Certificate[] { newCert } );
if (verbose) {
}
}
/**
* Processes a certificate reply from a certificate authority.
*
* <p>Builds a certificate chain on top of the certificate reply,
* using trusted certificates from the keystore. The chain is complete
* after a self-signed certificate has been encountered. The self-signed
* certificate is considered a root certificate authority, and is stored
* at the end of the chain.
*
* <p>The newly generated chain replaces the old chain associated with the
* key entry.
*
* @return true if the certificate reply was installed, otherwise false.
*/
throws Exception
{
}
}
}
// Read the certificates in the reply
if (c.isEmpty()) {
}
// single-cert reply
} else {
// cert-chain reply (e.g., PKCS#7)
}
// Now store the newly established chain in the keystore. The new
// chain replaces the old one.
newChain);
return true;
} else {
return false;
}
}
/**
* Imports a certificate and adds it to the list of trusted certificates.
*
* @return true if the certificate was added, otherwise false.
*/
throws Exception
{
}
("Certificate.not.imported.alias.alias.already.exists"));
}
// Read the certificate
try {
} catch (ClassCastException cce) {
} catch (CertificateException ce) {
}
// if certificate is self-signed, make sure it verifies
boolean selfSigned = false;
if (isSelfSigned(cert)) {
selfSigned = true;
}
if (noprompt) {
return true;
}
// check if cert already exists in keystore
if (trustalias != null) {
("Certificate.already.exists.in.keystore.under.alias.trustalias."));
} else if (selfSigned) {
("Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias."));
}
if (trustalias == null) {
// Print the cert and ask user if they really want to add
// it to their keystore
}
}
return true;
} else {
return false;
}
}
// Try to establish trust chain
try {
return true;
}
} catch (Exception e) {
// Print the cert and ask user if they really want to add it to
// their keystore
return true;
} else {
return false;
}
}
return false;
}
/**
* Prompts user for new password. New password must be different from
* old one.
*
* @param prompt the message that gets prompted on the screen
* @param oldPasswd the current (i.e., old) password
*/
throws Exception
{
("Password.is.too.short.must.be.at.least.6.characters"));
} else {
form = new MessageFormat
} else {
return entered;
}
}
}
}
}
}
/**
* Prompts user for alias name.
* @param prompt the {0} of "Enter {0} alias name: " in prompt line
* @returns the string entered by the user, without the \n at the end
*/
} else {
}
return (new BufferedReader(new InputStreamReader(
}
/**
* Prompts user for an input string from the command line (System.in)
* @prompt the prompt string printed
* @returns the string entered by the user, without the \n at the end
*/
return (new BufferedReader(new InputStreamReader(
}
/**
* Prompts user for key password. User may select to choose the same
* password (<code>otherKeyPass</code>) as for <code>otherAlias</code>.
*/
char[] otherKeyPass)
throws Exception
{
int count = 0;
do {
if (otherKeyPass != null) {
("Enter.key.password.for.alias."));
(".RETURN.if.same.as.for.otherAlias."));
} else {
("Enter.key.password.for.alias."));
}
}
count++;
}
return keyPass;
}
/**
* Prints a certificate in a human readable format.
*/
throws Exception
{
/*
out.println("Owner: "
+ cert.getSubjectDN().toString()
+ "\n"
+ "Issuer: "
+ cert.getIssuerDN().toString()
+ "\n"
+ "Serial number: " + cert.getSerialNumber().toString(16)
+ "\n"
+ "Valid from: " + cert.getNotBefore().toString()
+ " until: " + cert.getNotAfter().toString()
+ "\n"
+ "Certificate fingerprints:\n"
+ "\t MD5: " + getCertFingerPrint("MD5", cert)
+ "\n"
+ "\t SHA1: " + getCertFingerPrint("SHA1", cert));
*/
};
if (cert instanceof X509CertImpl) {
+ "." +
}
}
}
throws Exception {
int extnum = 0;
if (extnum == 0) {
}
byte[] v = ext.getExtensionValue();
if (v.length == 0) {
} else {
}
}
}
}
/**
* Returns true if the certificate is self-signed, false otherwise.
*/
}
return false;
}
try {
return true;
} catch (Exception e) {
return false;
}
}
/**
* Locates a signer for a given certificate from a given keystore and
* returns the signer's certificate.
* @param cert the certificate whose signer is searched, not null
* @param ks the keystore to search with, not null
* @return <code>cert</code> itself if it's already inside <code>ks</code>,
* or a certificate inside <code>ks</code> who signs <code>cert</code>,
* or null otherwise.
*/
throws Exception {
return cert;
}
aliases.hasMoreElements(); ) {
if (trustedCert != null) {
try {
return trustedCert;
} catch (Exception e) {
// Not verified, skip to the next one
}
}
}
return null;
}
/**
* Gets an X.500 name suitable for inclusion in a certification request.
*/
int maxRetry = 20;
do {
if (maxRetry-- < 0) {
"Too.many.retries.program.terminated"));
}
("What.is.the.name.of.your.organizational.unit."),
city);
state);
("What.is.the.two.letter.country.code.for.this.unit."),
country);
return name;
}
throws IOException
{
}
return value;
}
/**
* Writes an X.509 certificate in base64 or binary encoding to an output
* stream.
*/
throws IOException, CertificateException
{
if (rfc) {
} else {
}
}
/**
* Converts a byte to hex digit and writes to the supplied buffer
*/
'9', 'A', 'B', 'C', 'D', 'E', 'F' };
int low = (b & 0x0f);
}
/**
* Converts a byte array to hex string
*/
for (int i = 0; i < len; i++) {
if (i < len-1) {
}
}
}
/**
* Recovers (private) key associated with given alias.
*
* @return an array of objects, where the 1st element in the array is the
* recovered private key, and the 2nd element is the password used to
* recover it.
*/
char[] keyPass)
throws Exception
{
}
}
// Try to recover the key using the keystore password
try {
} catch (UnrecoverableKeyException e) {
// Did not work out, so prompt user for key password
if (!token) {
} else {
throw e;
}
}
} else {
}
}
/**
* Recovers entry associated with given alias.
*
* @return an array of objects, where the 1st element in the array is the
* recovered entry, and the 2nd element is the password used to
* recover it (null if no password).
*/
char[] pstore,
}
try {
// First attempt to access entry without key password
// (PKCS11 entry or trusted certificate entry, for example)
} catch (UnrecoverableEntryException une) {
// should not happen, but a possibility
throw une;
}
// entry is protected
// try provided key password
} else {
// try store pass
try {
} catch (UnrecoverableEntryException une2) {
// P12 keystore currently does not support separate
// store and entry passwords
throw une2;
} else {
// prompt for entry password
}
}
}
}
}
/**
* Gets the requested finger print of the certificate.
*/
throws Exception
{
return toHexString(digest);
}
/**
* Prints warning about missing integrity check.
*/
private void printWarning() {
(".WARNING.WARNING.WARNING."));
(".The.integrity.of.the.information.stored.in.your.keystore."));
(".WARNING.WARNING.WARNING."));
}
/**
* Validates chain in certification reply, and returns the ordered
* elements of the chain (with user certificate first, and root
* certificate last in the array).
*
* @param alias the alias name
* @param userCert the user certificate of the alias
* @param replyCerts the chain provided in the reply
*/
throws Exception
{
// order the certs in the reply (bottom-up).
// we know that all certs in the reply are of type X.509, because
// we parsed them using an X.509 certificate factory
int i;
break;
}
}
if (i == replyCerts.length) {
("Certificate.reply.does.not.contain.public.key.for.alias."));
}
replyCerts[i] = tmpCert;
// find a cert in the reply who signs thisCert
int j;
for (j=i; j<replyCerts.length; j++) {
tmpCert = replyCerts[i];
replyCerts[i] = replyCerts[j];
replyCerts[j] = tmpCert;
break;
}
}
if (j == replyCerts.length) {
throw new Exception
}
}
if (noprompt) {
return replyCerts;
}
// do we trust the cert at the top?
}
return null;
}
} else {
// append the root CA cert to the chain
Certificate[] tmpCerts =
}
}
return replyCerts;
}
/**
* Establishes a certificate chain (using trusted certificates in the
* keystore), starting with the user certificate
* and ending at a self-signed certificate found in the keystore.
*
* @param userCert the user certificate of the alias
* @param certToVerify the single certificate provided in the reply
*/
throws Exception
{
// Make sure that the public key of the certificate reply matches
// the original public key in the keystore
("Public.keys.in.reply.and.keystore.don.t.match"));
}
// If the two certs are identical, we're done: no need to import
// anything
("Certificate.reply.and.certificate.in.keystore.are.identical"));
}
}
// Build a hash table of all certificates in the keystore.
// Use the subject distinguished name as the key into the hash table.
// All certificates associated with the same subject distinguished
// name are stored in the same hash table entry as a vector.
}
if (trustcacerts) {
}
}
}
// start building chain
// buildChain() returns chain with self-signed root-cert first and
// user-cert last, so we need to invert the chain before we store
// it
int j=0;
j++;
}
return newChain;
} else {
throw new Exception
}
}
/**
* Recursively tries to establish chain from pool of trusted certs.
*
* @param certToVerify the cert that needs to be verified.
* @param chain the chain that's being built.
* @param certs the pool of trusted certs
*
* @return true if successful, false otherwise.
*/
if (isSelfSigned(certToVerify)) {
// reached self-signed root cert;
// no verification needed because it's trusted.
return true;
}
// Get the issuer's certificate(s)
return false;
}
// Try out each certificate in the vector, until we find one
// whose public key verifies the signature of the certificate
// in question.
issuerCerts.hasMoreElements(); ) {
try {
} catch (Exception e) {
continue;
}
return true;
}
}
return false;
}
/**
*
* @return the user's decision, can only be "YES" or "NO"
*/
throws IOException
{
int maxRetry = 20;
do {
if (maxRetry-- < 0) {
"Too.many.retries.program.terminated"));
}
reply = "NO";
reply = "YES";
} else {
}
return reply;
}
/**
* Returns the keystore with the configured CA certificates.
*/
throws Exception
{
+ "cacerts");
return null;
}
try {
} finally {
}
}
return caks;
}
/**
* Stores the (leaf) certificates of a keystore in a hashtable.
* All certs belonging to the same CA are stored in a vector that
* in turn is stored in the hashtable, keyed by the CA's subject DN
*/
throws Exception {
aliases.hasMoreElements(); ) {
} else {
}
}
}
}
}
/**
* Returns the issue time that's specified the -startdate option
* @param s the value of -startdate option
*/
Calendar c = new GregorianCalendar();
if (s != null) {
if (len == 0) {
throw ioe;
}
// Form 1: ([+-]nnn[ymdHMS])+
int start = 0;
int sign = 0;
default: throw ioe;
}
int i = start+1;
for (; i<len; i++) {
}
int unit = 0;
switch (s.charAt(i)) {
default: throw ioe;
}
start = i + 1;
}
} else {
if (len == 19) {
throw ioe;
} else if (len == 10) {
date = s;
} else if (len == 8) {
time = s;
} else {
throw ioe;
}
} else {
throw ioe;
}
}
} else {
throw ioe;
}
}
}
}
return c.getTime();
}
/**
* Match a command (may be abbreviated) with a command set.
* @param s the command provided
* @param list the legal command set. If there is a null, commands after it
* are regarded experimental, which means they are supported but their
* existence should not be revealed to user.
* @return the position of a single match, or -1 if none matched
* @throws Exception if s is ambiguous
*/
int nmatch = 0;
experiment = i;
continue;
}
} else {
boolean first = true;
for (char c: one.toCharArray()) {
if (first) {
first = false;
} else {
if (!Character.isLowerCase(c)) {
}
}
}
}
}
}
if (nmatch == 0) {
return -1;
} else if (nmatch == 1) {
return match[0];
} else {
// If multiple matches is in experimental commands, ignore them
return match[0];
}
("command.{0}.is.ambiguous."));
}
}
}
/**
* Create a GeneralName object from known types
* @param t one of 5 known types
* @param v value
* @return which one
*/
throws Exception {
if (p < 0) {
"Unrecognized.GeneralName.type.") + t);
}
switch (p) {
}
return new GeneralName(gn);
}
"BasicConstraints",
"KeyUsage",
"ExtendedKeyUsage",
"SubjectAlternativeName",
"IssuerAlternativeName",
"SubjectInfoAccess",
"AuthorityInfoAccess",
null,
"CRLDistributionPoints",
};
throws Exception {
default: return new ObjectIdentifier(type);
}
}
/**
* Create X509v3 extensions from a string representation. Note that the
* SubjectKeyIdentifierExtension will always be created non-critical besides
* the extension requested in the <code>extstr</code> argument.
*
* @param reqex the requested extensions, can be null, used for -gencert
* @param ext the original extensions, can be null, used for -selfcert
* @param extstrs -ext values, Read keytool doc
* @param pkey the public key for the certificate
* @param akey the public key for the authority (issuer)
* @return the created CertificateExtensions
*/
// This should not happen
throw new Exception("One of request and original should be null.");
}
try {
// name{:critical}{=value}
// Honoring requested extensions
// First check existence of "all"
}
// one by one for others
// add or remove
boolean add = true;
// -1, unchanged, 0 crtical, 1 non-critical
int action = -1;
add = false;
} else {
if (colonpos >= 0) {
"critical", "non-critical");
if (action == -1) {
("Illegal.value.") + item);
}
}
}
if (add) {
e = Extension.newExtension(
e.getExtensionId(),
!e.isCritical(),
e.getExtensionValue());
}
} else {
}
}
break;
}
}
}
boolean isCritical = false;
if (eqpos >= 0) {
} else {
}
if (colonpos >= 0) {
isCritical = true;
}
}
continue;
}
switch (exttype) {
case 0: // BC
int pathLen = -1;
boolean isCA = false;
isCA = true;
} else {
try { // the abbr format
isCA = true;
} catch (NumberFormatException ufe) {
// ca:true,pathlen:1
("Illegal.value.") + extstr);
} else {
} else {
("Illegal.value.") + extstr);
}
}
}
}
}
pathLen));
break;
case 1: // KU
boolean[] ok = new boolean[9];
int p = oneOf(s,
"digitalSignature", // (0),
"nonRepudiation", // (1)
"keyEncipherment", // (2),
"dataEncipherment", // (3),
"keyAgreement", // (4),
"keyCertSign", // (5),
"cRLSign", // (6),
"encipherOnly", // (7),
"decipherOnly", // (8)
"contentCommitment" // also (1)
);
if (p < 0) {
}
if (p == 9) p = 1;
ok[p] = true;
}
// The above KeyUsageExtension constructor does not
// allow isCritical value, so...
kue.getExtensionValue()));
} else {
("Illegal.value.") + extstr);
}
break;
case 2: // EKU
int p = oneOf(s,
"anyExtendedKeyUsage",
"serverAuth", //1
"clientAuth", //2
"codeSigning", //3
"emailProtection", //4
"", //5
"", //6
"", //7
"timeStamping", //8
"OCSPSigning" //9
);
if (p < 0) {
try {
v.add(new ObjectIdentifier(s));
} catch (Exception e) {
"Unknown.extendedkeyUsage.type.") + s);
}
} else if (p == 0) {
} else {
}
}
new ExtendedKeyUsageExtension(isCritical, v));
} else {
("Illegal.value.") + extstr);
}
break;
case 3: // SAN
case 4: // IAN
if (colonpos < 0) {
}
}
if (exttype == 3) {
isCritical, gnames));
} else {
isCritical, gnames));
}
} else {
("Illegal.value.") + extstr);
}
break;
case 5: // SIA, always non-critical
case 6: // AIA, always non-critical
if (isCritical) {
"This.extension.cannot.be.marked.as.critical.") + extstr);
}
new ArrayList<>();
("Illegal.value.") + extstr);
}
int p = oneOf(m,
"",
"ocsp", //1
"caIssuers", //2
"timeStamping", //3
"",
"caRepository" //5
);
if (p < 0) {
try {
oid = new ObjectIdentifier(m);
} catch (Exception e) {
"Unknown.AccessDescription.type.") + m);
}
} else {
}
oid, createGeneralName(t, v)));
}
if (exttype == 5) {
} else {
}
} else {
("Illegal.value.") + extstr);
}
break;
case 8: // CRL, experimental, only support 1 distributionpoint
if (colonpos < 0) {
}
}
} else {
("Illegal.value.") + extstr);
}
break;
case -1:
int pos = 0;
for (char c: value.toCharArray()) {
int hex;
if (c >= '0' && c <= '9') {
hex = c - '0' ;
} else if (c >= 'A' && c <= 'F') {
} else if (c >= 'a' && c <= 'f') {
} else {
continue;
}
} else {
}
pos++;
}
"Odd.number.of.hex.digits.found.") + extstr);
}
} else {
data = new byte[0];
}
.toByteArray()));
break;
default:
"Unknown.extension.type.") + extstr);
}
}
// always non-critical
}
} catch(IOException e) {
throw new RuntimeException(e);
}
return ext;
}
/**
* Prints the usage of this tool.
*/
private void usage() {
// Left and right sides of the options list
// Check if there's an unknown option
boolean found = false;
// Length of left side of options list
int lenLeft = 0;
}
}
}
"Use.keytool.help.for.all.available.commands"));
} else {
"Key.and.Certificate.Management.Tool"));
if (c == KEYCLONE) break;
}
"Use.keytool.command.name.help.for.usage.of.command.name"));
}
}
private void tinyHelp() {
usage();
if (debug) {
throw new RuntimeException("NO BIG ERROR, SORRY");
} else {
}
}
tinyHelp();
}
tinyHelp();
return null; // Useless, tinyHelp() already exits.
}
// This method also used by JarSigner
return arg.toCharArray();
"Cannot.find.environment.variable.") + arg);
return null;
} else {
return value.toCharArray();
}
try {
try {
if (f.exists()) {
} else {
"Cannot.find.file.") + arg);
return null;
}
}
url.openStream()));
return new char[0];
} else {
return value.toCharArray();
}
} catch (IOException ioe) {
return null;
}
} else {
modifier);
return null;
}
}
}
// This class is exactly the same as com.sun.tools.javac.util.Pair,
// it's copied here since the original one is not included in JRE.
class Pair<A, B> {
public final A fst;
public final B snd;
}
}
}
return
}
public int hashCode() {
}
return new Pair<>(a,b);
}
}