In certificaatdiscussies gaan twee beweringen rond. De eerste is dat een .p12 de sterke optie is en een .pem de losse; de tweede dat een tekstbestand veilig te versturen moet zijn omdat je het kunt lezen. Geen van beide doorstaat een minuut inspectie.

PKCS12, PEM en DER beschrijven hoe certificaatobjecten worden verpakt en gecodeerd. Ze bepalen niet wie de tegenpartij is, of de uitgever vertrouwd is, of het bestand een wachtwoord nodig heeft.

Wat de client accepteert is een compatibiliteitsvraag. Wat het bestand bevat is een identiteitsvraag. Houd die twee gescheiden en de meeste importfouten zijn niet langer raadselachtig.

Drie containers, één objectmodel

Begin met wat je echt hebt. Een certificaat is een ondertekende verklaring over een publieke sleutel. De privésleutel is apart materiaal dat bewijst dat je die sleutel beheert. Een keten is de verzameling uitgevers die je certificaat verbindt met een root die de client vertrouwt. Alle drie bestaan ongeacht de verpakking.

Een PKCS12-bestand, meestal .p12 of .pfx, is een container volgens RFC 7292 die een privésleutel, een of meer certificaten en de keten in één met een wachtwoord beschermd blok kan dragen, met een alias die de identiteit benoemt. Een PEM-bestand is tekstomlijning volgens RFC 7468: een base64-body tussen BEGIN- en END-regels, en één bestand kan meerdere blokken achter elkaar bevatten. DER is de binaire codering van dezelfde ASN.1-structuren, en de PEM-body is letterlijk DER met base64 eromheen.

Die laatste zin is het onthouden waard. PEM naar DER omzetten herschrijft de omlijning, niet de inhoud, en terugomzetten geeft de oorspronkelijke bytes.

ContainerCan holdDoes not decide
PKCS12 (.p12, .pfx)Key, leaf certificate, chain, alias, passwordWhich root the client trusts
PEM (.pem, .crt, .cer)Any number of base64 blocksWhether the private key is present
DER (.der, .cer)One binary structureThe object type, whatever the extension says

Coderen is geen versleuteling

base64 is een transportalfabet. Het verbergt niets, en iedereen kan een PEM-blok in een shell decoderen. Een DER-bestand is binair en even openbaar. Geen van beide eigenschappen is bescherming, en geen van beide impliceert dat er een wachtwoord is.

Echte bescherming zit in het sleutelmateriaal. Een PKCS12-bundel kan de inhoud versleutelen met een uit een wachtwoord afgeleide sleutel. Een privé-PEM-sleutel kan met een oude kopblok worden versleuteld of in PKCS#8 EncryptedPrivateKeyInfo worden bewaard. Een certificaat alleen bevat niets geheims, daarom laat een export die alleen een certificaat opleverde de client niet kunnen authenticeren, in welk formaat je het ook wikkelt.

De extensie is een hint, geen contract. Bestanden die eindigen op .cer en .crt komen in beide coderingen voor, en apparaten exporteren DER-certificaten vaak genoeg onder .pem-namen dat gissen op de suffix een middag kost. Lees in plaats daarvan de eerste bytes: een PEM-bestand opent met een BEGIN-regel, terwijl DER begint met 0x30 omdat de buitenste structuur een SEQUENCE is.

Waarom de import werkelijk mislukt

Foutmeldingen van de client persen verschillende problemen in één zin over een ongeldig certificaat, dus scheid ze naar oorzaak. Het meest voorkomend is een coderingsverschil: een client die PEM parseert, geeft een parsefout op een DER-bestand, en de oplossing is een conversie, geen nieuw certificaat. Het tweede is een ontbrekende sleutel, waarbij het certificaat in orde is en de identiteit niet kan worden bewezen. Het derde is de keten, waarbij een bundel zonder het tussenliggende certificaat er in de importdialoog correct uitziet en tijdens de handshake faalt.

Versleutelingsparameters veroorzaken een vierde, en die ziet er precies als een verkeerd wachtwoord uit. Oudere apparaten exporteerden PKCS12-bestanden met RC2-40 en 3DES, die OpenSSL 3 weigert tenzij de legacy-provider is geladen. Opnieuw exporteren vanaf het apparaat met AES-256-CBC en PBKDF2 is de duurzame oplossing. Oude cijfers permanent aan laten staan op een clientmachine voor één bestand is een slechte ruil.

De vijfde is dubbelzinnigheid. Een container met twee sleutels en twee certificaten, of een PEM-bestand met drie CERTIFICATE-blokken, dwingt de client te kiezen, en zijn keuze is vaak simpelweg het eerste item. Wanneer een tunnel opkomt met de verkeerde identiteit, is dat meestal de reden.

Inspecteer voordat je converteert

Lees de structuur zonder geheimen af te drukken. openssl pkcs12 -in bundle.p12 -info -noout rapporteert de versleutelingsalgoritmen en de aliassen en onderdrukt sleutel- en certificaatsuitvoer, en de openssl-pkcs12-handleiding documenteert de vlaggen. -noout weglaten en -nodes toevoegen is voor bestanden die je wilt bewaren, niet voor een snelle blik, omdat het de privésleutel in klare tekst schrijft.

Voor een certificaat beantwoordt openssl x509 -in cert.pem -noout -subject -issuer -dates wat een importdialoog niet zal beantwoorden, en met -ext subjectAltName erbij toont het de namen waarvoor het certificaat werkelijk geldig is. Is het bestand DER, voeg -inform DER toe; die ene vlag lost de meeste unable-to-load-fouten op.

Een sleutel aan een certificaat koppelen is mechanisch, en de moeite waard vóór elke import:

openssl x509 -in cert.pem -noout -pubkey | openssl sha256
openssl pkey -in key.pem -pubout | openssl sha256

Identieke digests betekenen dat het paar bij elkaar hoort. Verschillende digests betekenen dat je de verkeerde sleutel hebt, en geen enkele formaatconversie verandert dat.

Wat het formaat nooit verandert

Vertrouwensbeslissingen vinden boven de container plaats. De client loopt de keten naar een root in zijn opslag, controleert het geldigheidsvenster, controleert uitgebreid sleutelgebruik voor clientauthenticatie, en controleert aan de serverkant of de naam die hij belde in het certificaat voorkomt. Geen van die stappen leest een bestandsextensie.

Daarom is een bestand hernoemen tot een fout verdwijnt zo'n betrouwbare manier om tijd te verliezen. De import slaagt, de identiteit is nog steeds fout, en de fout komt terug tijdens de handshake waar de melding minder behulpzaam is. Daarom wordt een bundel die twee jaar geleden is geëxporteerd schoon geïmporteerd en toch geweigerd: de vervaldatum reisde in het certificaat, niet in de bestandsnaam.

Een volgorde die herbouw voorkomt

Vraag de documentatie van de client welke coderingen hij accepteert en welke container hij voor een clientidentiteit verwacht, en kijk dan naar wat je is gegeven. Wil de client één importeerbare identiteit en heb je losse PEM-bestanden, bouw de bundel dan één keer met een wachtwoord dat je beheert en bewaar de bronnen. Wil hij PEM, haal dan de sleutel en de keten eruit, en verwijder daarna de tussenbestanden via het proces voor het omgaan met inloggegevens dat je team al gebruikt.

Controleer na de import de identiteit in plaats van de dialoog: subject, uitgever, vervaldatum en de naam die de client zal presenteren. Een vriendelijke naam in een lijst is een label, geen geverifieerde identiteit. Faalt de tunnel daarna, dan debug je authenticatie of routering in plaats van verpakking, wat een veel korter gesprek is.

Gerelateerde artikelen