Autenticación HMAC
HMAC(K, m) = H((K' XOR opad) || H((K' XOR ipad) || m))
Calcula el HMAC de un mensaje con una clave secreta, en hexadecimal o Base64, y compáralo con una firma esperada (se acepta el prefijo sha256=) para verificar un webhook de GitHub, Stripe o Shopify.
Hexadecimal o Base64, con o sin prefijo como sha256=.
Esta herramienta calcula el HMAC de un mensaje con una clave secreta, con SHA-1, SHA-256, SHA-384 o SHA-512, y lo compara con una firma esperada. Está pensada sobre todo para desarrolladores que integran o depuran webhooks de GitHub, Stripe o Shopify y necesitan saber si el fallo viene del secreto, del cuerpo del mensaje o de su código.
Un HMAC (RFC 2104, FIPS 198-1) combina una función hash con una clave secreta: HMAC(K, m) = H((K ⊕ opad) ‖ H((K ⊕ ipad) ‖ m)). Esta doble pasada hace imposible producir el valor sin la clave y evita el ataque de extensión de longitud que afecta a un simple SHA-256(clave ‖ mensaje). Con la clave «key» y el mensaje «The quick brown fox jumps over the lazy dog», HMAC-SHA-256 da f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8 en hexadecimal, es decir, 97yD9DBThCSxMpjmqm+xQ+9NWaFJRhdZl0edvC0aPNg= en Base64. La clave se usa tal como la escribes, mensaje y clave se codifican en UTF-8 y el cálculo pasa por la API Web Crypto del navegador.
La mayoría de proveedores firman el cuerpo bruto de la petición. GitHub envía X-Hub-Signature-256: sha256=<hex>, Shopify envía X-Shopify-Hmac-Sha256 en Base64 y Stripe firma la cadena «marca_de_tiempo.cuerpo» y coloca el valor hexadecimal tras v1= en la cabecera Stripe-Signature. Elige, por tanto, la salida hexadecimal o Base64 según el proveedor y pega la firma recibida en el campo opcional: se aceptan prefijos como «sha256=» y el resultado se actualiza mientras escribes. La comparación se hace en tiempo constante, como recomienda GitHub para el código de servidor.
Pega el mensaje exacto que se firma, por ejemplo el cuerpo bruto de un webhook, y después la clave secreta compartida.
Selecciona SHA-1, SHA-256, SHA-384 o SHA-512 y una salida hexadecimal o Base64 según lo que espere el servicio.
Si quieres, pega la firma esperada, con o sin un prefijo como sha256=: el HMAC y el resultado de la verificación se actualizan mientras escribes.
HMAC(K, m) = H((K' XOR opad) || H((K' XOR ipad) || m))
Copia el payload bruto y la cabecera X-Hub-Signature-256 desde la pestaña Recent Deliveries del webhook, introduce el secreto y compara. Si el valor coincide aquí pero no en tu servidor, es tu framework el que modifica el cuerpo antes de la verificación.
Reconstruye la cadena firmada «t.cuerpo» a partir de la cabecera Stripe-Signature y del cuerpo bruto, calcula el HMAC-SHA-256 con tu secreto whsec_… y compáralo con el valor v1 para localizar por qué falla la verificación.
Shopify firma el cuerpo bruto con HMAC-SHA-256 y envía el resultado en Base64 en X-Shopify-Hmac-Sha256. Elige la salida Base64 y pega la cabecera para confirmar que usas el secreto de aplicación correcto.
Entrada
Mensaje: The quick brown fox jumps over the lazy dog; Clave secreta: key; Algoritmo: SHA-256; Codificación: HexadecimalResultado
Firma calculada: f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8Cualquiera puede calcular un hash como SHA-256: demuestra la integridad, no el origen. Un HMAC añade una clave secreta, de modo que solo quien tiene esa clave puede producir el valor correcto. Por eso autentica al remitente además de detectar cualquier modificación.
Casi siempre el cuerpo se modificó antes del cálculo: JSON analizado y vuelto a serializar por el framework, otra codificación o espacios añadidos. Otras causas frecuentes son un secreto equivocado (el de pruebas en lugar del de producción), un formato de salida incorrecto (hex en lugar de Base64) o, en Stripe, olvidar la marca de tiempo en la cadena firmada.
Para autenticar mensajes, sí: las colisiones de SHA-1 no permiten falsificar un HMAC-SHA-1 sin la clave, y se sigue usando, por ejemplo, en TOTP. Para cualquier sistema nuevo, prefiere HMAC-SHA-256, que ya es el estándar de los webhooks. GitHub mantiene la cabecera X-Hub-Signature en SHA-1 solo por compatibilidad.
La RFC 2104 recomienda una clave al menos tan larga como la salida del hash, es decir, 32 bytes para HMAC-SHA-256. Una clave más larga que el bloque (64 bytes en SHA-256) se procesa primero con el hash, así que no aporta seguridad adicional. Genérala de forma aleatoria en lugar de elegir una contraseña.
No, un HMAC no es un cifrado: no contiene el mensaje ni permite reconstruirlo. De hecho, el mensaje suele enviarse en claro junto a la firma. Para que un contenido sea ilegible necesitas un cifrado como AES-GCM.
El cálculo se realiza solo en tu navegador con Web Crypto: ni la clave ni el mensaje se transmiten. Aun así, por principio, usa un secreto de pruebas o rota el secreto tras una sesión de depuración en un ordenador compartido.
Herramientas relacionadas
Herramientas similares o complementarias a esta.
Calcula de una vez los hash MD5, SHA-1, SHA-256, SHA-384 y SHA-512 de un texto o archivo.
Comprueba si dos hash o sumas de verificación coinciden, sin importar mayúsculas, espacios ni dos puntos.
Genera tokens aleatorios seguros de 8 a 256 bytes en hexadecimal, Base64 o Base64URL, con prefijo opcional.
Distingue hash, cifrado y codificación; comprende SHA-256, SHA-3, colisiones y los límites de una huella sin autenticación.
Aprende cuándo utilizar cifrado, hashing, HMAC o PBKDF2 para confidencialidad, integridad, autenticación y contraseñas.
Comprende cómo los hashes SRI detectan cambios inesperados en scripts y hojas de estilo externos y cuáles son sus límites.
Aprende qué contiene un JWT, por qué decodificar no equivale a verificar y cómo funcionan exp, nbf, iss y aud.