Codificador y decodificador Base64

Ambas direcciones, seguras para Unicode, con el alfabeto seguro para URL cuando lo necesites.

Para qué sirve

Base64 resuelve un solo problema: tienes bytes arbitrarios y un canal que solo admite texto imprimible. Las cabeceras de correo, los campos de texto de JSON, las URL, los atributos de HTML y buena parte de la infraestructura antigua se atragantan con el binario en crudo. Base64 convierte cada tres bytes en cuatro caracteres de un alfabeto de 64 símbolos que sobrevive a todos ellos.

Ese es todo su propósito. No es compresión: la salida es un tercio más larga. No es cifrado: no hay ninguna clave. Es una codificación de transporte, y todas las propiedades que la gente le atribuye por error vienen de confundir «no puedo leer esto» con «esto está protegido».

Dónde te lo vas a encontrar

  • JWT. Los tres segmentos, en el alfabeto seguro para URL y sin el relleno.
  • Autenticación básica de HTTP. Authorization: Basic no es más que usuario:contraseña codificado en Base64, y por eso la autenticación básica sobre HTTP sin cifrar equivale a enviar la contraseña en claro.
  • URI de datos. data:image/png;base64,... incrusta un archivo directamente en el HTML o el CSS.
  • Certificados y claves PEM. Las líneas entre -----BEGIN----- y -----END----- son DER codificado en Base64.
  • Adjuntos de correo. SMTP es un protocolo de texto; MIME usa Base64 para transportar todo lo que no lo sea.

La trampa de Unicode

El navegador te da btoa y atob, y son una trampa. Los dos trabajan sobre bytes representados como cadena, así que btoa lanza un error con cualquier carácter por encima de U+00FF. Pruébalo con un emoji y obtendrás InvalidCharacterError.

La solución es convertir antes a bytes UTF-8, que es lo que hace esta página:

// Encode any string safely
const bytes = new TextEncoder().encode(text);
const b64 = btoa(String.fromCharCode(...bytes));

// Decode back
const binary = atob(b64);
const out = new TextDecoder().decode(
  Uint8Array.from(binary, c => c.charCodeAt(0))
);

Una advertencia sobre la línea de codificación: desplegar un array grande dentro de String.fromCharCode desborda la pila de llamadas en torno a los cien mil elementos. Para cualquier cosa grande, recorre por trozos; esta página lo hace, y por eso aguanta un pegado de varios megabytes sin caerse.

Los dos alfabetos

Estándar (RFC 4648 §4)Seguro para URL (§5)
Índice 62+-
Índice 63/_
Relleno=, obligatorioNormalmente se omite
Lo usanMIME, PEM, autenticación básicaJWT, URL, nombres de archivo

El relleno es la parte que da problemas. Su única función es hacer que la longitud sea múltiplo de cuatro, y un descodificador siempre puede deducir cuánto falta, así que la variante segura para URL lo elimina. Los descodificadores estrictos rechazan entonces el resultado, y por eso un segmento de JWT pegado en otra herramienta falla tan a menudo. El de aquí restaura el relleno por su cuenta.

Dónde se usa mal

Como Base64 no se lee de un vistazo, acaba usándose como si fuera un secreto. Vale la pena nombrar los casos concretos:

  • Base64 para guardar contraseñas. Esto es texto plano disfrazado. Las contraseñas necesitan un hash lento de un solo sentido: bcrypt, scrypt, Argon2.
  • Base64 en el contenido de un JWT como si fuera privado. Ese contenido lo puede leer cualquiera que tenga el token, incluido el propio usuario. No pongas ahí nada que no le enseñarías.
  • Base64 para colar datos por delante de un filtro. Funciona un rato, y cualquier escáner que merezca la pena lo descodifica igualmente.

La regla que cubre los tres casos: si la seguridad de algo depende de que quien lo lea no lo descodifique, no tiene ninguna seguridad.

Relacionado

El descodificador de JWT separa un token y analiza ambos segmentos de una vez. Si lo que quieres es escapar texto que va dentro de una URL en lugar de codificar bytes, lo que seguramente buscas es la codificación por porcentaje, que es otra cosa. Y si lo que has descodificado resulta ser JSON, el formateador te lo dejará bien puesto.

Preguntas sobre Base64

¿Es el cifrado Base64?

No, y vale la pena ser franco porque la confusión provoca incidentes reales. Base64 es una codificación reversible sin clave ni secreto: cualquiera que tenga la cadena tiene los datos y decodificarlos requiere una línea de código. Existe para mover bytes a través de canales que solo llevan texto imprimible, no para ocultar nada. Almacenar una contraseña codificada en Base64 es almacenarla en texto sin formato con un paso adicional.

¿Por qué tantas herramientas Base64 fallan con emojis o caracteres acentuados?

Porque la función btoa del navegador opera con bytes en lugar de caracteres y arroja cualquier valor superior a U+00FF. Las herramientas que lo llaman directamente fallan en é, en 日本語 y en todos los emoji. Esta página se codifica primero en bytes UTF-8 y se vuelve a decodificar de la misma manera, por lo que el viaje de ida y vuelta es limpio para cualquier texto que pueda escribir.

¿Qué es Base64 seguro para URL?

El alfabeto estándar incluye + y /, que tienen significado en una URL, y = relleno, que también lo tiene. La variante segura para URL definida en RFC 4648 sustituye - por + y _ por /, y normalmente elimina el relleno. Es lo que usan los JWT para los tres segmentos, razón por la cual un segmento JWT pegado en un decodificador estándar a menudo falla hasta que se restablece el relleno. El decodificador aquí acepta alfabeto, acolchado o no.

¿Por qué la cadena codificada es más grande que lo que puse?

Alrededor de un tercio, siempre. Base64 representa tres bytes de entrada como cuatro caracteres imprimibles, por lo que la salida tiene 4/3 del tamaño antes del relleno. Ése es el precio de utilizar sólo caracteres que sobrevivan a sistemas que no pueden transportar bytes arbitrarios. También es la razón por la que se incrustan imágenes como datos: los URI en CSS hacen que la hoja de estilo sea notablemente más grande que los archivos de imagen.

Decodifiqué algo y entendí un galimatías. ¿Qué pasó?

Lo más probable es que los bytes no sean texto. Base64 codifica binarios arbitrarios (una imagen, un certificado, un archivo comprimido) y decodificarlos en una cadena produce una tontería porque no hay texto allí para recuperar. Esta página te lo dice explícitamente en lugar de mostrarte mojibake: decodifica con estricta validación UTF-8, por lo que las secuencias de bytes no válidas se informan como binarias en lugar de reemplazarlas silenciosamente con signos de interrogación.

Última revisión . ¿Has visto algo desactualizado? Dínoslo.