Upload a file
  1. base64hub
  2. Learn Base64
  3. Base64 standards and RFCs
Reference

Base64 Standards: From PEM and MIME to RFC 4648

Base64 has no single inventor and no single specification. It grew out of secure email in 1987, was adopted by MIME, and was finally written down on its own in 2003. These are the documents that define it and the variants they created.

Timeline

YearDocumentWhat it contributed
1987RFC 989 (PEM, part I)The 64-character “printable encoding” with = padding, plus * for unencrypted sections
1988, 1989RFC 1040, RFC 1113Revised PEM drafts
1992RFC 1341 (MIME)Base64 as a Content-Transfer-Encoding for email
1993RFC 1421 (PEM), RFC 1521 (MIME)PEM lines of exactly 64 characters, revised MIME
1996RFC 2045 (MIME)The MIME definition still in use: lines of at most 76 characters
1997RFC 2152 (UTF-7)Base64 inside a text encoding for Unicode
2003RFC 3501 (IMAP4rev1)Modified Base64 with , for mailbox names
2003RFC 3548First standalone spec: base64, base64url, base32, base16
2006RFC 4648Replaces RFC 3548, adds base32hex and test vectors
2007RFC 4880 (OpenPGP)Radix-64 armor with a CRC-24 checksum
2015RFC 7468Strict rules for PEM-style certificate and key files
2015RFC 7515 (JWS)Base64URL without padding for tokens
2024RFC 9580 (OpenPGP)Replaces RFC 4880, deprecates the armor checksum

PEM: where Base64 started

The alphabet we use today first appeared in RFC 989, “Privacy Enhancement for Internet Electronic Mail”, published in February 1987. Encrypted mail had to pass through gateways that only handled printable text, so PEM needed a way to write binary ciphertext with characters that survive any mail system. It took 6 bits at a time and mapped them to A-Z, a-z, 0-9, + and /, with = for padding. The table in RFC 989 is identical to the alphabet table on this site. It also reserved * to mark sections that were not encrypted, a feature that did not survive.

PEM went through RFC 1040 and RFC 1113 and settled in RFC 1421 (February 1993), which fixed the line length: “each line except the last containing exactly 64 printable characters and the final line containing 64 or fewer”. The reason given was printing and SMTP’s 1000-character line limit. PEM as a secure mail system never caught on, but its file format did. Every -----BEGIN CERTIFICATE----- block is a descendant, and RFC 7468 (2015) now spells out the rules: generators must wrap at exactly 64 characters, parsers may accept other widths. Inspect such files with the certificate decoder.

MIME: Base64 for every email attachment

MIME (RFC 1341 in 1992, RFC 1521 in 1993, RFC 2045 in 1996) needed a way to put images and documents into email and borrowed PEM’s encoding. RFC 2045 is still the reference for email today, and it differs from PEM in two ways:

  • Encoded lines must not be longer than 76 characters, separated by CRLF.
  • “Any characters outside of the base64 alphabet are to be ignored in base64-encoded data.” Decoders skip line breaks, spaces and anything else that is not part of the alphabet.

That second rule is why so many decoders silently drop invalid characters. Generate MIME-style output with the MIME Base64 encoder, and see Base64 in email for how attachments are structured.

RFC 3548 and RFC 4648: one reference for all

Until 2003, every protocol that used Base64 pointed to MIME or PEM and inherited their line-length and lenient-decoding rules, whether it wanted them or not. RFC 3548 (July 2003) defined base64, base64url, base32 and base16 as standalone encodings. RFC 4648 (October 2006) replaced it with minor changes: it added base32hex, which keeps the sort order of the encoded data, and a set of test vectors:

BASE64("")       = ""
BASE64("f")      = "Zg=="
BASE64("fo")     = "Zm8="
BASE64("foo")    = "Zm9v"
BASE64("foobar") = "Zm9vYmFy"

The rules in RFC 4648 are stricter than MIME’s, unless the specification that references it says otherwise:

  • Line feeds: implementations must not add them (section 3.1).
  • Padding: implementations must include = padding (section 3.2).
  • Non-alphabet characters: decoders must reject them (section 3.3).
  • Canonical encoding: encoders must set unused bits to zero, and decoders may reject input where they are not (section 3.5). Without this, SGk/Pg== and SGk/Ph== both decode to Hi?>.

The phrase “unless the specification referring to this document explicitly states otherwise” is doing a lot of work. It is how JWS gets to drop padding and MIME gets to keep its 76-character lines while both still use “RFC 4648 Base64”. The Base32 and Base16 tools implement the other two encodings from the same RFC.

Variants defined in other standards

JWS and JWT: Base64URL without padding

RFC 7515 (May 2015) defines BASE64URL(x) as the section 5 alphabet “with all trailing ‘=’ characters omitted”, with no line breaks or whitespace. JWT, JWE, JWK and most of the JOSE family use this. Details in Base64 in JWT.

IMAP: modified UTF-7 with a comma

IMAP mailbox names are 7-bit strings, so RFC 3501 (section 5.1.3) encodes non-ASCII folder names in “modified UTF-7”. Runs of non-ASCII characters are converted to UTF-16, Base64-encoded without padding, with , instead of /, and wrapped in & and -. The RFC’s own example &U,BTFw- is the Chinese name 台北, and a German folder Entwürfe becomes Entw&APw-rfe. Plain UTF-7 (RFC 2152) writes the same name as Entw+APw-rfe.

OpenPGP: Radix-64 with a CRC-24

OpenPGP’s ASCII armor is MIME Base64 plus a checksum line. RFC 4880 defines a CRC-24 (generator 0x864CFB, initial value 0xB704CE) over the binary data, Base64-encoded and prefixed with =. GnuPG produces this for the 12 bytes Hello world!:

-----BEGIN PGP ARMORED FILE-----
Comment: Use "gpg --dearmor" for unpacking

SGVsbG8gd29ybGQh
=s4Gu
-----END PGP ARMORED FILE-----

RFC 4880 allows lines of up to 76 characters; GnuPG writes 64. RFC 9580 (July 2024) keeps the format but says the CRC-24 line “SHOULD NOT be generated” and that implementations must not reject a block because it is missing or wrong.

Table of Base64 variants

VariantIndex 62 and 63PaddingLine lengthDefined in
Standard Base64+ /RequiredNoneRFC 4648, section 4
Base64URL- _Optional, by referring specNoneRFC 4648, section 5
JWS / JWT- _NeverNoneRFC 7515
MIME+ /RequiredAt most 76, CRLFRFC 2045
PEM+ /RequiredExactly 64RFC 1421, RFC 7468
OpenPGP armor+ /RequiredAt most 76 (GnuPG: 64)RFC 4880, RFC 9580
UTF-7+ /NoneNot applicableRFC 2152
IMAP modified UTF-7+ ,NoneNot applicableRFC 3501
bcryptAlphabet ./A-Za-z0-9NoneNot applicableDe facto (OpenBSD)
crypt(3) hashesAlphabet ./0-9A-Za-zNoneNot applicableDe facto (Unix)

In the last two rows the whole alphabet is reordered. They are covered on the alphabet page. Many other formats reference one of the rows above without changing anything: HTTP Basic authentication (RFC 7617), data URIs (RFC 2397), XML Schema’s base64Binary, and Subresource Integrity hashes all use standard Base64 with padding.

FAQ

Which RFC defines Base64?

RFC 4648 (October 2006) is the general reference. It defines base64, base64url, base32, base32hex and base16. MIME’s version is in RFC 2045, and PEM’s original in RFC 1421.

Why are MIME lines 76 characters and PEM lines 64?

Both limits keep lines well under SMTP’s 1000-character limit. PEM fixed 64 in RFC 1421; MIME chose “no more than 76” in its own spec. RFC 4648 says encoders must not add line breaks at all unless the referring standard asks for them.

Is Base64URL an official standard?

Yes. It is section 5 of RFC 4648, “Base 64 Encoding with URL and Filename Safe Alphabet”, and appeared first in RFC 3548. JWS (RFC 7515) uses it without padding.

What is the =XXXX line at the end of a PGP block?

A CRC-24 checksum of the decoded data, itself written in Base64. RFC 9580 (2024) says new implementations should not emit it and must not reject a block because of it.

Keep reading