Firmar y verificar JWT

Firma un JWT con HS256/384/512 o RS256/ES256, y verifica un token con un secreto o clave pública — firma, caducidad y alg:none comprobados por separado. En tu navegador.

encoding

Firmar y verificar JWT

Algoritmo
Payload (JSON)
Secreto
Expira en

ej. "1h", "7d" — deja vacío para omitir el claim "exp"

La firma ocurre en tu navegador con WebCrypto. Una clave privada pegada aquí nunca sale de esta pestaña — pero no firmes tokens de producción con una herramienta de navegador; usa tu backend.

What next?

FAQ

¿Qué diferencia hay entre esto y el JWT Decoder del sitio?

El decodificador de JWT solo lee un token: decodifica Base64URL el encabezado y el payload y te muestra los claims, pero nunca comprueba la firma. Eso funciona para responder "qué dice este token", pero no puede responder "es legítimo este token", porque un token completamente falsificado con cualquier payload que se te ocurra se decodifica igual de limpio que uno auténtico. Esta herramienta sí ejecuta la verificación criptográfica real: recalcula la firma a partir del encabezado y el payload usando el secreto o la clave pública que le des, la compara byte a byte con la firma que trae el token, y solo entonces reporta los claims de tiempo. Una diferencia concreta aparece justo en el caso alg: "none": según RFC 7519 §6, un "JWT sin seguridad" es un token con alg: "none" y la parte de firma vacía, y como el decodificador solo lee, sigue decodificando ese token con normalidad y le pone la etiqueta de advertencia "Sin seguridad" encima. Esta herramienta de verificación, en cambio, siempre rechaza ese token de plano — no hay forma de que "pase" la pestaña de verificación.

¿Por qué obtengo tres resultados distintos en vez de solo "válido" o "inválido"?

Porque "inválido" en realidad son tres fallos distintos con tres soluciones distintas. Una firma inválida significa que el token fue firmado con una clave diferente a la que proporcionaste — secreto equivocado, clave pública equivocada, o el payload fue alterado. Un token expirado tiene una firma perfectamente válida; quien lo emitió hizo todo bien, el token simplemente sobrevivió a su claim "exp" — la solución es pedir un token nuevo, no sospechar de una falsificación. Un algoritmo rechazado significa que el encabezado del token declara un algoritmo distinto al que le pediste a esta herramienta que comprobara, lo cual es un desajuste de configuración o, en el peor caso, un intento de ataque. Juntar los tres bajo una sola etiqueta "inválido" no le diría nada útil a alguien depurando un 401 sobre cuál de esos tres problemas tan diferentes está viendo realmente.

¿Qué es la vulnerabilidad "alg: none" y cómo la evita esta herramienta?

Algunas bibliotecas JWT antiguas aceptaban un token cuyo encabezado declarara "alg": "none" y trataban una firma vacía como automáticamente válida — la biblioteca veía "no se pidió ningún algoritmo" y se saltaba la verificación por completo, lo que significaba que cualquiera podía falsificar un token con los claims que quisiera con solo poner ese campo y no añadir nada después del último punto. Esta herramienta evita toda esa categoría de fallo al no preguntar nunca "¿el encabezado dice que hay que saltarse la verificación?": tú eliges de antemano el algoritmo que esperas (HS256, RS256, etc.), y esa expectativa se aplica como una lista blanca explícita mediante el parámetro algorithms de la librería jose. Si el encabezado del token declara cualquier otra cosa — "none" incluido — la verificación se rechaza antes de tocar siquiera el material de la clave, tal como debería comportarse una librería backend consciente de la seguridad. Esto mismo bloquea el ataque clásico de "confusión de algoritmo": usar la clave pública RS256 como si fuera un secreto HMAC para verificar una firma HS256 falsificada, porque la herramienta siempre fija el algoritmo de verificación según tu elección y nunca lo lee del propio token para decidir cómo comprobarlo.

¿Una firma válida significa que el token todavía se puede usar?

No necesariamente — por eso existe el estado expired separado del estado valid. La firma solo demuestra que el token viene de quien tiene la clave y que su contenido no fue alterado; no dice nada sobre si el token sigue "vivo". Un token con firma perfectamente correcta pero con el claim exp en el pasado devuelve el estado expired, con el detalle "la firma es válida, pero el claim exp está en el pasado". De forma similar, si el claim nbf (not-before) todavía está en el futuro, la herramienta reporta notYetValid aunque la firma sea correcta. Solo cuando todos los claims de tiempo son válidos y la firma coincide el resultado final es valid.

¿Qué formato de clave espera la ruta RS256 / ES256?

Para firmar, se espera una clave privada PEM en formato PKCS#8 (el bloque empieza con -----BEGIN PRIVATE KEY-----). Para verificar, se espera una clave pública PEM en formato SPKI (-----BEGIN PUBLIC KEY-----). Son exactamente los formatos que crypto.subtle.importKey de WebCrypto entiende de forma nativa — la librería jose que usa esta herramienta es solo una capa más cómoda sobre WebCrypto, no inventa su propio mecanismo de lectura de claves. Las claves PKCS#1 antiguas (-----BEGIN RSA PRIVATE KEY-----) usan una codificación distinta que WebCrypto no lee directamente; hay que convertirlas antes con openssl pkcs8 -topk8 -nocrypt.

¿Es seguro firmar o verificar una clave de producción en una herramienta de navegador?

Verificar tiene poco riesgo: solo pegas una clave pública o un secreto compartido cuyo destinatario ya conoces, y nada de lo que escribes se envía a ningún lado — la comprobación corre con la WebCrypto nativa del navegador, entera dentro de esta pestaña. Firmar es el caso donde hay que pensarlo dos veces: una clave privada pegada en cualquier pestaña queda expuesta al JavaScript de esa pestaña mientras esté abierta, y a cualquiera con acceso a ese dispositivo o una extensión maliciosa durante ese tiempo. Para un token de prueba desechable, ese es un intercambio razonable por la comodidad; para una clave privada que protege un sistema de producción real, fírmala en tu backend o en tu pipeline de CI con una librería del lado del servidor ya verificada — la misma precaución que ya recomiendan los generadores de claves de este sitio.

More encoding tools