SSH Keys and PEM Certificates in Base64

SSH keys, TLS certificates, and PEM files wrap raw binary keys in Base64 between header and footer markers. Learn the format, how to decode keys, and common CI/CD patterns.

ZERO UPLOAD · ALL LOCAL
  1. Select DECODE (default) to paste Base64 and get the original text, or switch to ENCODE to convert text to Base64.
  2. For text: type or paste into the text area — the result appears instantly.
  3. For files: drop a file onto the drop zone or click it to browse — any file up to 500 MB works.
  4. Use Copy to grab the output, or Download as .txt to save long Base64 strings.
  5. Note: Base64 is encoding, not encryption. Anyone can decode it with no key.

What to look for

  • 64 characters per line (not MIME's 76)
  • roughly 1,700 bytes of Base64 across about 27 lines
  • exactly 5 hyphens on each side

A PEM wrapped at 76 characters instead of 64 fails OpenSSL parsing with a generic error, not a message pointing at the line width.

INPUT
FILE INPUT

Drop a file here

or click to select a file · any format · max 500 MB

OUTPUT

SSH Keys and PEM Certificates in Base64

SSH keys and TLS certificates travel safely because PEM gives binary data a text envelope.

Every SSH private key and TLS certificate you use is a Base64-wrapped binary structure. The PEM format (Privacy Enhanced Mail) dates from 1993 and uses Base64 to make binary ASN.1 structures transmissible through text channels , email, YAML, environment variables, and config files.1

Between the BEGIN marker and END marker markers sits standard Base64 with 64-character line wrapping. Strip the headers, join the lines, and decode the result to access the raw DER-encoded binary.

How PEM format works

PEM encodes binary key or certificate structures using MIME-compatible Base64 wrapped at a specific line width that differs from the MIME standard of 76 characters. The structure is: a header line (such as BEGIN CERTIFICATE), one or more lines of 64-character Base64, and a footer (such as END CERTIFICATE).1

Matching PEM wrapping to parser expectations

The Base64 uses the standard alphabet (+ and /) with = padding, wrapped at exactly 64 characters per line with LF or CRLF line endings, which is shorter than the 76-character MIME wrapping used for email attachments.2 Consequently, a 2,048-bit RSA private key produces roughly 1,700 bytes of Base64 wrapped across about 27 lines. Building on this, OpenSSH keys (the modern BEGIN OPENSSH PRIVATE KEY marker format) use the same Base64 wrapping but encode a custom OpenSSH binary structure instead of ASN.1. The 64-character line length originates from PEM's roots in email transport, where SMTP line-length limits made shorter lines necessary. Despite the format dating from 1993, the 64-character convention persists because changing it would break compatibility with the vast installed base of OpenSSL and TLS tooling that expects exactly this wrapping width.

This matters because a single over-long line is enough to break a load that works everywhere else. A 76-character PEM that one tool emits will fail an OpenSSL handshake with a generic error, so when a certificate loads in one place and not another, the line width is the first thing to check.

Common pitfalls and variants

PEM line length is 64 characters, not 76 , do not confuse it with MIME Base64's 76-character wrapping.2 Some tools produce 76-character-wrapped PEM files that most TLS libraries reject with an 'invalid PEM format' error. Furthermore, copying PEM keys through terminals, Slack, or email clients often introduces extra whitespace, replaces hyphens with en-dashes, or wraps long lines. Verify that the BEGIN marker and END marker markers use exactly 5 hyphens on each side and that no line contains trailing spaces. A single extra character breaks OpenSSL parsing silently. When converting between PEM and other formats, OpenSSH's ssh-keygen utility can re-wrap keys to the correct line width, and the fold -w 64 command on Linux forces any Base64 string into 64-character lines suitable for PEM encapsulation.

Security and best practice

PEM files containing private keys must never appear in source control, application logs, or API responses. Use .gitignore patterns for *.pem, *.key, and id_rsa. For CI/CD pipelines, store the Base64-encoded PEM in a CI secret variable and decode it at build time: echo $SSH_KEY_B64 | base64 -d > /tmp/id_rsa && chmod 600 /tmp/id_rsa. Furthermore, PKCS#8 (private key in PEM) and PKCS#12 (combined cert+key bundle) require a passphrase for encrypted storage , always use encrypted private keys in production and store the passphrase in a secrets manager, not alongside the key file.3

Keeping private keys out of shared surfaces

Never paste private keys into public issue trackers, chat histories, or build logs while debugging a PEM import error. Use a redacted certificate or a disposable test key when asking for help, then rotate any key that may have been exposed. If a private key does leak, the incident response should include revoking the corresponding certificate, generating a new key pair, and auditing all systems that trusted the compromised certificate, because a leaked private key allows an attacker to impersonate your server or decrypt traffic in transit.

Inspecting and validating PEM files

Inspecting a PEM file with openssl x509 -in cert.pem -text -noout displays the certificate's subject, issuer, validity dates, and public key details without requiring you to decode the Base64 manually.4 For private keys, openssl rsa -in key.pem -check validates the key structure and confirms it is internally consistent. For SSH keys in OpenSSH format, ssh-keygen -y -f id_rsa prints the corresponding public key: a successful output confirms the private key is valid and readable by the SSH toolchain.

Checking PEM line lengths after copying

After copying a PEM file through a terminal, email, or a chat tool, verify that line widths are exactly 64 characters (PEM standard) rather than 76 (MIME standard) by running awk 'length > 64 { print NR": "length" chars" }' cert.pem. Any line exceeding 64 characters indicates a misformatted PEM or a copy-paste line-wrap issue. OpenSSL rejects certificates with incorrect line lengths during TLS handshakes with a generic error that is difficult to trace without this check.

CI/CD SSH key injection patterns

For CI/CD pipelines, the recommended pattern for SSH key injection stores the Base64-encoded key as a CI secret, decodes it to a temporary path in the job step, sets correct permissions, and removes the file after use. A complete GitHub Actions step: echo "${{ secrets.SSH_KEY_B64 }}" | base64 -d > /tmp/id_rsa && chmod 600 /tmp/id_rsa && trap "rm -f /tmp/id_rsa" EXIT. The trap command ensures the key file is removed even when the subsequent step fails.

In GitLab CI, passing the key directly to ssh-add via stdin keeps it only in the SSH agent's memory and never writes it to disk: echo "$SSH_KEY_B64" | base64 -d | ssh-add -. Combining ssh-add - with SSH_AUTH_SOCK environment variable configuration allows subsequent steps to clone and push to Git repositories without accessing the key file again, avoiding the window of vulnerability between writing the key to disk and deleting it after use.5

When to use this

Use PEM (Base64-wrapped) format for TLS certificates, SSH keys, and CSRs when your tooling (OpenSSL, nginx, curl, ssh) expects PEM. Decode the Base64 to DER format when working with languages or libraries that require raw binary keys. For a quick check on a suspect PEM block, strip the header and footer markers and confirm the remaining text produces the DER bytes you expect before trusting the certificate.

Examples

Extract the raw bytes from a PEM certificate

Before
BEGIN CERTIFICATE marker
MIIBIjANBgkqhkiG...
END CERTIFICATE marker
After
# Strip headers and decode in bash:
openssl x509 -in cert.pem -outform DER -out cert.der
# Or manually:
grep -v 'BEGIN\|END' cert.pem | tr -d '\n' | base64 -d > cert.der

openssl is the preferred method , it handles encoding quirks that manual base64 -d may not.

Store an SSH key in a CI/CD environment variable

Before
# id_rsa stored as file on build agent
After
# Encode (single line, no wrapping):
export SSH_KEY_B64=$(base64 -w 0 ~/.ssh/id_rsa)
# In CI script, decode and use:
echo $SSH_KEY_B64 | base64 -d > /tmp/id_rsa
chmod 600 /tmp/id_rsa
GIT_SSH_COMMAND='ssh -i /tmp/id_rsa' git clone [email protected]:org/repo.git

Clean up /tmp/id_rsa after use with rm -f /tmp/id_rsa.

Sources
  1. 1.

    J. Linn, "Privacy Enhancement for Internet Electronic Mail: Part I: Message Encryption and Authentication Procedures," RFC 1421, IETF, February 1993. https://rfc-editor.org/rfc/rfc1421.html

  2. 2.

    S. Josefsson and S. Leonard, "Textual Encodings of PKIX, PKCS, and CMS Structures," RFC 7468, IETF, February 2015. https://rfc-editor.org/rfc/rfc7468.html

  3. 3.

    OpenSSL Project, "openssl-pkcs8," docs.openssl.org, accessed June 2026. https://www.openssl.org/docs/man3.3/man1/openssl-pkcs8.html

  4. 4.

    OpenSSL Project, "openssl-x509," docs.openssl.org, accessed June 2026. https://docs.openssl.org/master/man1/openssl-x509/

  5. 5.

    Linux man-pages project, "ssh-add," man7.org, accessed June 2026. https://man7.org/linux/man-pages/man1/ssh-add.1.html

FAQ