Subir un archivo
  1. base64hub
  2. Aprende Base64
  3. Estándares y RFC de Base64
Referencia

Estándares Base64: de PEM y MIME a RFC 4648

Base64 no tiene un único inventor ni una única especificación. Nació del correo seguro en 1987, MIME lo adoptó y en 2003 por fin se escribió como estándar propio. Estos son los documentos que lo definen y las variantes que crearon.

Cronología

AñoDocumentoQué aportó
1987RFC 989 (PEM, parte I)La «codificación imprimible» de 64 caracteres con relleno =, más * para secciones sin cifrar
1988, 1989RFC 1040, RFC 1113Borradores revisados de PEM
1992RFC 1341 (MIME)Base64 como Content-Transfer-Encoding para el correo
1993RFC 1421 (PEM), RFC 1521 (MIME)Líneas PEM de exactamente 64 caracteres, MIME revisado
1996RFC 2045 (MIME)La definición de MIME que sigue vigente: líneas de 76 caracteres como máximo
1997RFC 2152 (UTF-7)Base64 dentro de una codificación de texto para Unicode
2003RFC 3501 (IMAP4rev1)Base64 modificado con , para nombres de buzones
2003RFC 3548Primera especificación independiente: base64, base64url, base32, base16
2006RFC 4648Sustituye a RFC 3548, añade base32hex y vectores de prueba
2007RFC 4880 (OpenPGP)Armadura Radix-64 con suma de comprobación CRC-24
2015RFC 7468Reglas estrictas para archivos de certificados y claves al estilo PEM
2015RFC 7515 (JWS)Base64URL sin relleno para tokens
2024RFC 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== y SGk/Ph== se decodifican ambos como Hi?>.

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 63RellenoLongitud de líneaDefinida en
Base64 estándar+ /ObligatorioNingunaRFC 4648, sección 4
Base64URL- _Opcional, según la especificación que la citeNingunaRFC 4648, sección 5
JWS / JWT- _NuncaNingunaRFC 7515
MIME+ /Obligatorio76 como máximo, CRLFRFC 2045
PEM+ /ObligatorioExactamente 64RFC 1421, RFC 7468
Armadura OpenPGP+ /Obligatorio76 como máximo (GnuPG: 64)RFC 4880, RFC 9580
UTF-7+ /NingunoNo aplicaRFC 2152
UTF-7 modificado de IMAP+ ,NingunoNo aplicaRFC 3501
bcryptAlfabeto ./A-Za-z0-9NingunoNo aplicaDe facto (OpenBSD)
Hashes de crypt(3)Alfabeto ./0-9A-Za-zNingunoNo aplicaDe 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.

Sigue leyendo