Base64 Encode a Certificate: PEM vs DER, and How to Tell Which You Have

"Base64 encoded certificate" means three different things depending on who asks. Windows calls a PEM file "Base-64 encoded X.509". Some APIs want only the Base64 body without the BEGIN and END lines. Kubernetes, Helm charts and many MDM consoles want the entire PEM file, headers included, encoded once more. All three start from the same binary DER certificate, so once you can tell them apart the conversion is a one-line command.

DER and Base64: the same certificate in two forms

An X.509 certificate is a binary structure encoded with ASN.1 DER. That binary file is what Windows calls "DER encoded binary X.509 (.CER)". Binary is awkward to paste into an email or a configuration field, so the same bytes are usually Base64-encoded and wrapped in labels. That text form is PEM, defined in RFC 7468:

-----BEGIN CERTIFICATE-----
MIIBhDCCASmgAwIBAgIUbYyaO2x6gHKQvs2V3gjpF9Jk9OwwCgYIKoZIzj0EAwIw
FzEVMBMGA1UEAwwMZXhhbXBsZS50ZXN0MB4XDTI2MTAxOTE1NTk...
-----END CERTIFICATE-----

The lines between the labels are exactly the Base64 of the DER file, broken into 64-character lines. Nothing else is added: no compression, no encryption. So the answer to "are Base64 and PEM certificates interchangeable?" is yes in content, and only the wrapping differs. "Base-64 encoded X.509 (.CER)" in the Windows export wizard produces a PEM file, even though the extension is .cer.

File extensions do not tell you the encoding. A .cer or .crt file can be either DER or PEM, and .pem almost always means text. Look at the content, not the name.

How to tell if a certificate is Base64 encoded

Open the file in a text editor or print its first bytes. There are four cases, and each has an unmistakable start:

-----BEGIN CERTIFICATE-----     PEM: Base64 DER with labels
MIIB… / MIIC… / MIID…           bare Base64 DER, labels removed
LS0tLS1CRUdJTi…                 Base64 of a whole PEM file ("-----BEGIN" encoded)
30 82 01 84 30 82 …  (binary)   DER: unreadable bytes, starts with 0x30 0x82

The MII prefix is not a coincidence. A DER certificate begins with the ASN.1 SEQUENCE tag 0x30 followed by 0x82 and a two-byte length, and those first bytes encode to MII in Base64 whenever the certificate body is between 256 bytes and 16 KB, which covers virtually every real certificate. LS0tLS1 is the Base64 of -----, so it means somebody encoded the PEM text again.

To check from the command line, ask OpenSSL to parse it. If the PEM read succeeds, the file is Base64 (PEM); if only the DER read succeeds, it is binary:

openssl x509 -in cert.cer -noout -subject                # PEM
openssl x509 -inform der -in cert.cer -noout -subject    # DER
# Windows: certutil -dump cert.cer shows the certificate in either form

OpenSSL 3 usually detects DER on its own, but scripts that must also run on OpenSSL 1.1 should pass -inform der explicitly.

Base64 encode a certificate with OpenSSL

Converting DER to PEM is the most common request, and it is exactly the same as Base64 encoding with labels:

# DER -> PEM (Base64 with BEGIN/END lines)
openssl x509 -inform der -in cert.der -out cert.pem

# PEM -> DER
openssl x509 -in cert.pem -outform der -out cert.der

# bare Base64 of the DER bytes, one line, no labels
openssl base64 -A -in cert.der

openssl base64 wraps output at 64 characters, matching PEM, unless you add -A for a single line. A converted file is byte-for-byte reversible: DER to PEM and back gives the identical DER file, which makes a good self-check before you upload anything.

macOS Terminal, Linux and Windows without OpenSSL

If a form asks for "the certificate in Base64" and rejects a PEM file, it usually wants the bare body on one line. You can produce it with the system base64 tool or by stripping the labels from an existing PEM:

# Linux (GNU coreutils): -w0 disables line wrapping
base64 -w0 cert.der

# macOS: output is not wrapped by default
base64 -i cert.der

# from an existing PEM: drop the labels and join the lines
grep -v -- '-----' cert.pem | tr -d '\n'

# Windows: wraps DER in BEGIN/END CERTIFICATE lines (PEM)
certutil -encode cert.der cert.pem

On macOS, a PEM exported from Keychain Access already is the Base64 form; only use base64 on the .cer file if it is DER. Encoding a PEM file again is the most common mistake, and it gives the LS0tLS1 string described above.

When a tool wants the whole PEM file encoded

Some systems do want that double encoding, on purpose. A Kubernetes Secret stores every value Base64-encoded, so tls.crt holds the Base64 of the complete PEM text, labels and all. Helm values, Terraform variables and several device-management (MDM) consoles follow the same convention because they carry the certificate inside JSON or YAML:

# value for a Kubernetes Secret 'data:' field or a Helm value
base64 -w0 cert.pem          # Linux
base64 -i cert.pem           # macOS

# or let kubectl do the encoding for you
kubectl create secret tls web-tls --cert=cert.pem --key=key.pem

If the documentation asks for "certificate and key in Base64", read the example value. One starting with LS0tLS1 expects the encoded PEM file; one starting with MII expects the bare DER body. For a key, a bare body starts with MII too but the PEM label says PRIVATE KEY, so do not mix the two up when pasting.

PFX and PKCS#12 bundles

A .pfx or .p12 file contains a certificate, its chain and usually the private key, all in one binary container protected by a password. Services such as Azure Key Vault and many CI secret stores accept it as a single Base64 string:

# bundle PEM certificate and key into PKCS#12, then encode it
openssl pkcs12 -export -in cert.pem -inkey key.pem -out bundle.pfx
base64 -w0 bundle.pfx > bundle.pfx.b64

# decode it back
base64 -d bundle.pfx.b64 > bundle.pfx

The Base64 of a PKCS#12 file also starts with MII, because it is also a DER SEQUENCE. Do not rely on the prefix alone here: try to open it with openssl pkcs12 -in bundle.pfx -info -noout to be sure what you have. And treat that string as the private key itself; anyone who has it and the password can impersonate the server.

Common mistakes

Windows line endings. A PEM edited on Windows can carry \r\n; most parsers accept it, but some strict Base64 decoders do not, and the error message rarely says so. Strip \r before encoding a PEM file.

Missing chain. A server certificate alone is often not enough; the client also needs the intermediate certificates. In PEM you simply concatenate the blocks, leaf first.

Changing the value while inspecting it. Paste certificates into an offline tool, such as the Base64 encoder and decoder that runs in your browser, rather than a site that uploads them. A certificate is public, but the bundle next to it often is not.

Sources and further reading

RFC 7468 defines the PEM textual encoding, the labels and the 64-character lines. RFC 5280 defines the X.509 certificate structure, and ITU-T X.690 the DER encoding rules behind the 0x30 0x82 prefix. RFC 4648 specifies Base64. RFC 7292 defines PKCS#12. The OpenSSL x509, base64 and pkcs12 manual pages, Microsoft's certutil documentation and the Kubernetes documentation on TLS Secrets cover the commands shown here.

Frequently asked questions

How do I tell if a certificate is Base64 encoded?

Open it in a text editor. A Base64 (PEM) certificate is readable text starting with -----BEGIN CERTIFICATE-----, or with MII if the labels were removed. A DER certificate is binary and looks like random bytes.

What is the difference between DER and Base64 encoded certificates?

None in content. DER is the binary encoding of the certificate, and the Base64 (PEM) form is those same bytes encoded as text with BEGIN and END lines. Converting between them is lossless.

Are PEM and Base64 certificates the same?

Practically, yes. PEM is Base64-encoded DER with header and footer lines and 64-character line breaks. Some tools want the bare Base64 without the lines, which you get by removing them and joining the rest.

How do I Base64 encode a certificate with OpenSSL?

Use openssl x509 -inform der -in cert.der -out cert.pem for PEM, or openssl base64 -A -in cert.der for a single-line Base64 string without labels.

Why does my Base64 certificate start with LS0tLS1?

That is the Base64 of the text -----BEGIN, so the whole PEM file was encoded again. Kubernetes Secrets and Helm values expect exactly that; most other APIs do not and need the original PEM or DER.

Which option should I choose in the Windows certificate export wizard?

Choose Base-64 encoded X.509 (.CER) for anything that expects PEM text, such as Linux servers, nginx or a web form. Choose DER encoded binary X.509 (.CER) only if the receiving system explicitly asks for binary DER.