Cronología
| Año | Documento | Qué aportó |
|---|---|---|
| 1987 | RFC 989 (PEM, parte I) | La «codificación imprimible» de 64 caracteres con relleno =, más * para secciones sin cifrar |
| 1988, 1989 | RFC 1040, RFC 1113 | Borradores revisados de PEM |
| 1992 | RFC 1341 (MIME) | Base64 como Content-Transfer-Encoding para el correo |
| 1993 | RFC 1421 (PEM), RFC 1521 (MIME) | Líneas PEM de exactamente 64 caracteres, MIME revisado |
| 1996 | RFC 2045 (MIME) | La definición de MIME que sigue vigente: líneas de 76 caracteres como máximo |
| 1997 | RFC 2152 (UTF-7) | Base64 dentro de una codificación de texto para Unicode |
| 2003 | RFC 3501 (IMAP4rev1) | Base64 modificado con , para nombres de buzones |
| 2003 | RFC 3548 | Primera especificación independiente: base64, base64url, base32, base16 |
| 2006 | RFC 4648 | Sustituye a RFC 3548, añade base32hex y vectores de prueba |
| 2007 | RFC 4880 (OpenPGP) | Armadura Radix-64 con suma de comprobación CRC-24 |
| 2015 | RFC 7468 | Reglas estrictas para archivos de certificados y claves al estilo PEM |
| 2015 | RFC 7515 (JWS) | Base64URL sin relleno para tokens |
| 2024 | RFC 9580 (OpenPGP) | Sustituye a RFC 4880, declara obsoleta la suma de comprobación de la armadura |
PEM: donde empezó Base64
El alfabeto que usamos hoy apareció por primera vez en RFC 989, «Privacy Enhancement for Internet Electronic Mail», publicada en febrero de 1987. El correo cifrado tenía que pasar por pasarelas que solo manejaban texto imprimible, así que PEM necesitaba una forma de escribir el texto cifrado binario con caracteres que sobrevivieran a cualquier sistema de correo. Tomaba 6 bits cada vez y los asignaba a A-Z, a-z, 0-9, + y /, con = como relleno. La tabla de RFC 989 es idéntica a la tabla del alfabeto de este sitio. También reservaba * para marcar las secciones sin cifrar, una función que no sobrevivió.
PEM pasó por RFC 1040 y RFC 1113 y quedó fijado en RFC 1421 (febrero de 1993), que estableció la longitud de línea: cada línea salvo la última con exactamente 64 caracteres imprimibles, y la última con 64 o menos. El motivo que se daba era la impresión y el límite de 1000 caracteres por línea de SMTP. PEM como sistema de correo seguro nunca cuajó, pero su formato de archivo sí. Todo bloque -----BEGIN CERTIFICATE----- desciende de él, y RFC 7468 (2015) detalla ahora las reglas: los generadores deben cortar exactamente a 64 caracteres y los analizadores pueden aceptar otros anchos. Inspecciona estos archivos con el decodificador de certificados.
MIME: Base64 para cada adjunto de correo
MIME (RFC 1341 en 1992, RFC 1521 en 1993, RFC 2045 en 1996) necesitaba una forma de meter imágenes y documentos en el correo y tomó prestada la codificación de PEM. RFC 2045 sigue siendo hoy la referencia para el correo, y se diferencia de PEM en dos cosas:
- Las líneas codificadas no deben superar los 76 caracteres y se separan con CRLF.
- Cualquier carácter fuera del alfabeto base64 debe ignorarse en los datos codificados en base64. Los decodificadores se saltan los saltos de línea, los espacios y todo lo que no pertenezca al alfabeto.
Esa segunda regla es la razón de que tantos decodificadores descarten sin avisar los caracteres no válidos. Genera salida al estilo MIME con el codificador Base64 MIME, y consulta Base64 en el correo electrónico para ver cómo se estructuran los adjuntos.
RFC 3548 y RFC 4648: una referencia para todo
Hasta 2003, cada protocolo que usaba Base64 remitía a MIME o a PEM y heredaba sus reglas de longitud de línea y de decodificación permisiva, las quisiera o no. RFC 3548 (julio de 2003) definió base64, base64url, base32 y base16 como codificaciones independientes. RFC 4648 (octubre de 2006) la sustituyó con cambios menores: añadió base32hex, que conserva el orden de los datos codificados, y un conjunto de vectores de prueba:
BASE64("") = ""
BASE64("f") = "Zg=="
BASE64("fo") = "Zm8="
BASE64("foo") = "Zm9v"
BASE64("foobar") = "Zm9vYmFy"
Las reglas de RFC 4648 son más estrictas que las de MIME, salvo que la especificación que la cita diga otra cosa:
- Saltos de línea: las implementaciones no deben añadirlos (sección 3.1).
- Relleno: las implementaciones deben incluir el relleno
=(sección 3.2). - Caracteres fuera del alfabeto: los decodificadores deben rechazarlos (sección 3.3).
- Codificación canónica: los codificadores deben poner a cero los bits sobrantes, y los decodificadores pueden rechazar la entrada en la que no lo estén (sección 3.5). Sin esta regla,
SGk/Pg==ySGk/Ph==se decodifican ambos comoHi?>.
La frase «a menos que la especificación que cita este documento indique explícitamente lo contrario» tiene mucho peso. Gracias a ella, JWS puede prescindir del relleno y MIME puede mantener sus líneas de 76 caracteres, y ambos siguen usando «Base64 RFC 4648». Las herramientas Base32 y Base16 implementan las otras dos codificaciones de la misma RFC.
Variantes definidas en otros estándares
JWS y JWT: Base64URL sin relleno
RFC 7515 (mayo de 2015) define BASE64URL(x) como el alfabeto de la sección 5 con todos los caracteres = finales omitidos, sin saltos de línea ni espacios. JWT, JWE, JWK y la mayor parte de la familia JOSE lo usan. Los detalles, en Base64 en JWT.
IMAP: UTF-7 modificado con coma
Los nombres de buzón de IMAP son cadenas de 7 bits, así que RFC 3501 (sección 5.1.3) codifica los nombres de carpeta que no son ASCII en «UTF-7 modificado». Las secuencias de caracteres no ASCII se convierten a UTF-16, se codifican en Base64 sin relleno, con , en lugar de /, y se envuelven entre & y -. El ejemplo de la propia RFC, &U,BTFw-, es el nombre chino 台北, y una carpeta alemana Entwürfe se convierte en Entw&APw-rfe. El UTF-7 normal (RFC 2152) escribe el mismo nombre como Entw+APw-rfe.
OpenPGP: Radix-64 con CRC-24
La armadura ASCII de OpenPGP es Base64 MIME más una línea de suma de comprobación. RFC 4880 define un CRC-24 (generador 0x864CFB, valor inicial 0xB704CE) sobre los datos binarios, codificado en Base64 y precedido de =. GnuPG genera esto para los 12 bytes de Hello world!:
-----BEGIN PGP ARMORED FILE-----
Comment: Use "gpg --dearmor" for unpacking
SGVsbG8gd29ybGQh
=s4Gu
-----END PGP ARMORED FILE-----
RFC 4880 permite líneas de hasta 76 caracteres; GnuPG escribe 64. RFC 9580 (julio de 2024) mantiene el formato, pero dice que la línea CRC-24 no debería generarse («SHOULD NOT be generated») y que las implementaciones no deben rechazar un bloque porque falte o sea incorrecta.
Tabla de variantes de Base64
| Variante | Índices 62 y 63 | Relleno | Longitud de línea | Definida en |
|---|---|---|---|---|
| Base64 estándar | + / | Obligatorio | Ninguna | RFC 4648, sección 4 |
| Base64URL | - _ | Opcional, según la especificación que la cite | Ninguna | RFC 4648, sección 5 |
| JWS / JWT | - _ | Nunca | Ninguna | RFC 7515 |
| MIME | + / | Obligatorio | 76 como máximo, CRLF | RFC 2045 |
| PEM | + / | Obligatorio | Exactamente 64 | RFC 1421, RFC 7468 |
| Armadura OpenPGP | + / | Obligatorio | 76 como máximo (GnuPG: 64) | RFC 4880, RFC 9580 |
| UTF-7 | + / | Ninguno | No aplica | RFC 2152 |
| UTF-7 modificado de IMAP | + , | Ninguno | No aplica | RFC 3501 |
| bcrypt | Alfabeto ./A-Za-z0-9 | Ninguno | No aplica | De facto (OpenBSD) |
| Hashes de crypt(3) | Alfabeto ./0-9A-Za-z | Ninguno | No aplica | De facto (Unix) |
En las dos últimas filas se reordena todo el alfabeto. Se explican en la página del alfabeto. Muchos otros formatos remiten a una de las filas anteriores sin cambiar nada: la autenticación HTTP Basic (RFC 7617), las data URI (RFC 2397), el tipo base64Binary de XML Schema y los hashes de Subresource Integrity usan Base64 estándar con relleno.
Preguntas frecuentes
¿Qué RFC define Base64?
RFC 4648 (octubre de 2006) es la referencia general. Define base64, base64url, base32, base32hex y base16. La versión de MIME está en RFC 2045, y la original de PEM en RFC 1421.
¿Por qué las líneas de MIME tienen 76 caracteres y las de PEM 64?
Ambos límites mantienen las líneas muy por debajo del límite de 1000 caracteres de SMTP. PEM fijó 64 en RFC 1421; MIME eligió «no más de 76» en su propia especificación. RFC 4648 dice que los codificadores no deben añadir saltos de línea a menos que el estándar que la cita lo pida.
¿Base64URL es un estándar oficial?
Sí. Es la sección 5 de RFC 4648, «Base 64 Encoding with URL and Filename Safe Alphabet», y apareció por primera vez en RFC 3548. JWS (RFC 7515) lo usa sin relleno.
¿Qué es la línea =XXXX al final de un bloque PGP?
Una suma de comprobación CRC-24 de los datos decodificados, escrita a su vez en Base64. RFC 9580 (2024) dice que las nuevas implementaciones no deberían generarla y que no deben rechazar un bloque por su causa.