"Lo codificaré en Base64 para que nadie pueda leerlo." Esta línea aparece en revisiones de código, mensajes de Slack y respuestas de Stack Overflow más de lo que debería. Base64 no es cifrado. No es ofuscación. No es seguridad de ningún tipo. Decodificarlo requiere una llamada de función y cero conocimiento de cualquier clave o secreto. Este artículo explica qué es realmente Base64, por qué persiste la confusión y qué usar en su lugar cuando de verdad necesitas proteger datos.
Qué es Base64 realmente
Base64 es un esquema de codificación —— un mapeo reversible entre datos binarios y un conjunto de 64 caracteres ASCII imprimibles (A–Z, a–z, 0–9, +, /, con = como padding).
Cada 3 bytes de entrada se convierten en 4 caracteres Base64. El algoritmo es completamente determinista y no requiere clave:
// Codificación
btoa("hello") // → "aGVsbG8="
btoa("secret password") // → "c2VjcmV0IHBhc3N3b3Jk"
// Decodificación —— una llamada, sin clave
atob("c2VjcmV0IHBhc3N3b3Jk") // → "secret password"Eso es todo. Cualquiera con acceso a la cadena codificada puede decodificarla al instante, en cualquier lenguaje, en cualquier entorno, sin información adicional.
Por qué existe la confusión
Las cadenas codificadas en Base64 parecen datos cifrados. Están llenas de mayúsculas, minúsculas, números y caracteres especiales mezclados, y no tienen parecido visible con la entrada original. Este ruido visual basta para engañar a un observador no técnico —— y, sorprendentemente a menudo, también a uno técnico.
El patrón también se refuerza por proximidad. Base64 aparece constantemente en contextos de seguridad:
- Los certificados HTTPS están codificados en Base64 (formato PEM)
- Los tokens JWT usan codificación Base64url para su header y payload
- La autenticación HTTP Basic envía credenciales como Base64
- Las claves SSH se almacenan como Base64
- El cifrado a menudo se codifica en Base64 para el transporte
Ver Base64 en todos estos lugares adyacentes a la seguridad lleva a los desarrolladores a confundir la codificación con la seguridad. La codificación es solo el envoltorio; la seguridad viene de las operaciones criptográficas que hay debajo.
Codificación vs cifrado: la diferencia central
La distinción es simple y absoluta:
| Codificación (Base64) | Cifrado (AES, RSA…) | |
|---|---|---|
| Propósito | Representar datos binarios como texto | Ocultar datos de partes no autorizadas |
| ¿Requiere clave? | No | Sí |
| ¿Reversible por cualquiera? | Sí —— una llamada de función | Solo con la clave correcta |
| ¿Añade confidencialidad? | No | Sí (si se usa correctamente) |
| Tamaño de salida | ~33% mayor que la entrada | Varía según algoritmo |
El cifrado transforma los datos con una clave de forma que, sin la clave, recuperar el original es computacionalmente inviable. La codificación Base64 no tiene esa propiedad.
Errores de seguridad en el mundo real
Guardar secretos "codificados" en el código fuente
// ❌ Esto no es secreto —— cualquiera puede decodificarlo
const API_KEY = atob("c2stbGl2ZS1hYmMxMjM0NTY3ODk=");
// Cualquiera que lea este código ejecuta:
atob("c2stbGl2ZS1hYmMxMjM0NTY3ODk=") // → "sk-live-abc123456789"Las herramientas automáticas de escaneo de secretos (Secret Scanning de GitHub, GitGuardian, truffleHog) decodifican cadenas Base64 como parte de su detección. Si esperas que Base64 las detenga, no lo hará.
Autenticación HTTP Basic
// La cabecera Authorization se ve así:
Authorization: Basic dXNlcjpwYXNzd29yZA==
// Ese Base64 se decodifica trivialmente:
atob("dXNlcjpwYXNzd29yZA==") // → "user:password"La autenticación HTTP Basic solo es segura sobre HTTPS —— la capa TLS proporciona el cifrado real. El Base64 en la cabecera es puramente para codificar el par username:password como un único valor textual, no para ocultarlo. Sobre HTTP plano, cualquiera que intercepte el tráfico puede leer las credenciales al instante.
Tratar los "tokens" JWT como secretos
// Un JWT se ve como tres secciones Base64url unidas por puntos:
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjQyfQ.abc123
// La sección central (payload) se decodifica a:
atob("eyJ1c2VySWQiOjQyfQ") // → '{"userId":42}'Los payloads JWT no están cifrados —— están codificados en Base64url y firmados. Cualquiera que reciba el token puede leer el payload. La firma evita la manipulación pero no proporciona confidencialidad. Nunca pongas datos sensibles (contraseñas, números de tarjeta, información personal) en un payload JWT a menos que uses JWE (JSON Web Encryption), que es un estándar diferente y mucho menos común.
Ofuscar datos en URLs
// Patrón habitual en apps legadas
/profile?data=eyJ1c2VySWQiOjQyfQ==
// Pega esto en cualquier decodificador:
atob("eyJ1c2VySWQiOjQyfQ==") // → '{"userId":42}' Base64 en URLs no añade seguridad alguna. También se rompe fácilmente —— los caracteres + y / del Base64 estándar no son URL-safe y deben codificarse por porcentaje, por eso existe Base64url (+ → -, / → _, sin padding) como variante separada.
Para qué sirve Base64 en realidad
Base64 tiene usos legítimos e importantes —— solo que no para seguridad:
- Incrustar datos binarios en formatos de texto —— imágenes, fuentes y ficheros incrustados como URIs
data:en HTML/CSS o adjuntos en respuestas JSON de API - Adjuntos de email —— la codificación MIME usa Base64 para transmitir ficheros binarios sobre protocolos que solo manejan ASCII de 7 bits
- Seguridad de transporte —— algunos canales corrompen los datos binarios (bytes nulos, caracteres de control); Base64 garantiza que el contenido sobreviva intacto
- Identificadores opacos —— codificar un ID o cursor como Base64 le indica a los consumidores de la API "no intentes parsear esto", aunque no proporciona seguridad
Qué usar cuando realmente necesitas seguridad
Si tu objetivo es prevenir el acceso no autorizado a datos, usa una herramienta criptográfica real:
| Objetivo | Qué usar |
|---|---|
| Cifrar datos en reposo | AES-256-GCM (cifrado simétrico) |
| Cifrar datos en tránsito | TLS 1.3 (HTTPS) |
| Hash de contraseñas | bcrypt, scrypt o Argon2 —— nunca SHA-256 solo |
| Firmar tokens | HMAC-SHA256 (como JWT HS256) o RS256 |
| Almacenar secretos | Variables de entorno, un gestor de secretos (Vault, AWS Secrets Manager) |
| Cifrar tokens de extremo a extremo | JWE (JSON Web Encryption) —— no JWT plano |
Cuando realmente necesitas un token cifrado: JWE y JOSE
Un JWT estándar está firmado (JWS), no cifrado —— el payload se puede leer. Si de verdad necesitas confidencialidad de los claims, usa un JWE (JSON Web Encryption, RFC 7516). JWE forma parte de la familia de estándares JOSE:
- Algoritmos JOSE —— cifrado de contenido (p. ej.
A256GCM) y gestión de claves (p. ej.RSA-OAEP-256,ECDH-ES,A256KW). "alg" elige cómo se envuelve la clave de cifrado de contenido; "enc" elige cómo se cifra el payload mismo. - Envoltura de clave —— JWE genera una clave de cifrado de contenido fresca por mensaje y la envuelve bajo la clave del destinatario (asimétrica o simétrica). La clave envuelta viaja en la cabecera del token. Esto permite cifrar el mismo texto plano para distintos destinatarios sin recifrar el cuerpo.
- Forma compacta JWE —— cinco secciones Base64url unidas por puntos (header.key.iv.ciphertext.tag), visualmente como un JWT pero con cuatro piezas en vez de tres.
Elige una librería revisada (jose, node-jose, python-jose) en vez de implementar JWE por tu cuenta —— las combinaciones de algoritmos y formatos de clave son sutiles, y la caída silenciosa a algoritmos débiles es un bug clásico de JOSE.
Una prueba rápida para tu propio código
Busca en tu base de código btoa(, atob( y Buffer.from(…, 'base64'). Para cada aparición, pregúntate:
- ¿Lo hago para que el texto encaje en un campo o sobreviva al transporte? → Bien.
- ¿Lo hago para ocultar datos a alguien? → Reemplázalo por cifrado real o control de acceso.
Preguntas frecuentes
¿Base64 es cifrado?
No. Base64 es una codificación reversible sin clave —— cualquiera puede decodificarla en una llamada (atob()). El cifrado requiere una clave y hace inviable recuperar el contenido sin ella.
¿Es seguro guardar contraseñas o claves de API en Base64?
No. La decodificación es trivial y los escáneres de secretos decodifican Base64 automáticamente. Usa un gestor de secretos o variables de entorno y hashea contraseñas con bcrypt, scrypt o Argon2.
¿Cualquiera puede leer el payload de un JWT?
Sí. Los payloads JWT están codificados en Base64url y firmados, no cifrados —— cualquiera con el token puede leer todos los claims. Nunca pongas secretos en un JWT a menos que uses JWE. Pegar tokens en herramientas online es arriesgado; ver por qué no deberías pegar JSON sensible online.
¿Para qué sirve Base64 entonces?
Representar datos binarios como texto de forma segura —— URIs data:, adjuntos de email (MIME) y transporte sobre canales que solo manejan ASCII. Es un envoltorio, no una medida de seguridad.
Codifica y decodifica en tu navegador
¿Necesitas inspeccionar una cadena Base64 ahora mismo? Codificación y decodificación Base64 en fixjson.org te deja codificar o decodificar cualquier cadena al instante —— incluido Unicode completo y UTF-8 —— sin instalar nada. Útil para depurar payloads JWT, inspeccionar respuestas de API o ver qué se esconde dentro de una URI data:.
- Codificar y decodificar Base64 —— al instante, en el navegador, sin enviar datos a ningún servidor
- RFC 4648: El estándar Base64 —— la historia y definición formal de Base64 y Base64url
- Cómo decodificar un JWT —— leer los claims de un token y por qué decodificar no es verificar
- RFC 7519: JSON Web Token (JWT) —— cómo se usa Base64url en el estándar JWT y consideraciones de seguridad
- Decodificar URL —— decodifica por porcentaje una URL o query string
- JSON Stringify —— codifica un valor JSON como literal de cadena escapado