Convertir JKS en PKCS#12 – et inversement

Depuis Java 9, PKCS#12 est le format de keystore par défaut, et keytool incite à migrer à chaque accès à un fichier JKS. La conversion tient en une commande ; les pièges sont les mots de passe et les anciennes versions.

Pourquoi PKCS#12 ?

JKS est un format que seul Java comprend. PKCS#12 (extension .p12 ou .pfx) est un standard lu aussi par OpenSSL, Windows, les outils des serveurs web et les navigateurs. Depuis Java 9, keytool crée donc du PKCS#12 par défaut. Pour un fichier JKS, il affiche :

Warning: The JKS keystore uses a proprietary format. It is recommended to migrate
to PKCS12 which is an industry standard format using "keytool -importkeystore ..."

La commande

keytool -importkeystore \
  -srckeystore keystore.jks -srcstoretype JKS \
  -destkeystore keystore.p12 -deststoretype PKCS12

keytool demande le mot de passe de la source et le nouveau mot de passe. Toutes les entrées sont reprises : clés avec leur chaîne et certificats de confiance. Adapte ensuite le nom et le type dans l’application, par exemple dans Spring Boot :

server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-type=PKCS12

Le piège des mots de passe

En JKS, chaque clé peut avoir son propre mot de passe, différent de celui du keystore. keytool ne le permet pas en PKCS#12 : mot de passe de la clé et du magasin sont identiques. keytool affiche alors :

Warning: Different store and key passwords not supported for PKCS12 KeyStores.
Ignoring user-specified -destkeypass value.

Si la clé avait un autre mot de passe, indique-le avec -srckeypass. Au final, seul le mot de passe du magasin compte. Supprime dans l’application un réglage key-password séparé ou donne-lui la même valeur.

Revenir à JKS

Certaines anciennes applications ou appliances exigent JKS. Le retour se fait avec la même commande en inversant les types :

keytool -importkeystore \
  -srckeystore keystore.p12 -srcstoretype PKCS12 \
  -destkeystore keystore.jks -deststoretype JKS

PKCS#12 en PEM pour nginx ou Apache

Pour un serveur web ou un répartiteur de charge, il faut en général du PEM. Avec OpenSSL ou le convertisseur de certificats :

openssl pkcs12 -in keystore.p12 -clcerts -nokeys -out server.crt
openssl pkcs12 -in keystore.p12 -cacerts -nokeys -out chain.crt
openssl pkcs12 -in keystore.p12 -nocerts -nodes -out server.key

Anciennes versions de Java et OpenSSL 3

Le chiffrement interne de PKCS#12 a changé. Java 12 et plus (ainsi que Java 8u301 et 11.0.12) écrivent le PKCS#12 en AES-256 et SHA-256. Les versions plus anciennes utilisaient RC2 et 3DES. D’où deux problèmes :

L’assistant keystore Java lit les deux variantes et te laisse choisir « moderne » (AES-256) ou « compatible » (3DES) à l’enregistrement.

FAQ

Est-ce que je perds quelque chose à la conversion ?

Clés, chaînes et certificats de confiance sont repris. Seuls les mots de passe différents par clé disparaissent, car PKCS#12 utilise un mot de passe unique en Java.

Puis-je simplement renommer le .p12 en .pfx ?

Oui. C’est le même format ; Windows attend en général l’extension .pfx.

Et JCEKS ?

JCEKS peut aussi stocker des clés symétriques. keytool les transfère aussi en PKCS#12 si tu indiques -srcstoretype JCEKS.

Faut-il aussi convertir les truststores ?

Pas obligatoirement, Java lit toujours JKS. Le cacerts du JDK est lui-même en PKCS#12 depuis Java 9, mais il est lu quel que soit son type.