Enviar um arquivo
  1. base64hub
  2. Aprenda Base64
  3. Padrões e RFCs do Base64
Referência

Padrões do Base64: do PEM e MIME até a RFC 4648

O Base64 não tem um inventor nem uma especificação única. Ele nasceu do e-mail seguro em 1987, foi adotado pelo MIME e só ganhou uma especificação própria em 2003. Estes são os documentos que o definem e as variantes que eles criaram.

Linha do tempo

AnoDocumentoO que trouxe
1987RFC 989 (PEM, parte I)A “codificação imprimível” de 64 caracteres com preenchimento =, mais * para seções não criptografadas
1988, 1989RFC 1040, RFC 1113Rascunhos revisados do PEM
1992RFC 1341 (MIME)Base64 como Content-Transfer-Encoding para e-mail
1993RFC 1421 (PEM), RFC 1521 (MIME)Linhas PEM de exatamente 64 caracteres, MIME revisado
1996RFC 2045 (MIME)A definição do MIME usada até hoje: linhas de no máximo 76 caracteres
1997RFC 2152 (UTF-7)Base64 dentro de uma codificação de texto para Unicode
2003RFC 3501 (IMAP4rev1)Base64 modificado com , para nomes de caixas de correio
2003RFC 3548Primeira especificação independente: base64, base64url, base32, base16
2006RFC 4648Substitui a RFC 3548, acrescenta base32hex e vetores de teste
2007RFC 4880 (OpenPGP)Armadura Radix-64 com checksum CRC-24
2015RFC 7468Regras estritas para arquivos de certificado e chave no estilo PEM
2015RFC 7515 (JWS)Base64URL sem preenchimento para tokens
2024RFC 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== e SGk/Ph== decodificam ambos para Hi?>.

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 63PreenchimentoTamanho da linhaDefinida em
Base64 padrão+ /ObrigatórioNenhumRFC 4648, seção 4
Base64URL- _Opcional, conforme a especificação que a referenciaNenhumRFC 4648, seção 5
JWS / JWT- _NuncaNenhumRFC 7515
MIME+ /ObrigatórioNo máximo 76, CRLFRFC 2045
PEM+ /ObrigatórioExatamente 64RFC 1421, RFC 7468
Armadura OpenPGP+ /ObrigatórioNo máximo 76 (GnuPG: 64)RFC 4880, RFC 9580
UTF-7+ /NenhumNão se aplicaRFC 2152
UTF-7 modificado do IMAP+ ,NenhumNão se aplicaRFC 3501
bcryptAlfabeto ./A-Za-z0-9NenhumNão se aplicaDe facto (OpenBSD)
Hashes crypt(3)Alfabeto ./0-9A-Za-zNenhumNão se aplicaDe 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.

Continue lendo