A pkcs12 keystore is commonly used for both S/MIME User Certificates and SSL/TLS Server Certificates. They keystore may contain both private keys and their corresponding certificates with or without a complete chain. The keystore’s purpose is to store the credential of an identity, being a person, client, or server. The file extension can be either .p12 or .pfx.
RFC 7292 goes into much much much more detail: https://tools.ietf.org/html/rfc7292
Unfortunately, there is not 100% coverage in all commands for maintaining PKCS #12 keystores in either OpenSSL or the Java Keytool so you must use both.
How do I create a keystore with a self-signed certificate using the java keytool?
Using the Java Keytool, run the following command to create the keystore with a self-signed certificate:
keytool -genkey -alias somealias -keystore keystore.p12 -storetype PKCS12 -keyalg RSA -storepass somepass -validity 730 -keysize 4096
How do I create a PKCS12 keystore from an existing private key and certificate using openssl?
To create the keystore from an existing private key and certificate, run the following command:
openssl pkcs12 -export -in certificate.pem -inkey key.pem -out keystore.p12
Where pkcs12
is the openssl pkcs12 utility, -export
means to export to a file, -in certificate.pem
is the certificate and -inkey key.pem
is the key to be imported into the keystore. -out keystore.p12
is the keystore file.
How do I convert a JKS keystore to PKCS12?
To convert a Java Keystore to a PKCS #12 Keystore (.jks to .p12), run the following command:
keytool -importkeystore -srckeystore keystore.jks -destkeystore keystore.p12
-srcstoretype JKS -deststoretype PKCS12 -deststorepass password
-srcalias alias -destalias alias
How do I convert a PKCS12 keystore to JKS?
To convert a PKCS12 keystore to JKS, run the following command:
keytool -importkeystore -srckeystore example.p12 -srcstoretype PKCS12 -destkeystore example.jks -deststoretype JKS
Read more about using java keytool to import a keystore into another keystore.
To change the password of a PKCS #12 keystore (make sure to also change the password of the key, if not, the keystore will be corrupt), run the following:
keytool -storepasswd -keystore keystore.p12
keytool -keypasswd -alias alias -keystore keystore.p12
To change the alias, run the following (the default alias is 1):
keytool -changealias -keystore keystore.p12 -alias alias
To list the contents of the PKCS #12 keystore:
keytool -list -v -keystore keystore.p12
How do I extract a private key from a keystore using openssl?
To extract the private key:
openssl pkcs12 -in keystore.p12 -nocerts -nodes
How do I extract certificates from a keystore using openssl?
To extract a certificate or certificate chain from a PKCS12 keystore using openssl, run the following command:
openssl pkcs12 -in example.p12 -nokeys
Where -in example.p12
is the keystore and -nokeys
means only extract the certificates and not the keys.
How do I update the trust chain in an existing keystore for a specific keystore entry?
You may find it useful or necessary to update a trust chain to an existing keystore entry. For example, in the event of an expiring trust chain due to a cross signed root or intermediate, you may have an expiring chain installed and need to replace it (like with the AddTrust root expiration). To update the trust chain for a given alias in a pkcs12 keystore, run the following command:
keytool -import -trustcacerts -alias alias_to_be_updated -file chain.pem -keystore keystore.p12
Where -trustcacerts
means the trust chain is being added to the existing entry, -alias alias_to_be_updated
is the entry being updated, -file chain.pem
is the complete certificate chain including the root, and -keystore keystore.p12
is the keystore being updated.
If you encounter Error: “java.lang.exception: failed to establish chain from reply” it is likely you have not included the correct chain or the complete chain, including the root. Also, check the formatting of the chain as it is easy to miss a character in the header and/or footer of each certificate in the chain.
Keystore Exceptions – PKCS12, JKS, or any type
When operating on a keystore, you will likely enter invalid input or find your keystore in a confusing state at some point. Here are some common exceptions you may see.
When listing a keystore (and likely other operations), you may encounter this error:
keytool error: java.security.KeyStoreException: This keystore does not support probing and must be loaded with a specified type
keytool error: java.security.KeyStoreException: This keystore does not support probing and must be loaded with a specified type
java.security.KeyStoreException: This keystore does not support probing and must be loaded with a specified type
at java.base/java.security.KeyStore.getInstance(KeyStore.java:1816)
at java.base/java.security.KeyStore.getInstance(KeyStore.java:1687)
at java.base/sun.security.tools.keytool.Main.doCommands(Main.java:924)
at java.base/sun.security.tools.keytool.Main.run(Main.java:409)
at java.base/sun.security.tools.keytool.Main.main(Main.java:402)
To move past this error, simply specify the keystore type with -storetype PKCS12 (or the store type of your keystore) in your command.
Create PKCS12 keystore with Java
Here’s some Java code to programmatically create the Keystore. For the complete example, review the GitHub project at https://github.com/misterpki/generate-keystore
public static KeyStore generatePKCS12KeyStore(final String password)
throws KeyStoreException, NoSuchAlgorithmException, IOException, CertificateException, OperatorCreationException
{
final KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null, password.toCharArray());
// Create Symmetric key entry
final KeyGenerator aesGenerator = KeyGenerator.getInstance("AES");
aesGenerator.init(128);
final KeyStore.SecretKeyEntry aesSecretKey = new KeyStore.SecretKeyEntry(aesGenerator.generateKey());
final KeyStore.ProtectionParameter aesSecretKeyPassword =
new KeyStore.PasswordProtection(password.toCharArray());
// Add symmetric key to keystore
keyStore.setEntry("symm-key", aesSecretKey, aesSecretKeyPassword);
// Create Asymmetric key pair
final KeyPair asymmetricKeys = KeyPairGenerator.getInstance("RSA").generateKeyPair();
final KeyStore.PrivateKeyEntry privateKey =
new KeyStore.PrivateKeyEntry(
asymmetricKeys.getPrivate(),
new X509Certificate[]{generateX509Certificate(asymmetricKeys)});
final KeyStore.ProtectionParameter privateKeyPassword =
new KeyStore.PasswordProtection(password.toCharArray());
// Add asymmetric key to keystore
keyStore.setEntry("asymm-key", privateKey, privateKeyPassword);
return keyStore;
}
Another example (not recommended) but for general demonstration.
package com.misterpki;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import sun.security.tools.keytool.CertAndKeyGen;
import sun.security.x509.X500Name;
public class Main {
public static void main(String[] args) throws Exception {
try (final FileOutputStream stream = new FileOutputStream("keyStore.p12")) {
generatePKCS12().store(stream, "changeit".toCharArray());
}
}
private static KeyStore generatePKCS12() throws NoSuchProviderException,
NoSuchAlgorithmException,
KeyStoreException,
InvalidKeyException,
IOException,
CertificateException,
SignatureException
{
final KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(null, new char[0]);
final CertAndKeyGen certGenerator = new CertAndKeyGen("RSA", "SHA256WithRSA", null);
certGenerator.generate(4096);
//validity of 1 year
final long validSecs = (long) 365 * 24 * 60 * 60;
final X509Certificate certificate = certGenerator.getSelfCertificate(
new X500Name("CN=some_name,O=some_org,L=some_city,C=some_country"), validSecs);
keyStore.setKeyEntry("alias",
certGenerator.getPrivateKey(),
"changeit".toCharArray(),
new X509Certificate[]{certificate});
return keyStore;
}
}
Please comment and provide suggestions for additional pkcs12 openssl and java keytool commands that may be helpful so that we may provide as valuable content as possible.
Leave a Reply