Two claims circulate in certificate threads. The first is that a .p12 is the strong option and a .pem is the loose one; the second is that a text file must be safe to send because you can read it. Neither survives a minute of inspection.

PKCS12, PEM and DER describe how certificate objects are packed and encoded. They do not decide who the peer is, whether the issuer is trusted, or whether the file needs a password.

What the client accepts is a compatibility question. What the file contains is an identity question. Keep those apart and most import errors stop being mysterious.

Three containers, one object model

Start with what you actually have. A certificate is a signed statement about a public key. The private key is separate material that proves you control that key. A chain is the set of issuers linking your certificate to a root the client trusts. All three exist regardless of packaging.

A PKCS12 file, usually .p12 or .pfx, is a container defined in RFC 7292 that can carry a private key, one or more certificates and the chain in a single password-protected blob, with an alias naming the identity. A PEM file is text framing defined in RFC 7468: a base64 body between BEGIN and END lines, and one file can hold several blocks in sequence. DER is the binary encoding of the same ASN.1 structures, and the PEM body is literally DER with base64 wrapped around it.

That last sentence is the one worth keeping. Converting PEM to DER rewrites the wrapping, not the content, and converting back returns the original 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

Encoding is not encryption

Base64 is a transport alphabet. It hides nothing, and anyone can decode a PEM block in a shell. A DER file is binary and equally public. Neither property is protection, and neither implies that a password exists.

Real protection lives in the key material. A PKCS12 bundle can encrypt its contents under a password-derived key. A PEM private key can be encrypted with a legacy header block or kept inside PKCS#8 EncryptedPrivateKeyInfo. A certificate on its own holds nothing secret, which is why an export that produced only a certificate leaves the client unable to authenticate no matter which format you wrap it in.

The extension is a hint, not a contract. Files ending .cer and .crt appear in both encodings, and appliances export DER certificates under .pem names often enough that guessing from the suffix wastes an afternoon. Read the first bytes instead: a PEM file opens with a BEGIN line, while DER starts with 0x30 because the outer structure is a SEQUENCE.

Why the import actually fails

Client error messages compress several different problems into one sentence about an invalid certificate, so separate them by cause. The most common is an encoding mismatch: a client that parses PEM returns a parse error on a DER file, and the fix is a conversion rather than a new certificate. The second is a missing key, where the certificate is fine and the identity cannot be proven. The third is the chain, where a bundle without its intermediate looks correct in the import dialog and fails during the handshake.

Encryption parameters cause a fourth, and it looks exactly like a wrong password. Older appliances exported PKCS12 files with RC2-40 and 3DES, which OpenSSL 3 refuses unless the legacy provider is loaded. Re-exporting from the appliance with AES-256-CBC and PBKDF2 is the durable fix. Leaving legacy ciphers enabled permanently on a client machine to accommodate one file is a bad trade.

A fifth is ambiguity. A container holding two keys and two certificates, or a PEM file with three CERTIFICATE blocks, forces the client to choose, and its choice is often simply the first item. When a tunnel comes up with the wrong identity, that is usually the reason.

Inspect before you convert

Read the structure without printing secrets. openssl pkcs12 -in bundle.p12 -info -noout reports the encryption algorithms and the aliases while suppressing key and certificate output, and the openssl-pkcs12 manual documents the flags. Dropping -noout and adding -nodes is for producing files you intend to store, not for a quick look, because it writes the private key in clear.

For a certificate, openssl x509 -in cert.pem -noout -subject -issuer -dates answers what an import dialog will not, and adding -ext subjectAltName shows the names the certificate is actually valid for. If the file is DER, add -inform DER; that single flag resolves most unable-to-load errors.

Matching a key to a certificate is mechanical, and worth doing before any import:

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

Identical digests mean the pair belongs together. Different digests mean you have the wrong key, and no amount of format conversion will change that.

What the format never changes

Trust decisions happen above the container. The client walks the chain to a root in its store, checks the validity window, checks extended key usage for client authentication, and on the server side checks that the name it dialled appears in the certificate. None of those steps reads a file extension.

That is why renaming a file until an error disappears is such a reliable way to lose time. The import succeeds, the identity is still wrong, and the failure reappears during the handshake where the message is less helpful. It is also why a bundle exported two years ago imports cleanly and is still rejected: the expiry date travelled inside the certificate, not in the file name.

An order that avoids rework

Ask the client's documentation which encodings it accepts and which container it expects for a client identity, then look at what you were handed. If the client wants a single importable identity and you have loose PEM files, build the bundle once with a password you control and keep the sources. If it wants PEM, extract the key and chain, and remove the intermediate files afterwards through whatever credential-handling process your team already uses.

After import, verify the identity rather than the dialog: subject, issuer, expiry, and the name the client will present. A friendly name in a list is a label, not a verified identity. If the tunnel then fails, you are debugging authentication or routing instead of packaging, which is a much shorter conversation.

Allakkat attuumassuteqartut