java.lang.Object
net.i2p.crypto.KeyStoreUtil

public final class KeyStoreUtilextends Object
Keystore utilities, consolidated from various places.
  • Field Details

    • _blacklistLogged

      private static boolean _blacklistLogged
      Whether the blacklist warning has been logged.
    • DEFAULT_KEYSTORE_PASSWORD

      public static final String DEFAULT_KEYSTORE_PASSWORD
      Well-known JKS password used when no other is configured.
      See Also:
    • DEFAULT_KEY_ALGORITHM

      private static final String DEFAULT_KEY_ALGORITHM
      Default algorithm for the router keys.
      See Also:
    • DEFAULT_KEY_SIZE

      private static final int DEFAULT_KEY_SIZE
      Default router key size, in bits.
      See Also:
    • DEFAULT_CA_KEY_ALGORITHM

      private static final String DEFAULT_CA_KEY_ALGORITHM
      Default algorithm for the CA keys.
      See Also:
    • DEFAULT_CA_KEY_SIZE

      private static final int DEFAULT_CA_KEY_SIZE
      Default CA key size, in bits.
      See Also:
    • DEFAULT_KEY_VALID_DAYS

      private static final int DEFAULT_KEY_VALID_DAYS
      Default time a generated certificate stays valid.
      See Also:
    • BLACKLIST_SHA1

      private static final String[] BLACKLIST_SHA1
      SHA1 hashes

      No reports of some of these in a Java keystore but just to be safe... CNNIC ones are in Ubuntu keystore.

      In comments below are the serial numer, CN, and OU.

    • _blacklist

      private static final Set<SHA1Hash> _blacklist
      Fingerprint hashes of revoked certificates.
    • STOREPASS_ENV

      private static final String STOREPASS_ENV
      Env var names used by createKeysCLI() to pass passwords to keytool via :env.
      See Also:
    • KEYPASS_ENV

      private static final String KEYPASS_ENV
      Environment variable holding the keystore password.
      See Also:
  • Constructor Details

    • KeyStoreUtil

      public KeyStoreUtil()
      Constructor. Every helper works on the KeyStore it is given, so an instance carries no state.
  • Method Details

    • createKeyStore

      public static KeyStore createKeyStore(File ksFile, String password) throws GeneralSecurityException, IOException
      Create a new KeyStore object, and load it from ksFile if it is non-null and it exists. If ksFile is non-null and it does not exist, create a new empty keystore file.
      Parameters:
      ksFile - may be null
      password - may be null
      Returns:
      the keystore, loaded from ksFile if it existed and otherwise newly initialized
      Throws:
      GeneralSecurityException - if keystore operations fail
      IOException - if file operations fail
    • loadSystemKeyStore

      public static KeyStore loadSystemKeyStore()
      Loads certs from location of javax.net.ssl.keyStore property, else from $JAVA_HOME/lib/security/jssecacerts, else from $JAVA_HOME/lib/security/cacerts.
      Returns:
      null on catastrophic failure, returns empty KeyStore if can't load system file
    • loadCerts

      private static boolean loadCerts(File file, KeyStore ks)
      Load all X509 Certs from a key store File into a KeyStore Note that each call reinitializes the KeyStore.
      Parameters:
      file - the key store file to read, a missing file yields false
      ks - the key store to reinitialize and load the certs into
      Returns:
      true if the file was loaded, false if it is missing or cannot be read
    • countCerts

      public static int countCerts(KeyStore ks)
      Count all X509 Certs in a key store.
      Parameters:
      ks - the key store
      Returns:
      number successfully added
    • logCertExpiration

      public static boolean logCertExpiration(File f, String ksPW, long expiresWithin)
      Validate expiration for all private key certs in a key store. Use this for keystores containing selfsigned certs where the user will be expected to renew an expiring cert. Use this for Jetty keystores, where we aren't doing the loading ourselves.

      If a cert isn't valid, it will probably cause bigger problems later when it's used.

      Parameters:
      f - the keystore file to read the certificates from
      ksPW - the keystore password, which must not be null
      expiresWithin - ms if cert expires within this long, we will log a warning, e.g. 180*24*60*60*1000L
      Returns:
      true if all are good, false if we logged something
    • logCertExpiration

      public static boolean logCertExpiration(KeyStore ks, String location, long expiresWithin)
      Validate expiration for all private key certs in a key store. Use this for keystores containing selfsigned certs where the user will be expected to renew an expiring cert. Use this for keystores we are feeding to an SSLContext and ServerSocketFactory.

      We added support for self-signed certs in 0.8.3 2011-01, with a 10-year expiration. We still don't generate them by default. We don't expect anybody's certs to expire until 2021.

      Parameters:
      ks - the key store whose private key aliases supply the certificate chains
      location - the path or other identifying info, for logging only
      expiresWithin - ms if cert expires within this long, we will log a warning, e.g. 180*24*60*60*1000L
      Returns:
      true if all are good, false if we logged something
    • removeBlacklistedCerts

      private static int removeBlacklistedCerts(KeyStore ks)
      Remove all blacklisted X509 Certs in a key store.
      Parameters:
      ks - the key store whose certificate entries are checked and pruned
      Returns:
      number successfully removed
    • addCerts

      public static int addCerts(File dir, KeyStore ks)
      Load all X509 Certs from a directory and add them to the trusted set of certificates in the key store

      This DOES check for revocation.

      Parameters:
      dir - the directory containing certificate files
      ks - the key store to add certificates to
      Returns:
      number successfully added
    • addCert

      public static boolean addCert(File file, String alias, KeyStore ks)
      Load an X509 Cert from a file and add it to the trusted set of certificates in the key store

      This does NOT check for revocation.

      Parameters:
      file - the file to read the certificate from
      alias - the keystore entry name to store the certificate under
      ks - the keystore to add the certificate to
      Returns:
      true if the certificate was read and added, false if it is revoked, expired, not yet valid, or cannot be parsed
    • addCert

      public static boolean addCert(File file, String alias, KeyStore ks, CertStore cs)
      Load an X509 Cert from a file and add it to the trusted set of certificates in the key store

      This DOES check for revocation, IF cs is non-null.

      Parameters:
      file - the file to read the certificate from
      alias - the keystore entry name to store the certificate under
      ks - the keystore to add the certificate to
      cs - may be null; if non-null, check for revocation
      Returns:
      true if the certificate was read and added, false if it is revoked, expired, not yet valid, or cannot be parsed
    • randomString

      public static String randomString()
      Generates a random password for the keystore.
      Returns:
      48 base32 characters, 30 bytes of entropy
    • createKeys

      public static boolean createKeys(File ks, String alias, String cname, String ou, String keyPW)
      Create a keypair and store it in the keystore at ks, creating it if necessary. Use default keystore password, valid days, algorithm, and key size.

      As of 0.9.35, default algorithm and size depends on cname. If it appears to be a CA, it will use EC/256. Otherwise, it will use RSA/2048.

      Warning, may take a long time.

      Parameters:
      ks - path to the keystore
      alias - the name of the key
      cname - e.g. localhost. Must be a hostname or email address. IP addresses will not be correctly encoded.
      ou - the organizational unit of the certificate subject, e.g. console
      keyPW - the key password, must be at least 6 characters
      Returns:
      true if the key was generated and stored, false if it already exists or creation failed
    • createKeys

      public static boolean createKeys(File ks, String alias, String cname, Set<String> altNames, String ou, String keyPW)
      Create a keypair and store it in the keystore at ks, creating it if necessary. Use default keystore password, valid days, algorithm, and key size.

      As of 0.9.35, default algorithm and size depends on cname. If it appears to be a CA, it will use EC/256. Otherwise, it will use RSA/2048.

      Warning, may take a long time.

      Parameters:
      ks - path to the keystore
      alias - the name of the key
      cname - e.g. localhost. Must be a hostname or email address. IP addresses will not be correctly encoded.
      altNames - the Subject Alternative Names. May be null. May contain hostnames and/or IP addresses. cname, localhost, 127.0.0.1, and ::1 will be automatically added.
      ou - the organizational unit of the certificate subject, e.g. console
      keyPW - the key password, must be at least 6 characters
      Returns:
      true if the key was generated and stored, false if it already exists or creation failed
    • createKeys

      public static boolean createKeys(File ks, String ksPW, String alias, String cname, String ou, int validDays, String keyAlg, int keySize, String keyPW)
      Create a keypair and store it in the keystore at ks, creating it if necessary.

      For new code, the createKeysAndCRL(File, String, String, String, String, int, String, int, String) with the SigType argument is recommended over this one, as it throws exceptions, and returns the certificate and CRL.

      Warning, may take a long time.

      Parameters:
      ks - path to the keystore
      ksPW - the keystore password
      alias - the name of the key
      cname - e.g. localhost. Must be a hostname or email address. IP addresses will not be correctly encoded.
      ou - the organizational unit of the certificate subject, e.g. console
      validDays - e.g. 3652 (10 years)
      keyAlg - e.g. DSA , RSA, EC
      keySize - e.g. 1024
      keyPW - the key password, must be at least 6 characters
      Returns:
      true if the key was generated and stored, false if it already exists or creation failed
    • createKeys

      public static boolean createKeys(File ks, String ksPW, String alias, String cname, Set<String> altNames, String ou, int validDays, String keyAlg, int keySize, String keyPW)
      Create a keypair and store it in the keystore at ks, creating it if necessary.

      For new code, the createKeysAndCRL() with the SigType argument is recommended over this one, as it throws exceptions, and returns the certificate and CRL.

      Warning, may take a long time.

      Parameters:
      ks - path to the keystore
      ksPW - the keystore password
      alias - the name of the key
      cname - e.g. localhost. Must be a hostname or email address. IP addresses will not be correctly encoded.
      altNames - the Subject Alternative Names. May be null. May contain hostnames and/or IP addresses. cname, localhost, 127.0.0.1, and ::1 will be automatically added.
      ou - the organizational unit of the certificate subject, e.g. console
      validDays - e.g. 3652 (10 years)
      keyAlg - e.g. DSA , RSA, EC
      keySize - e.g. 1024
      keyPW - the key password, must be at least 6 characters
      Returns:
      true if the key was generated and stored, false if it already exists or creation failed
    • createKeysAndCRL

      public static Object[] createKeysAndCRL(File ks, String ksPW, String alias, String cname, String ou, int validDays, String keyAlg, int keySize, String keyPW) throws GeneralSecurityException, IOException
      New way - Native Java, does not call out to keytool. Create a keypair and store it in the keystore at ks, creating it if necessary.

      This returns the public key, private key, certificate, and CRL in an array. All of these are Java classes. Keys may be converted to I2P classes with SigUtil. The private key and selfsigned cert are stored in the keystore. The public key may be derived from the private key with KeyGenerator.getSigningPublicKey(SigningPrivateKey). The public key certificate may be stored separately with CertUtil.saveCert(Certificate, File) if desired. The CRL is not stored by this method, store it with CertUtil.saveCRL(X509CRL, File) or CertUtil.exportCRL(X509CRL, OutputStream) if desired.

      Throws on all errors. Warning, may take a long time.

      Parameters:
      ks - path to the keystore
      ksPW - the keystore password
      alias - the name of the key
      cname - e.g. localhost. Must be a hostname or email address. IP addresses will not be correctly encoded.
      ou - the organizational unit of the certificate subject, e.g. console
      validDays - e.g. 3652 (10 years)
      keyAlg - e.g. DSA , RSA, EC
      keySize - e.g. 1024
      keyPW - the key password, must be at least 6 characters
      Returns:
      all you need: rv[0] is a Java PublicKey rv[1] is a Java PrivateKey rv[2] is a Java X509Certificate rv[3] is a Java X509CRL
      Throws:
      GeneralSecurityException - if the keyAlg and keySize pair is not supported, or the keypair, certificate, or CRL cannot be generated or stored
      IOException - if the directory holding the keystore cannot be created, or the keystore cannot be written
    • createKeysAndCRL

      public static Object[] createKeysAndCRL(File ks, String ksPW, String alias, String cname, Set<String> altNames, String ou, int validDays, String keyAlg, int keySize, String keyPW) throws GeneralSecurityException, IOException
      New way - Native Java, does not call out to keytool. Create a keypair and store it in the keystore at ks, creating it if necessary.

      This returns the public key, private key, certificate, and CRL in an array. All of these are Java classes. Keys may be converted to I2P classes with SigUtil. The private key and selfsigned cert are stored in the keystore. The public key may be derived from the private key with KeyGenerator.getSigningPublicKey(SigningPrivateKey). The public key certificate may be stored separately with CertUtil.saveCert(Certificate, File) if desired. The CRL is not stored by this method, store it with CertUtil.saveCRL(X509CRL, File) or CertUtil.exportCRL(X509CRL, OutputStream) if desired.

      Throws on all errors. Warning, may take a long time.

      Parameters:
      ks - path to the keystore
      ksPW - the keystore password
      alias - the name of the key
      cname - e.g. localhost. Must be a hostname or email address. IP addresses will not be correctly encoded.
      altNames - the Subject Alternative Names. May be null. May contain hostnames and/or IP addresses. cname, localhost, 127.0.0.1, and ::1 will be automatically added.
      ou - the organizational unit of the certificate subject, e.g. console
      validDays - e.g. 3652 (10 years)
      keyAlg - e.g. DSA , RSA, EC
      keySize - e.g. 1024
      keyPW - the key password, must be at least 6 characters
      Returns:
      all you need: rv[0] is a Java PublicKey rv[1] is a Java PrivateKey rv[2] is a Java X509Certificate rv[3] is a Java X509CRL
      Throws:
      GeneralSecurityException - if the keyAlg and keySize pair is not supported, or the keypair, certificate, or CRL cannot be generated or stored
      IOException - if the directory holding the keystore cannot be created, or the keystore cannot be written
    • createKeysAndCRL

      public static Object[] createKeysAndCRL(File ks, String ksPW, String alias, String cname, String ou, int validDays, SigType type, String keyPW) throws GeneralSecurityException, IOException
      New way - Native Java, does not call out to keytool. Create a keypair and store it in the keystore at ks, creating it if necessary.

      This returns the public key, private key, certificate, and CRL in an array. All of these are Java classes. Keys may be converted to I2P classes with SigUtil. The private key and selfsigned cert are stored in the keystore. The public key may be derived from the private key with KeyGenerator.getSigningPublicKey(SigningPrivateKey). The public key certificate may be stored separately with CertUtil.saveCert(Certificate, File) if desired. The CRL is not stored by this method, store it with CertUtil.saveCRL(X509CRL, File) or CertUtil.exportCRL(X509CRL, OutputStream) if desired.

      Throws on all errors. Warning, may take a long time.

      Parameters:
      ks - path to the keystore
      ksPW - the keystore password
      alias - the name of the key
      cname - e.g. localhost. Must be a hostname or email address. IP addresses will not be correctly encoded.
      ou - the organizational unit of the certificate subject, e.g. console
      validDays - e.g. 3652 (10 years)
      type - the signature algorithm to generate the keypair for
      keyPW - the key password, must be at least 6 characters
      Returns:
      all you need: rv[0] is a Java PublicKey rv[1] is a Java PrivateKey rv[2] is a Java X509Certificate rv[3] is a Java X509CRL
      Throws:
      GeneralSecurityException - if the keystore cannot be created or opened, the password is wrong, or the key entry cannot be stored
      IOException - if the keystore cannot be read or written
    • createKeysAndCRL

      public static Object[] createKeysAndCRL(File ks, String ksPW, String alias, String cname, Set<String> altNames, String ou, int validDays, SigType type, String keyPW) throws GeneralSecurityException, IOException
      New way - Native Java, does not call out to keytool. Create a keypair and store it in the keystore at ks, creating it if necessary.

      This returns the public key, private key, certificate, and CRL in an array. All of these are Java classes. Keys may be converted to I2P classes with SigUtil. The private key and selfsigned cert are stored in the keystore. The public key may be derived from the private key with KeyGenerator.getSigningPublicKey(SigningPrivateKey). The public key certificate may be stored separately with CertUtil.saveCert(Certificate, File) if desired. The CRL is not stored by this method, store it with CertUtil.saveCRL(X509CRL, File) or CertUtil.exportCRL(X509CRL, OutputStream) if desired.

      Throws on all errors. Warning, may take a long time.

      Parameters:
      ks - path to the keystore
      ksPW - the keystore password
      alias - the name of the key
      cname - e.g. localhost. Must be a hostname or email address. IP addresses will not be correctly encoded.
      altNames - the Subject Alternative Names. May be null. May contain hostnames and/or IP addresses. cname, localhost, 127.0.0.1, and ::1 will be automatically added.
      ou - the organizational unit of the certificate subject, e.g. console
      validDays - e.g. 3652 (10 years)
      type - the signature algorithm to generate the keypair for
      keyPW - the key password, must be at least 6 characters
      Returns:
      all you need: rv[0] is a Java PublicKey rv[1] is a Java PrivateKey rv[2] is a Java X509Certificate rv[3] is a Java X509CRL
      Throws:
      GeneralSecurityException - if the keypair, certificate, or CRL cannot be generated, or the private key or certificate chain cannot be stored
      IOException - if the directory holding the keystore cannot be created, or the keystore cannot be written
    • buildEnv

      private static String[] buildEnv(String key1, String val1, String key2, String val2)
      Build a child-process environment array: the current process environment plus the two given entries.
      Parameters:
      key1 - name of the first extra environment variable
      val1 - value of the first extra environment variable
      key2 - name of the second extra environment variable
      val2 - value of the second extra environment variable
      Returns:
      an array of KEY=VALUE strings for ProcessBuilder, never null
    • createKeysCLI

      private static boolean createKeysCLI(File ks, String ksPW, String alias, String cname, String ou, int validDays, String keyAlg, int keySize, String keyPW)
      OLD way - keytool Create a keypair and store it in the keystore at ks, creating it if necessary.

      Warning, may take a long time.

      Parameters:
      ks - path to the keystore
      ksPW - the keystore password
      alias - the name of the key
      cname - e.g. randomstuff.console.i2p.net
      ou - the organizational unit of the certificate subject, e.g. console
      validDays - e.g. 3652 (10 years)
      keyAlg - e.g. DSA , RSA, EC
      keySize - e.g. 1024
      keyPW - the key password, must be at least 6 characters
      Returns:
      true if the key was generated and stored, false if it already exists or creation failed
    • getSigAlg

      private static String getSigAlg(int size, String keyalg)
      Picks the signature algorithm for a key.
      Parameters:
      size - the key size, in bits
      keyalg - the key algorithm name
      Returns:
      the signature algorithm to use
    • getPrivateKey

      public static PrivateKey getPrivateKey(File ks, String ksPW, String alias, String keyPW) throws GeneralSecurityException, IOException
      Get a private key out of a keystore.
      Parameters:
      ks - path to the keystore
      ksPW - the keystore password, may be null
      alias - the name of the key
      keyPW - the key password, must be at least 6 characters
      Returns:
      the key or null if not found
      Throws:
      GeneralSecurityException - if the keystore cannot be opened, the password is wrong, or the JCE provider rejects the keystore type
      IOException - if the keystore file cannot be read
    • exportPrivateKey

      public static void exportPrivateKey(File ks, String ksPW, String alias, String keyPW, OutputStream out) throws GeneralSecurityException, IOException
      Export the private key and certificate chain (if any) out of a keystore. Does NOT close the output stream. Throws on all errors.
      Parameters:
      ks - path to the keystore
      ksPW - the keystore password, may be null
      alias - the name of the key
      keyPW - the key password, must be at least 6 characters
      out - the stream to write the key and chain to; not closed by this method
      Throws:
      GeneralSecurityException - if the keystore cannot be opened, the password is wrong, or no private key is stored under the alias
      IOException - if the keystore file cannot be read or the output stream cannot be written
    • renewPrivateKeyCertificate

      public static X509Certificate renewPrivateKeyCertificate(File ks, String ksPW, String alias, String keyPW, int validDays) throws GeneralSecurityException, IOException
      Renew the the private key certificate in a keystore. Closes the input and output streams. Throws on all errors.
      Parameters:
      ks - path to the keystore
      ksPW - the keystore password, may be null
      alias - the name of the key, or null to get the first one in keystore
      keyPW - the key password, must be at least 6 characters
      validDays - new cert to expire this many days from now
      Returns:
      the new certificate
      Throws:
      GeneralSecurityException - if the keystore cannot be opened, the password is wrong, no private key is stored under the alias, the cert chain length is not 1, or the renewed certificate cannot be generated or stored
      IOException - if the keystore file cannot be read or written
    • importPrivateKey

      public static String importPrivateKey(File ks, String ksPW, String alias, String keyPW, InputStream in) throws GeneralSecurityException, IOException
      Import the private key and certificate chain to a keystore. Keystore will be created if it does not exist. Private key MUST be first in the stream. Closes the stream. Throws on all errors.
      Parameters:
      ks - path to the keystore
      ksPW - the keystore password, may be null
      alias - the name of the key. If null, will be taken from the Subject CN of the first certificate in the chain.
      keyPW - the key password, must be at least 6 characters
      in - the stream to read the key and chain from; closed by this method
      Returns:
      the alias as specified or extracted
      Throws:
      GeneralSecurityException - if the keystore cannot be created or opened, the password is wrong, alias is null and no certificate in the chain carries a Subject CN, or the JCE provider rejects the keystore type
      IOException - if the input stream cannot be read or the keystore cannot be written
    • storePrivateKey

      public static void storePrivateKey(File ks, String ksPW, String alias, String keyPW, PrivateKey pk, List<X509Certificate> certs) throws GeneralSecurityException, IOException
      Import the private key and certificate chain to a keystore. Keystore will be created if it does not exist. Private key MUST be first in the stream. Closes the stream. Throws on all errors.
      Parameters:
      ks - path to the keystore
      ksPW - the keystore password, may be null
      alias - the name of the key, non-null.
      keyPW - the key password, must be at least 6 characters
      pk - the private key to store
      certs - the certificate chain for the key, stored in the order given
      Throws:
      GeneralSecurityException - if the keystore cannot be created or opened, the password is wrong, or the key entry cannot be stored
      IOException - if the keystore cannot be written
    • getCert

      public static Certificate getCert(File ks, String ksPW, String alias) throws GeneralSecurityException, IOException
      Get a cert out of a keystore.
      Parameters:
      ks - path to the keystore
      ksPW - the keystore password, may be null
      alias - the name of the key
      Returns:
      the certificate or null if not found
      Throws:
      GeneralSecurityException - if the keystore cannot be opened, the password is wrong, or the JCE provider rejects the keystore type
      IOException - if the keystore file cannot be read
    • exportCert

      public static boolean exportCert(File ks, String ksPW, String alias, File certFile)
      Pull the cert back OUT of the keystore and save it in Base64-encoded X.509 format so the clients can get to it.
      Parameters:
      ks - path to the keystore
      ksPW - the keystore password, may be null
      alias - the name of the key
      certFile - the file to write the Base64-encoded certificate to
      Returns:
      true if the certificate was written, false if the alias was not found or the file could not be written
    • info

      private static void info(String msg)
      Prints an informational line for the tool.
      Parameters:
      msg - the text to print
    • warn

      private static void warn(String msg, Throwable t)
      Log a keystore warning.
      Parameters:
      msg - the warning message
      t - the related exception, or null if there is none
    • error

      private static void error(String msg, Throwable t)
      Prints an error line for the tool.
      Parameters:
      msg - the text to print
      t - the cause, null if none
    • log

      private static void log(I2PAppContext ctx, int level, String msg, Throwable t)
      Writes one entry to the router log.
      Parameters:
      ctx - the app context, null for the console only
      level - the log level
      msg - the text to log
      t - the cause, null if none
    • main

      public static void main(String[] args)
      Usage: KeyStoreUtil system (loads from system keystore)
      KeyStoreUtil foo.ks (loads from system keystore, and from foo.ks keystore if exists, else creates empty)
      KeyStoreUtil import file.ks file.key alias keypw (imports private key from file to keystore)
      KeyStoreUtil export file.ks alias keypw (exports private key from keystore)
      KeyStoreUtil keygen file.ks alias keypw (create keypair in keystore)
      KeyStoreUtil keygen2 file.ks alias keypw (create keypair using I2PProvider)
      
      Parameters:
      args - the command name followed by its arguments; an empty array prints the usage
    • usage

      private static void usage()
      Prints the command line usage text.
    • testImport

      private static void testImport(String[] args) throws Exception
      Runs the import test command.
      Parameters:
      args - the command line arguments
      Throws:
      Exception - if the import fails
    • testExport

      private static void testExport(String[] args) throws Exception
      Runs the export test command.
      Parameters:
      args - the command line arguments
      Throws:
      Exception - if the export fails
    • testKeygen

      private static void testKeygen(String[] args)
      Runs the key generation test command.
      Parameters:
      args - the command line arguments
    • testKeygen2

      private static void testKeygen2(String[] args) throws Exception
      Runs the second key generation test.
      Parameters:
      args - the command line arguments
      Throws:
      Exception - if the generation fails
    • listKeys

      private static void listKeys(String[] args)
      Lists the keys in the keystore.
      Parameters:
      args - the command line arguments