Saltar al contenido

Cómo validar manualmente una firma JWT usando herramientas en línea

Este equipo de expertos despúes de varios días de trabajo y recopilar de datos, obtuvimos los datos necesarios, queremos que todo este artículo sea de utilidad en tu plan.

Solución:

Todo es cuestión de formatos y codificación.

En https://jwt.io obtienes este token basado en tus valores de entrada y secreto:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

Queremos demostrar que la firma:

3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

es correcto.

La firma es un hash HMAC-SHA256 codificado en Base64url. (como se describe en RFC7515)

Cuando usa el generador HMAC en línea para calcular un hash para

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

con el secreto

hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6

usted obtiene

de921a2a4b225fd66ff0983e8566eb0f6e1584bdfa84120568da40e1f571dbd3

como resultado, que es un valor HMAC-SHA256, pero no codificado en Base64url. Este hash es un hexadecimal string representación de un gran número.

Para compararlo con el valor de https://jwt.io, debe convertir el valor de su hexadecimal string representación de nuevo a un número y Base64url lo codifica.

El siguiente script lo está haciendo y también usa crypto-js para calcular su propio hash. Esta también puede ser una forma de verificar sin bibliotecas JWT.

var CryptoJS = require("crypto-js");

// the input values
var base64Header = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
var base64Payload = "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ";
var secret = "hONPMX3tHWIp9jwLDtoCUwFAtH0RwSK6";

// two hashes from different online tools
var signatureJWTIO = "3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M";
var onlineCaluclatedHS256 =  "de921a2a4b225fd66ff0983e8566eb0f6e1584bdfa84120568da40e1f571dbd3";

// hash calculation with Crypto-JS. 
// The two replace expressions convert Base64 to Base64url format by replacing 
// '+' with '-', '/' with '_' and stripping the '=' padding
var base64Signature = CryptoJS.HmacSHA256(base64Header + "." + base64Payload , secret).toString(CryptoJS.enc.Base64).replace(/+/g,'-').replace(///g,'_').replace(/=+$/m,'');

// converting the online calculated value to Base64 representation
var base64hash = new Buffer.from(onlineCaluclatedHS256, 'hex').toString('base64').replace(///g,'_').replace(/+/g,'-').replace(/=+$/m,'')


// the results:
console.log("Signature from JWT.IO             : " + signatureJWTIO);
console.log("NodeJS calculated hash            : " + base64Signature);
console.log("online calulated hash (converted) : " + base64hash);

Los resultados son:

Signature from JWT.IO             : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

NodeJS calculated hash            : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

online calulated hash (converted) : 3pIaKksiX9Zv8Jg-hWbrD24VhL36hBIFaNpA4fVx29M

¡idéntico!

Conclusión:

Los valores calculados por las diferentes herramientas en línea son todos correctos pero no directamente comparables debido a los diferentes formatos y codificaciones. Un pequeño script como se muestra arriba podría ser una mejor solución.

Tuve el mismo problema hasta que me di cuenta de que estaba usando base64 codificación en lugar de base64url. También hay algunos detalles menores en el medio. Aquí está el manual paso a paso que, con suerte, hará que todo el proceso sea mucho más claro.

Notas

Nota 1: Debe eliminar todos los espacios y nuevas líneas de sus cadenas JSON (encabezado y carga útil). Se realiza implícitamente en jwt.io cuando genera un token JWT.

Nota 2: Para convertir JSON string para base64url string en cryptii.com cree la siguiente configuración:

First view: Text

Second view: Encode
    Encoding: Base64
    Variant: Standard 'base64url' (RFC 4648 §5)

Third view: Text

Nota 3: Para convertir el código HMAC HEX (firma) a base64url string en cryptii.com cree la siguiente configuración:

First view: Bytes
    Format: Hexadecimal
    Group by: None

Second view: Encode
    Encoding: Base64
    Variant: Standard 'base64url' (RFC 4648 §5)

Third view: Text

Manual

Solo necesitará dos herramientas en línea:

  1. [Tool 1]: cryptii.com – para base64url codificación
  2. [Tool 2]: codebeautify.org – para el cálculo de HMAC.

En cryptii.com puedes hacer ambas cosas base64url codificación / decodificación y también cálculo HMAC, pero para HMAC debe proporcionar un HEX key que es diferente de la entrada en jwt.io, por lo que utilicé un servicio separado para el cálculo de HMAC.

Los datos de entrada

En este manual utilicé los siguientes datos:

  • Encabezamiento:

    "alg":"HS256","typ":"JWT"
    
  • Carga útil:

    "sub":"1234567890","name":"John Doe","iat":1516239022
    
  • Secreto (key):

    The Earth is flat!
    

El secreto no es base64 codificado.

Paso 1: convertir el encabezado [Tool 1]

  • Encabezado (texto sin formato):

    "alg":"HS256","typ":"JWT"
    
  • Encabezado (base64url codificado):

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    

Paso 2: convertir la carga útil [Tool 1]

  • Carga útil (texto sin formato):

    "sub":"1234567890","name":"John Doe","iat":1516239022
    
  • Carga útil (base64url codificado):

    eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
    

Paso 3: Calcule el código HMAC (firma) [Tool 2]

Calcule HMAC usando SHA256 algoritmo.

  • Aporte string (base64url encabezado codificado y carga útil, concatenados con un punto):

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
    
  • Código calculado (número HEX):

    c8a9ae59f3d64564364a864d22490cc666c74c66a3822be04a9a9287a707b352
    

El código HMAC calculado es una representación HEX de la firma.
Nota: no debe estar codificado para base64url como texto plano string sino como una secuencia de bytes.

Paso 4: Codifique el código HMAC calculado para base64url [Tool 1]:

  • Firma (Bytes):

    c8a9ae59f3d64564364a864d22490cc666c74c66a3822be04a9a9287a707b352
    
  • Firma (base64url codificado):

    yKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I
    

Resumen

Aquí están nuestros resultados (todos base64url codificado):

  • Encabezamiento:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    
  • Carga útil:

    eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
    
  • Firma:

    yKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I
    

Los resultados de jwt.io:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.yKmuWfPWRWQ2SoZNIkkMxmbHTGajgivgSpqSh6cHs1I

Como puede ver, las tres partes son idénticas.

Te mostramos reseñas y valoraciones

Si tienes alguna perplejidad y capacidad de medrar nuestro escrito eres capaz de dejar un comentario y con mucho gusto lo leeremos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *