Linha do tempo
| Ano | Documento | O que trouxe |
|---|---|---|
| 1987 | RFC 989 (PEM, parte I) | A “codificação imprimível” de 64 caracteres com preenchimento =, mais * para seções não criptografadas |
| 1988, 1989 | RFC 1040, RFC 1113 | Rascunhos revisados do PEM |
| 1992 | RFC 1341 (MIME) | Base64 como Content-Transfer-Encoding para e-mail |
| 1993 | RFC 1421 (PEM), RFC 1521 (MIME) | Linhas PEM de exatamente 64 caracteres, MIME revisado |
| 1996 | RFC 2045 (MIME) | A definição do MIME usada até hoje: linhas de no máximo 76 caracteres |
| 1997 | RFC 2152 (UTF-7) | Base64 dentro de uma codificação de texto para Unicode |
| 2003 | RFC 3501 (IMAP4rev1) | Base64 modificado com , para nomes de caixas de correio |
| 2003 | RFC 3548 | Primeira especificação independente: base64, base64url, base32, base16 |
| 2006 | RFC 4648 | Substitui a RFC 3548, acrescenta base32hex e vetores de teste |
| 2007 | RFC 4880 (OpenPGP) | Armadura Radix-64 com checksum CRC-24 |
| 2015 | RFC 7468 | Regras estritas para arquivos de certificado e chave no estilo PEM |
| 2015 | RFC 7515 (JWS) | Base64URL sem preenchimento para tokens |
| 2024 | RFC 9580 (OpenPGP) | Substitui a RFC 4880, torna obsoleto o checksum da armadura |
PEM: onde o Base64 começou
O alfabeto que usamos hoje apareceu pela primeira vez na RFC 989, “Privacy Enhancement for Internet Electronic Mail”, publicada em fevereiro de 1987. O e-mail criptografado precisava passar por gateways que só lidavam com texto imprimível, então o PEM precisava de um jeito de escrever o texto cifrado binário com caracteres que sobrevivessem a qualquer sistema de correio. Ele pegava 6 bits por vez e os mapeava para A-Z, a-z, 0-9, + e /, com = como preenchimento. A tabela da RFC 989 é idêntica à tabela do alfabeto deste site. Ela também reservava * para marcar seções não criptografadas, um recurso que não sobreviveu.
O PEM passou pelas RFC 1040 e RFC 1113 e se firmou na RFC 1421 (fevereiro de 1993), que fixou o tamanho da linha: “cada linha, exceto a última, contém exatamente 64 caracteres imprimíveis, e a última linha contém 64 ou menos”. O motivo citado era a impressão e o limite de 1000 caracteres por linha do SMTP. O PEM como sistema de e-mail seguro nunca pegou, mas o formato de arquivo dele, sim. Todo bloco -----BEGIN CERTIFICATE----- é um descendente, e hoje a RFC 7468 (2015) detalha as regras: geradores devem quebrar as linhas em exatamente 64 caracteres, e parsers podem aceitar outras larguras. Inspecione esses arquivos com o decodificador de certificados.
MIME: Base64 para todo anexo de e-mail
O MIME (RFC 1341 em 1992, RFC 1521 em 1993, RFC 2045 em 1996) precisava de um jeito de colocar imagens e documentos no e-mail e pegou emprestada a codificação do PEM. A RFC 2045 continua sendo a referência para e-mail hoje, e difere do PEM em dois pontos:
- As linhas codificadas não podem ter mais de 76 caracteres e são separadas por CRLF.
- “Quaisquer caracteres fora do alfabeto base64 devem ser ignorados em dados codificados em base64.” Os decodificadores pulam quebras de linha, espaços e qualquer outra coisa que não faça parte do alfabeto.
Essa segunda regra é o motivo de tantos decodificadores descartarem caracteres inválidos sem avisar. Gere saída no estilo MIME com o codificador Base64 MIME e veja Base64 no e-mail para entender como os anexos são estruturados.
RFC 3548 e RFC 4648: uma referência para todos
Até 2003, todo protocolo que usava Base64 apontava para o MIME ou o PEM e herdava as regras de tamanho de linha e de decodificação tolerante, quisesse ou não. A RFC 3548 (julho de 2003) definiu base64, base64url, base32 e base16 como codificações independentes. A RFC 4648 (outubro de 2006) a substituiu com pequenas mudanças: acrescentou o base32hex, que preserva a ordem de classificação dos dados codificados, e um conjunto de vetores de teste:
BASE64("") = ""
BASE64("f") = "Zg=="
BASE64("fo") = "Zm8="
BASE64("foo") = "Zm9v"
BASE64("foobar") = "Zm9vYmFy"
As regras da RFC 4648 são mais rígidas que as do MIME, a não ser que a especificação que a referencia diga o contrário:
- Quebras de linha: as implementações não devem inseri-las (seção 3.1).
- Preenchimento: as implementações devem incluir o preenchimento
=(seção 3.2). - Caracteres fora do alfabeto: os decodificadores devem rejeitá-los (seção 3.3).
- Codificação canônica: os codificadores devem zerar os bits não usados, e os decodificadores podem rejeitar entradas em que eles não estejam zerados (seção 3.5). Sem isso,
SGk/Pg==eSGk/Ph==decodificam ambos paraHi?>.
A ressalva “a menos que a especificação que referencia este documento declare explicitamente o contrário” carrega muito peso. É assim que o JWS pode dispensar o preenchimento e o MIME pode manter as linhas de 76 caracteres, enquanto os dois continuam usando “Base64 da RFC 4648”. As ferramentas Base32 e Base16 implementam as outras duas codificações da mesma RFC.
Variantes definidas em outros padrões
JWS e JWT: Base64URL sem preenchimento
A RFC 7515 (maio de 2015) define BASE64URL(x) como o alfabeto da seção 5 “com todos os caracteres ‘=’ finais omitidos”, sem quebras de linha nem espaços em branco. JWT, JWE, JWK e quase toda a família JOSE usam essa forma. Detalhes em Base64 no JWT.
IMAP: UTF-7 modificado com vírgula
Os nomes de caixas de correio no IMAP são strings de 7 bits, então a RFC 3501 (seção 5.1.3) codifica nomes de pastas não ASCII em “UTF-7 modificado”. Sequências de caracteres não ASCII são convertidas para UTF-16, codificadas em Base64 sem preenchimento, com , no lugar de /, e envolvidas por & e -. O exemplo da própria RFC, &U,BTFw-, é o nome chinês 台北, e uma pasta alemã Entwürfe vira Entw&APw-rfe. O UTF-7 comum (RFC 2152) escreve o mesmo nome como Entw+APw-rfe.
OpenPGP: Radix-64 com CRC-24
A armadura ASCII do OpenPGP é Base64 MIME mais uma linha de checksum. A RFC 4880 define um CRC-24 (gerador 0x864CFB, valor inicial 0xB704CE) sobre os dados binários, codificado em Base64 e prefixado com =. O GnuPG produz isto para os 12 bytes Hello world!:
-----BEGIN PGP ARMORED FILE-----
Comment: Use "gpg --dearmor" for unpacking
SGVsbG8gd29ybGQh
=s4Gu
-----END PGP ARMORED FILE-----
A RFC 4880 permite linhas de até 76 caracteres; o GnuPG escreve 64. A RFC 9580 (julho de 2024) mantém o formato, mas diz que a linha CRC-24 “não deveria ser gerada” (SHOULD NOT) e que as implementações não podem rejeitar um bloco porque ela está ausente ou errada.
Tabela de variantes do Base64
| Variante | Índices 62 e 63 | Preenchimento | Tamanho da linha | Definida em |
|---|---|---|---|---|
| Base64 padrão | + / | Obrigatório | Nenhum | RFC 4648, seção 4 |
| Base64URL | - _ | Opcional, conforme a especificação que a referencia | Nenhum | RFC 4648, seção 5 |
| JWS / JWT | - _ | Nunca | Nenhum | RFC 7515 |
| MIME | + / | Obrigatório | No máximo 76, CRLF | RFC 2045 |
| PEM | + / | Obrigatório | Exatamente 64 | RFC 1421, RFC 7468 |
| Armadura OpenPGP | + / | Obrigatório | No máximo 76 (GnuPG: 64) | RFC 4880, RFC 9580 |
| UTF-7 | + / | Nenhum | Não se aplica | RFC 2152 |
| UTF-7 modificado do IMAP | + , | Nenhum | Não se aplica | RFC 3501 |
| bcrypt | Alfabeto ./A-Za-z0-9 | Nenhum | Não se aplica | De facto (OpenBSD) |
| Hashes crypt(3) | Alfabeto ./0-9A-Za-z | Nenhum | Não se aplica | De facto (Unix) |
Nas duas últimas linhas, o alfabeto inteiro é reordenado. Elas são explicadas na página do alfabeto. Muitos outros formatos referenciam uma das linhas acima sem mudar nada: autenticação HTTP Basic (RFC 7617), data URIs (RFC 2397), o base64Binary do XML Schema e os hashes de Subresource Integrity usam todos Base64 padrão com preenchimento.
Perguntas frequentes
Qual RFC define o Base64?
A RFC 4648 (outubro de 2006) é a referência geral. Ela define base64, base64url, base32, base32hex e base16. A versão do MIME está na RFC 2045, e a original do PEM, na RFC 1421.
Por que as linhas do MIME têm 76 caracteres e as do PEM têm 64?
Os dois limites mantêm as linhas bem abaixo do limite de 1000 caracteres do SMTP. O PEM fixou 64 na RFC 1421; o MIME escolheu “no máximo 76” na sua própria especificação. A RFC 4648 diz que os codificadores não devem inserir quebras de linha, a menos que o padrão que a referencia peça.
O Base64URL é um padrão oficial?
Sim. Ele é a seção 5 da RFC 4648, “Base 64 Encoding with URL and Filename Safe Alphabet”, e apareceu primeiro na RFC 3548. O JWS (RFC 7515) usa essa variante sem preenchimento.
O que é a linha =XXXX no fim de um bloco PGP?
Um checksum CRC-24 dos dados decodificados, também escrito em Base64. A RFC 9580 (2024) diz que novas implementações não deveriam gerá-lo e não podem rejeitar um bloco por causa dele.