HMAC (Hash-based Message Authentication Code, RFC 2104) combina un hash criptográfico con una clave secreta para generar un código que autentica tanto la integridad como el origen de un mensaje. Es la primitiva que hay detrás de la firma HS256 de los JWT, de webhooks de Stripe o GitHub y de la firma AWS Signature v4.
Por qué HMAC y no solo un hash
Un SHA-256 sobre `secret+mensaje` es vulnerable al length-extension attack: un atacante que conoce el hash de `secret+A` puede calcular el hash de `secret+A+B` sin conocer el secreto. HMAC evita el ataque con una construcción de doble hash (`H((K ⊕ opad) || H((K ⊕ ipad) || mensaje))`) que es demostrablemente segura mientras el hash base lo sea.
Elegir el algoritmo
HMAC-SHA256 es el estándar hoy: rápido, ampliamente soportado y con 256 bits de seguridad. HMAC-SHA512 tiene más margen pero es innecesario para la mayoría de casos. HMAC-SHA1 sigue siendo criptográficamente sólido como MAC (a diferencia de SHA-1 puro para firmas) pero muchas guías modernas ya lo desaconsejan por señal.
Verificación en tiempo constante
Al comparar el HMAC recibido con el esperado, nunca uses `===` o `strcmp`: son early-exit y filtran información temporal. Usa `crypto.timingSafeEqual` en Node, `hmac.compare_digest` en Python o equivalentes. Un atacante puede aprovechar la diferencia de nanosegundos para forjar firmas byte a byte.
Casos de uso comunes
- Verificar webhooks de Stripe, GitHub, Shopify o Twilio.
- Firmar cookies de sesión.
- Autenticar peticiones a APIs internas (HMAC pre-shared).