Cómo verificar signatures de JWT: HS256, RS256 y ES256
Cómo verificar signatures de JWT
Un JWT transporta sus claims en texto plano. Lo único que evita la falsificación es la signature. Sin verificación, un atacante puede crear tokens arbitrarios y suplantar a cualquier usuario. Esta guía cubre los tres algoritmos de firma JWT más comunes y cómo verificar cada uno.
El proceso de verificación
Independientemente del algoritmo, la verificación de la signature de un JWT sigue los mismos pasos:
- Divide el token en
.para extraer el header, el payload y la signature. - Decodifica el header en base64url para leer el campo
alg. - Recalcula la signature a partir del header y el payload usando el algoritmo y la clave.
- Compara la signature recalculada con la del token.
- Si coinciden, el token es auténtico.
HS256 (HMAC-SHA256)
HS256 es un algoritmo simétrico: la misma clave secreta crea y verifica la signature.
signature = HMACSHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
secret
)
Para verificar, recalcula el HMAC con la clave secreta compartida y compara:
Token: header.payload.sig
Secret: "my-shared-secret"
1. Compute: HMACSHA256("header.payload", "my-shared-secret")
2. Compare: computedSignature === sig
Consideraciones de seguridad: la clave secreta debe ser confidencial, rotarse periódicamente y tener al menos 256 bits de entropía. HS256 no es ideal para arquitecturas de microservicios donde muchos servicios necesitan la clave secreta compartida.
RS256 (RSA-SHA256)
RS256 es asimétrico. El emisor firma con una clave privada; los verificadores comprueban con la clave pública correspondiente.
signature = RSASHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
privateKey
)
Para verificar, usa la clave pública:
Token: header.payload.sig
Public: "-----BEGIN PUBLIC KEY-----..."
1. Load the RSA public key
2. Verify: RSA_SHA256_verify("header.payload", sig, publicKey)
Ventajas: las claves de firma y de verificación están separadas. Cualquier servicio puede verificar sin poseer una clave secreta. Las claves públicas pueden servirse desde un endpoint JWKS para facilitar la rotación.
ES256 (ECDSA-SHA256)
ES256 utiliza ECDSA con la curva P-256. Al igual que RS256, es asimétrico.
signature = ECDSA_SHA256(
base64urlEncode(header) + "." + base64urlEncode(payload),
privateKey
)
La verificación utiliza la clave pública ECDSA P-256. ES256 produce signatures mucho más pequeñas (64 bytes frente a 256 bytes de RSA-2048) y ofrece una verificación más rápida.
Comparación de algoritmos
| Propiedad | HS256 | RS256 | ES256 | |----------|-------|-------|-------| | Tipo de clave | Simétrica (clave secreta compartida) | Asimétrica (par RSA) | Asimétrica (par EC) | | Tamaño de la signature | 32 bytes | 256 bytes | 64 bytes | | Distribución de claves | Compartida en secreto | La clave pública es pública | La clave pública es pública | | Rotación | Moderada | Fácil (JWKS) | Fácil (JWKS) | | Caso de uso | Sistemas internos de confianza | APIs distribuidas | Móvil, IoT |
Errores comunes en la verificación
- Ataque de confusión de algoritmos. Si tu código lee
algdel token sin imponerlo, un atacante puede cambiar el algoritmo. Valida siempre que el algoritmo coincida con el valor esperado. - Aceptar
alg: "none". Algunas bibliotecas aceptan tokens sin firmar. Rechazaalg: "none"de forma explícita. - Truncamiento de la signature. Una comparación no constante puede filtrar información mediante ataques de temporización. Usa la comparación integrada de tu biblioteca de JWT.
Verifica tokens JWT en línea
Usa la herramienta de decodificador de JWT para decodificar y validar cualquier token. Pega el token, consulta el header y el payload, y verifica la signature proporcionando la clave secreta o pública adecuada. Todo el procesamiento ocurre en tu navegador.