PKCS12, PEM ou DER : ce dont un client VPN a vraiment besoin
L’empaquetage décide si votre client importe l’identité, pas si elle est digne de confiance. Comparez PKCS12, PEM et DER, puis vérifiez.
Deux affirmations circulent dans les fils sur les certificats. La première est qu’un .p12 est l’option solide et un .pem l’option souple ; la seconde, qu’un fichier texte doit être sûr à envoyer parce qu’on peut le lire. Aucune ne survit une minute d’inspection.
PKCS12, PEM et DER décrivent comment les objets de certificat sont empaquetés et encodés. Ils ne décident ni qui est le pair, ni si l’émetteur est de confiance, ni si le fichier exige un mot de passe.
Ce que le client accepte est une question de compatibilité. Ce que le fichier contient est une question d’identité. Gardez les deux séparés et la plupart des erreurs d’import cessent d’être mystérieuses.
Trois conteneurs, un modèle d’objet
Partez de ce que vous avez réellement. Un certificat est une déclaration signée au sujet d’une clé publique. La clé privée est un matériau distinct qui prouve que vous contrôlez cette clé. Une chaîne est l’ensemble des émetteurs qui relient votre certificat à une racine à laquelle le client fait confiance. Les trois existent indépendamment de l’empaquetage.
Un fichier PKCS12, généralement .p12 ou .pfx, est un conteneur défini dans la RFC 7292 qui peut porter une clé privée, un ou plusieurs certificats et la chaîne dans un seul bloc protégé par mot de passe, avec un alias nommant l’identité. Un fichier PEM est un encadrement texte défini dans la RFC 7468 : un corps base64 entre les lignes BEGIN et END, et un fichier peut contenir plusieurs blocs à la suite. DER est l’encodage binaire des mêmes structures ASN.1, et le corps PEM est littéralement du DER enveloppé de base64.
Cette dernière phrase vaut la peine d’être retenue. Convertir PEM en DER réécrit l’enveloppe, pas le contenu, et la conversion inverse rend les octets d’origine.
| Container | Can hold | Does not decide |
|---|---|---|
| PKCS12 (.p12, .pfx) | Key, leaf certificate, chain, alias, password | Which root the client trusts |
| PEM (.pem, .crt, .cer) | Any number of base64 blocks | Whether the private key is present |
| DER (.der, .cer) | One binary structure | The object type, whatever the extension says |
Encoder n’est pas chiffrer
Base64 est un alphabet de transport. Il ne cache rien, et n’importe qui peut décoder un bloc PEM dans un shell. Un fichier DER est binaire et tout aussi public. Aucune des deux propriétés n’est une protection, et aucune n’implique qu’un mot de passe existe.
La vraie protection réside dans le matériau de clé. Un paquet PKCS12 peut chiffrer son contenu sous une clé dérivée d’un mot de passe. Une clé privée PEM peut être chiffrée avec un ancien bloc d’en-tête ou conservée dans PKCS#8 EncryptedPrivateKeyInfo. Un certificat seul ne contient rien de secret, c’est pourquoi une exportation qui n’a produit qu’un certificat laisse le client incapable de s’authentifier, quel que soit le format dans lequel vous l’enveloppez.
L’extension est un indice, pas un contrat. Les fichiers terminés par .cer et .crt apparaissent dans les deux encodages, et les équipements exportent des certificats DER sous des noms .pem assez souvent pour que deviner d’après le suffixe coûte un après-midi. Lisez plutôt les premiers octets : un fichier PEM s’ouvre sur une ligne BEGIN, tandis que DER commence par 0x30 parce que la structure externe est une SEQUENCE.
Pourquoi l’import échoue réellement
Les messages d’erreur du client compriment plusieurs problèmes différents en une phrase sur un certificat invalide, alors séparez-les par cause. Le plus courant est un décalage d’encodage : un client qui analyse du PEM renvoie une erreur d’analyse sur un fichier DER, et le correctif est une conversion, pas un nouveau certificat. Le deuxième est une clé manquante, où le certificat est correct et l’identité ne peut pas être prouvée. Le troisième est la chaîne, où un paquet sans son intermédiaire paraît correct dans la boîte d’import et échoue pendant la poignée de main.
Les paramètres de chiffrement en causent un quatrième, et il ressemble exactement à un mauvais mot de passe. Les anciens équipements exportaient des fichiers PKCS12 avec RC2-40 et 3DES, qu’OpenSSL 3 refuse sauf si le fournisseur legacy est chargé. Réexporter depuis l’équipement avec AES-256-CBC et PBKDF2 est la correction durable. Laisser des chiffrements anciens activés en permanence sur un poste client pour un seul fichier est un mauvais échange.
Le cinquième est l’ambiguïté. Un conteneur contenant deux clés et deux certificats, ou un fichier PEM avec trois blocs CERTIFICATE, force le client à choisir, et son choix est souvent simplement le premier élément. Quand un tunnel monte avec la mauvaise identité, c’est généralement la raison.
Inspectez avant de convertir
Lisez la structure sans imprimer de secrets. openssl pkcs12 -in bundle.p12 -info -noout rapporte les algorithmes de chiffrement et les alias tout en supprimant la sortie de clé et de certificat, et le manuel openssl-pkcs12 documente les options. Retirer -noout et ajouter -nodes sert à produire des fichiers que vous comptez conserver, pas à un coup d’œil rapide, car cela écrit la clé privée en clair.
Pour un certificat, openssl x509 -in cert.pem -noout -subject -issuer -dates répond à ce qu’une boîte d’import ne répondra pas, et ajouter -ext subjectAltName montre les noms pour lesquels le certificat est réellement valable. Si le fichier est DER, ajoutez -inform DER ; ce seul drapeau résout la plupart des erreurs unable-to-load.
Apparier une clé à un certificat est mécanique, et mérite d’être fait avant tout import :
openssl x509 -in cert.pem -noout -pubkey | openssl sha256openssl pkey -in key.pem -pubout | openssl sha256
Des empreintes identiques signifient que la paire va ensemble. Des empreintes différentes signifient que vous avez la mauvaise clé, et aucune conversion de format n’y changera rien.
Ce que le format ne change jamais
Les décisions de confiance se prennent au-dessus du conteneur. Le client remonte la chaîne jusqu’à une racine de son magasin, vérifie la fenêtre de validité, vérifie l’usage étendu de la clé pour l’authentification du client, et côté serveur vérifie que le nom qu’il a appelé figure dans le certificat. Aucune de ces étapes ne lit une extension de fichier.
Voilà pourquoi renommer un fichier jusqu’à ce qu’une erreur disparaisse est une façon si fiable de perdre du temps. L’import réussit, l’identité est toujours fausse, et la panne réapparaît pendant la poignée de main, où le message est moins utile. C’est aussi pourquoi un paquet exporté il y a deux ans s’importe proprement et est quand même rejeté : la date d’expiration voyageait dans le certificat, pas dans le nom du fichier.
Un ordre qui évite le retravail
Demandez à la documentation du client quels encodages il accepte et quel conteneur il attend pour une identité client, puis regardez ce qu’on vous a remis. Si le client veut une identité unique importable et que vous avez des fichiers PEM séparés, construisez le paquet une fois avec un mot de passe que vous contrôlez et gardez les sources. S’il veut du PEM, extrayez la clé et la chaîne, puis supprimez les fichiers intermédiaires via le processus de gestion des identifiants que votre équipe utilise déjà.
Après l’import, vérifiez l’identité plutôt que la boîte de dialogue : sujet, émetteur, expiration et le nom que le client présentera. Un nom convivial dans une liste est une étiquette, pas une identité vérifiée. Si le tunnel échoue ensuite, vous déboguez l’authentification ou le routage plutôt que l’empaquetage, ce qui est une conversation bien plus courte.