Claves API explicadas: longitud, formato, almacenamiento y rotación
Una clave API es una cadena larga y aleatoria que un programa envía con cada petición para indicar qué aplicación llama. A diferencia de una contraseña, nadie tiene que recordarla, así que puede ser tan larga y aleatoria como haga falta. A diferencia de un token de inicio de sesión, suele durar hasta que alguien la revoca. La documentación de Google resume el riesgo: las claves API son credenciales al portador, de modo que quien tiene una puede usarla.
Esta cuarta parte de la serie sobre seguridad recorre la vida entera de una clave: cuántos bits aleatorios necesita, en qué formato escribirla, por qué existen prefijos como sk_live_, cómo enviarla, qué debe guardar el servidor y cómo rotarla y revocarla.
¿Clave API, contraseña o token de acceso?
Las tres demuestran algo a un servidor, y por eso se confunden a menudo. La diferencia está en quién las crea, cuánto duran y qué guarda el servidor:
| Credencial | La crea | Dura | El servidor guarda |
|---|---|---|---|
| Contraseña | una persona | hasta que la persona la cambia | un hash lento (Argon2id, scrypt, bcrypt) |
| Clave API | un generador aleatorio | hasta que se rota o se revoca | un hash rápido, como SHA-256 |
| Token de acceso (OAuth, JWT) | el servidor de inicio de sesión, tras un login | de minutos a horas | una firma que comprobar, o un registro del token |
Una clave API suele identificar una aplicación o una integración, no a una persona. Cuando una clave haría las veces de una persona que inicia sesión, un token de acceso obtenido con un flujo de inicio de sesión adecuado suele ser mejor herramienta, como explica la parte anterior, sobre los JSON Web Tokens.
Qué longitud debe tener una clave
Lo que protege una clave es el número de bits aleatorios que contiene, no su longitud en caracteres. Cada bit duplica el número de claves posibles: 128 bits aleatorios permiten unas 3,4 × 10³⁸ claves, de modo que probar siquiera una millonésima parte a mil millones de intentos por segundo llevaría unos 10¹⁶ años, casi un millón de veces la edad del universo. Por eso 128 bits es un mínimo sólido, y 256 bits solo cuestan unos caracteres más.
Los bits deben salir de un generador aleatorio criptográfico. En un navegador es crypto.getRandomValues(); MDN advierte que Math.random() no proporciona números criptográficamente seguros y no debe usarse para nada relacionado con la seguridad. Los lenguajes de servidor tienen sus equivalentes, como el módulo secrets de Python o crypto.randomBytes() en Node.js.
GitHub subió sus tokens OAuth de 160 a 178 bits de entropía cuando cambió su formato en 2021. Un caso necesita todavía más: un secreto que firma JSON Web Tokens con HMAC. El RFC 7518 exige una clave al menos tan larga como la salida del hash: 256 bits para HS256, 384 para HS384 y 512 para HS512.
Formatos: base62, hexadecimal o base64url
Los bits aleatorios hay que escribirlos como texto. El alfabeto decide cuántos caracteres hacen falta y dónde se puede pegar la clave sin problemas:
| Formato | Caracteres | Bits por carácter | Longitud para 256 bits |
|---|---|---|---|
base62 | a–z, A–Z, 0–9 | 5,95 | 43 |
hex | 0–9, a–f | 4 | 64 |
base64url | a–z, A–Z, 0–9, - y _ | 6 | 43 |
Base62 se ha vuelto habitual para las claves porque solo tiene letras y números: nada que una URL, una terminal o un archivo de configuración traten de forma especial, y un doble clic selecciona la clave entera. El hexadecimal es más largo, pero funciona donde solo se aceptan 0–9 y a–f. Base64url, del RFC 4648, es el más corto, pero su - puede cortar la selección con doble clic. El Base64 estándar es una mala elección, porque su + y su / necesitan escaparse en las URL.
Escribir base62 correctamente exige cuidado: un byte aleatorio tiene 256 valores, y 256 no es múltiplo de 62, así que un simple byte % 62 hace un poco más probables los ocho primeros caracteres. Un buen generador descarta los bytes de 248 en adelante, como hace el generador de nTools.
Prefijos y escaneo de secretos
Muchos proveedores empiezan sus claves con un prefijo fijo y legible. Las claves secretas de Stripe empiezan por sk_live_ o sk_test_, sus claves publicables por pk_ y sus claves restringidas por rk_. Desde 2021, los tokens de GitHub empiezan por ghp_ los de acceso personal, gho_ los de OAuth y ghs_ los de servidor a servidor.
sk_live_…Clave secreta de Stripe, modo real: pagos de verdad.pk_test_…Clave publicable de Stripe, entorno de pruebas: se puede poner en una página web.ghp_…Token de acceso personal de GitHub.
Un prefijo no es secreto ni añade seguridad, pero cumple tres funciones útiles. Una persona ve de un vistazo para qué sirve una clave y si es de pruebas. GitHub eligió el guion bajo porque no es un carácter de Base64, de modo que cadenas aleatorias como los hashes no pueden parecer un token por casualidad, y porque un doble clic selecciona el token entero. Sobre todo, un prefijo permite a los escáneres encontrar claves filtradas: el escaneo de secretos de GitHub recorre todo el historial de Git de todas las ramas y, cuando encuentra el secreto de un proveedor asociado, avisa a ese proveedor, que puede revocar la clave.
GitHub termina además sus tokens con una suma de comprobación CRC32 de 32 bits escrita en seis caracteres base62. No añade seguridad, pero permite a un escáner descartar cadenas aleatorias sin conexión, sin preguntar al servidor si el token existe.
Envíala en una cabecera, nunca en la URL
El RFC 6750, que define los tokens al portador de OAuth 2.0, dice que los clientes deben enviarlos en la cabecera Authorization y no ponerlos en las URL de las páginas, porque las direcciones acaban en el historial del navegador y en los registros del servidor. Google da el mismo consejo para sus propias claves API y ofrece una cabecera para ellas. El mismo RFC exige TLS: una clave enviada por http simple la puede leer cualquiera por el camino.
Authorization: Bearer sk_live_…Recomendado: la clave viaja en una cabecera, por https.https://api.example.com/v1/orders?api_key=sk_live_…Evítalo: la clave acaba en los registros y en el historial del navegador.
Qué debe guardar el servidor
El servidor no necesita guardar la clave, solo una forma de reconocerla. Guarda un hash de la clave, como su SHA-256; cuando llegue una petición, calcula el hash de la clave que trae y búscalo. Si la base de datos se filtra, los hashes no sirven para llamar a la API y de ellos no se pueden recuperar las claves.
Las contraseñas necesitan un hash lento porque, como explica la guía de OWASP sobre almacenamiento de contraseñas, un hash rápido como SHA-256 permite a los atacantes probar enormes cantidades de intentos en poco tiempo. Ese razonamiento depende de que las contraseñas se puedan adivinar. Una clave con 256 bits aleatorios no se puede, así que basta un solo hash rápido, y cada petición sigue siendo rápida.
Como solo se guarda el hash, la clave completa solo puede mostrarse una vez, al crearla. Stripe funciona así con las claves secretas de modo real que creas tú: el panel muestra la clave una sola vez y no puede volver a revelarla. Guarda en claro el prefijo y los últimos caracteres si la gente necesita distinguir sus claves.
Mantener las claves fuera del código
Las claves filtradas aparecen sobre todo donde los desarrolladores las pusieron por comodidad. Stripe advierte de que hay quien escanea continuamente los repositorios públicos en busca de claves API, y de que incluso los repositorios privados pueden quedar expuestos. Su consejo, que repiten Google y OWASP:
- No escribas nunca una clave en el código fuente, en un archivo de configuración bajo control de versiones ni en una app que la gente descarga: las apps se pueden desempaquetar.
- Carga las claves al ejecutar desde un gestor de secretos, como AWS Secrets Manager, Google Cloud Secret Manager, Azure Key Vault o HashiCorp Vault. Las variables de entorno son una alternativa: OWASP señala que cualquier proceso puede leerlas y que pueden acabar en los registros.
- No escribas nunca una clave en los registros, y no muestres la configuración ni las variables de entorno en una página de error.
- Da a cada aplicación, y a cada persona, su propia clave, solo con los permisos que necesita. Las claves restringidas de Stripe y las restricciones de claves de Google limitan lo que puede hacer una clave robada.
- Añade un escáner de secretos a un hook pre-commit, para que una clave se rechace antes de llegar al repositorio.
Rotación y revocación
Toda clave debería poder sustituirse con poca antelación. Rotar significa crear una clave nueva, pasar todas las aplicaciones a ella y después borrar la antigua. Hecho de forma periódica, limita cuánto tiempo sigue funcionando una clave robada y, como señala Stripe, demuestra que sabes dónde se usa cada clave. El panel de Stripe mantiene la clave antigua y la nueva funcionando a la vez hasta siete días para que el cambio sea suave.
Cuando una clave queda expuesta —subida a un repositorio, pegada en un chat, impresa en un registro—, revócala de inmediato, aunque no estés seguro de que alguien la haya visto. Borrar el commit no basta: puede que ya la hayan copiado, y sigue en el historial de Git y en cada clon. Si el sistema lo permite, pon también fecha de caducidad a las claves, para que una clave olvidada deje de funcionar sola.
Generar una clave
El generador de claves API de nTools crea claves en base62, hexadecimal o base64url, de 128 a 512 bits, con un prefijo opcional y, si lo quieres, el hash SHA-256 para guardar en el servidor. Usa crypto.getRandomValues() y funciona por completo en tu navegador: las claves no se envían a ningún sitio.
Preguntas frecuentes
¿Puedo usar un UUID como clave API?
Un UUID versión 4 tiene 122 bits aleatorios y una forma fija y reconocible, y se diseñó como identificador, no como secreto. Es mejor generar una clave propia de 128 bits o más.
¿Es segura una clave generada en el navegador?
Sí, si sale de crypto.getRandomValues(), el generador criptográfico que el navegador usa para su propia seguridad, y la página no la envía a ningún sitio. El generador de nTools funciona así: ninguna petición sale de la página al pulsar «Generar».
¿Deben caducar las claves API?
Si el sistema lo permite, sí: una fecha de caducidad limita el daño de una clave olvidada o filtrada sin que nadie se dé cuenta. Las claves de larga duración son habituales, y por eso la rotación y la revocación rápida importan todavía más.
Subí una clave a Git. ¿Y ahora?
Primero revócala o rótala, y después limpia el repositorio. Reescribir el historial no vuelve a hacer segura la clave, porque puede que ya la hayan copiado.
¿Es mejor cifrar la clave que calcular su hash?
Solo si el propio servidor tiene que usar la clave más tarde, por ejemplo para llamar a otro servicio con ella. Una clave que solo hay que comprobar debe guardarse como hash: así no hay nada que descifrar si la base de datos se filtra.
Anterior en la serie ← JSON Web Tokens: claims, firmas y validación segura
Referencias
- GitHub — Behind GitHub’s new authentication token formats (April 2021)
- GitHub Docs — About secret scanning
- GitHub Docs — About secret scanning for partners
- Stripe — API keys
- Stripe — Best practices for managing secret API keys
- Google Cloud — Best practices for managing API keys
- RFC 6750 — The OAuth 2.0 Authorization Framework: Bearer Token Usage (October 2012)
- RFC 7518 — JSON Web Algorithms (JWA) (May 2015)
- RFC 4648 — The Base16, Base32, and Base64 Data Encodings (October 2006)
- OWASP — Secrets Management Cheat Sheet
- OWASP — Password Storage Cheat Sheet
- MDN — Crypto: getRandomValues()
- MDN — Math.random()
Guías relacionadas
- Direcciones IP explicadas: IPv4, IPv6 y los rangos reservados
- Subredes y CIDR explicados: prefijos, máscaras y hosts utilizables
- Registros DNS explicados: A, AAAA, CNAME, MX, TXT y NS
- ¿Está caído un sitio web o solo te pasa a ti? Cómo comprobarlo paso a paso
- Códigos de estado HTTP y errores de Cloudflare: qué significan 403, 404, 429, 500, 503 y 521
- Marcas de tiempo Unix y zonas horarias explicadas
- Contar fechas: días entre fechas, años bisiestos y semanas ISO
- Formatos de imagen explicados: JPEG, PNG, WebP, AVIF y HEIC
- El tamaño de una imagen explicado: píxeles, DPI, peso y calidad
- Las fotos del móvil explicadas: HEIC, metadatos EXIF y tu privacidad
- Fortaleza de las contraseñas explicada: longitud, entropía y frases de contraseña
- Funciones hash: SHA-256, sumas de comprobación y hash de contraseñas
- JSON Web Tokens: claims, firmas y validación segura
- Los UUID explicados: v4, v7 y cómo elegir la versión adecuada
- Los códigos QR explicados: capacidad, corrección de errores y tamaño de impresión
- Porcentajes e IVA explicados: añadir, quitar y encadenar
- Errores comunes en JSON y cómo corregirlos
- Los archivos CSV explicados: separadores, comillas, codificación y Excel
- Las codificaciones de texto explicadas: UTF-8, Base64 y codificación URL
- Editar PDF en el navegador: qué se conserva al unir, dividir y convertir