Herramientas de desarrollo · Codificador y decodificador Base64
RFC 4648 explicado: el estándar que define Base64, base32 y base16
· Antecedentes
base64 codificación
RFC 4648 es el documento breve y legible detrás de cada implementación de Base64. Esta publicación explica lo que especifica, lo que deja abierto deliberadamente y por qué las implementaciones aún difieren.
Dos bibliotecas, dos respuestas para la misma cadena: un verdadero enigma de interoperabilidad que solo resuelve el estándar
Dos bibliotecas de JavaScript pueden devolver Base64 diferente para la misma cadena, y cada una afirma ser correcta. RFC 4648 es el documento legible de doce páginas que debería resolver tales desacuerdos; sin embargo, las implementaciones aún difieren porque el RFC deja deliberadamente ciertas decisiones a las aplicaciones. Este artículo explica lo que especifica RFC 4648, lo que delega intencionalmente a las personas que llaman y por qué leer el estándar una vez resuelve la mayoría de los acertijos reales de interoperabilidad. La herramienta de codificador y decodificador Base64 incluye vectores de prueba RFC 4648 para que pueda verificar una implementación con los ejemplos autorizados.
RFC 4648 reemplazó y consolidó varios documentos anteriores: Base64 de MIME (RFC 2045), Base64 de Privacy-Enhanced Mail (RFC 1421), base32 de S/MIME (RFC 2630) y base16 de varias fuentes. La consolidación fue necesaria porque MIME y PEM tenían cada uno su propio alfabeto y reglas, y el ajuste de línea MIME entraba en conflicto con los bloques de columnas 64 de PEM. RFC 4648 define cinco familias de codificación en un solo lugar: base64, base64url, base32, base32hex y base16, cada una con su propio alfabeto, reglas de relleno y vectores de prueba de ejemplo. El alfabeto base64 es A-Z, a-z, 0-9, más y barra, en ese orden.
Lo que establecen los vectores de implementación y prueba: alfabetos estándar y seguros para URL, manejo de espacios en blanco y relleno
Cada carácter representa 6 bits; tres bytes de entrada (24 bits) se asignan a cuatro caracteres de salida. El alfabeto no es arbitrario: evita caracteres que difieren entre EBCDIC y ASCII, evitando caracteres de control, comillas y la barra invertida que necesitaría escapar en los literales de cadena C. La variante base64url reemplaza el signo más por un guión y la barra con guión bajo para evitar caracteres reservados en las URL y los nombres de archivos. Ambas variantes son igualmente válidas; La sección 2 del RFC 4648 especifica base64, la sección 5 especifica base64url y una aplicación debe indicar cuál utiliza.
Rellenar con caracteres iguales lleva la salida a un múltiplo de cuatro caracteres. Si la entrada es 1 byte (8 bits), la salida son dos caracteres más dos signos iguales. Si la entrada es 2 bytes (16 bits), la salida es de tres caracteres más un signo igual. Si la entrada es un múltiplo de 3 bytes, no se necesita relleno. Algunas aplicaciones omiten el relleno o permiten que falte relleno en la decodificación; La sección 3.2 del RFC 4648 define la codificación canónica como siempre rellenada, pero la sección 3.3 señala que los decodificadores pueden aceptar el relleno faltante por motivos de compatibilidad.
Los alfabetos que implementa esta herramienta: Base64 y Base64url estándar; otras bases quedan fuera de su alcance
La distinción de relleno es la razón por la cual las implementaciones no están de acuerdo: un decodificador estricto rechaza los iguales faltantes, mientras que uno indulgente lo acepta. RFC 4648 dice explícitamente: el carácter de relleno igual generalmente está codificado en porcentaje cuando se usa en URL, por lo que si la salida base64url se usa directamente en un parámetro de URL, el relleno no es necesario y debe omitirse. Esta oración es una de las razones por las que el modo seguro para URL y la omisión de relleno a menudo se combinan, aunque son opciones independientes. La sección 5 (base64url) no prohíbe el relleno; simplemente toma nota de la práctica común.
Una persona que llama y elige base64url debe decidir si se requiere relleno para el sistema receptor. Los diferentes decodificadores manejan de manera diferente los caracteres que no son alfabéticos en la entrada. La sección 3.1 del RFC 4648 establece: Las implementaciones DEBEN rechazar la codificación si contiene caracteres fuera del alfabeto base. Sin embargo, la sección 3.3 señala que MIME Base64 (RFC 2045) permite saltos de línea para el ajuste de caracteres 76, y los decodificadores para MIME deben omitir los espacios en blanco. El RFC distingue entre decodificación estricta (rechazar todo lo que no sea alfabético) y decodificación compatible con MIME (omitir espacios en blanco, rechazar otros caracteres).
Relleno, caracteres no alfabéticos y codificación canónica: las secciones que explican la mayoría de los desacuerdos sobre el decodificador
Una solicitud debe elegir qué regla seguir; el estándar define ambos. Base32 utiliza A-Z y 2-7 (32 caracteres en total), codificando cinco bytes de entrada (40 bits) en ocho caracteres de salida. Base32hex sustituye 0-9 y a-v por los caracteres alfabéticos, lo que resulta útil en contextos donde se prefieren las letras minúsculas.
Base16 es hexadecimal: 0-9 y a-f. Base32 y base32hex tienen sus propias reglas de relleno en las secciones 6 y 7, y el RFC proporciona vectores de prueba separados para cada alfabeto. La mayoría de los desarrolladores sólo necesitan base64 y base64url; base32, base32hex y base16 se incluyen en el RFC para que esté completo y para aplicaciones como secretos TOTP (RFC 4226) y codificación DNS.
Opciones de aplicación visibles en esta implementación: ajuste de línea, decodificación de texto estricta y manejo de errores
Los vectores de prueba en RFC 4648 son la verdad fundamental para verificar una implementación. La codificación de las cadenas f, fo, foo, foob, fooba y foobar produce una salida base64 específica: Zg==, Zm8=, Zm9v, Zm9vYg==, Zm9vYmE= y Zm9vYmFy. Una implementación que produce resultados diferentes para estas cadenas es incorrecta. El RFC proporciona vectores de prueba equivalentes para base32, base32hex y base16. La herramienta de codificación y decodificación Base64 incluye estos vectores para que pueda verificar su salida con el estándar. El ajuste de línea es una preocupación MIME, no una preocupación base64.
RFC 2045 especifica 76 líneas de caracteres; La sección 3.1 del RFC 4648 señala esto en el contexto de MIME pero no lo convierte en un requisito de base64 en sí. Algunas aplicaciones se ajustan a 64 caracteres (el estándar PEM original); otros no se envuelven en absoluto. Un decodificador RFC 4648 base64 estricto funciona únicamente con el alfabeto y el relleno. Un decodificador compatible con MIME debe omitir los saltos de línea (CR, LF, CRLF). Una aplicación que utilice base64 fuera de MIME no debe agregar saltos de línea a menos que el sistema receptor los requiera; El RFC no define el ajuste de línea como parte de base64.
Ejemplo resuelto: los propios vectores de prueba del RFC: codificar los prefijos 'foobar' y verificarlos en el navegador
El manejo de espacios en blanco es otro punto de variación en la implementación. RFC 4648 dice que los decodificadores estrictos deben rechazar caracteres que no sean alfabéticos. Base64 envuelto en MIME (RFC 2045 base64) permite espacios en blanco para formatear. Los dos estándares coinciden en cuáles deberían ser los bytes de salida, pero difieren en qué entrada es válida. La mayoría de las implementaciones de JavaScript eligen la compatibilidad MIME y omiten los espacios en blanco; la regla estricta rara vez se usa en los navegadores. El codificador y decodificador Base64 acepta entradas estrictas y que contienen espacios en blanco (MIME), lo que hace la distinción explícita. La decodificación canónica frente a la indulgente es la última gran variación.
La decodificación canónica sigue la sección RFC 4648 3.2: rechazar el relleno con formato incorrecto, rechazar el relleno faltante, rechazar los caracteres que no sean alfabéticos. La decodificación indulgente, utilizada en los estándares web (la especificación HTML lo llama perdonar-base64), agrega reglas: ignorar los espacios en blanco, aceptar el relleno faltante, permitir guiones y guiones bajos como equivalentes de barras diagonales incluso en el modo base64 estándar. atob() de JavaScript es indulgente; un decodificador RFC 4648 estricto es más estricto. Ninguno de los dos está mal; sirven a diferentes contextos. Una aplicación que lee datos de un usuario o de la red debe saber qué regla espera la otra parte.
Lo que esto no cubre: los documentos MIME y PEM en sí, y las API específicas del idioma.
El RFC deja nueve opciones a la aplicación: cuál de los cinco alfabetos, si requerir o permitir relleno, si requerir o permitir espacios en blanco, si tratar el guión bajo como equivalente de barra diagonal, cómo informar errores, cómo manejar el final de la entrada, si aceptar el relleno faltante, cuántos bytes de salida asignar y cómo señalar un límite de tamaño. Estas opciones explican por qué dos implementaciones de RFC 4648 pueden no estar de acuerdo en la misma entrada. Lea el RFC una vez; verifique su implementación con sus vectores de prueba; indique qué opciones utiliza su aplicación; probar la interoperabilidad con el par real, no suposiciones.
Comprender el RFC 4648 resuelve la mayoría de las disputas de Base64 porque el desacuerdo generalmente no se trata del RFC en sí, sino de las opciones que eligió cada parte. El RFC es lo suficientemente breve como para leerlo de un extremo a otro en una hora. El estándar define los alfabetos, proporciona vectores de prueba y advierte dónde deben decidir las implementaciones. La herramienta de codificación y decodificación Base64 le permite experimentar con los vectores de prueba y ver el alfabeto estándar en acción. La mayor parte del uso cotidiano de base64 no requiere un conocimiento profundo de RFC; pero al depurar discrepancias de codificación o integrar con una API desconocida, leer el estándar una vez elimina las conjeturas.
Conclusión: lea el estándar una vez: cómo el codificador y decodificador Base64 le brinda una manera rápida de verificar los vectores de prueba del alfabeto estándar
RFC 4648 es la consolidación de décadas de práctica de codificación base ad-hoc en una especificación legible. No define cuándo usar base64 (MIME, PEM, JWT, URI de datos, etc., cada uno tiene sus propias especificaciones); define qué es base64. Al definir cinco familias de codificación y observar qué opciones son canónicas, el RFC permite comprobar si una implementación es correcta. Los vectores de prueba autorizados son el punto de partida: si su implementación codifica foobar y produce algo distinto a Zm9vYmFy, el RFC dice que la implementación es incorrecta.
Utilice esa autoridad como punto de control de verificación: codifique cada vector de prueba RFC, compare los caracteres exactos y luego decodifique el resultado para confirmar que los bytes originales regresan sin cambios. Esta verificación basada en navegador separa un error alfabético o de relleno de un problema en otra parte de una integración, manteniendo al mismo tiempo el estándar en sí como referencia en lugar de depender de una etiqueta de biblioteca.