HMAC: firma y verificación de mensajes
let firma be hmac(cuerpo, clave) -- la firma como bytes (32)
decode(firma, "hex") -- la misma firma como texto hex de 64 caracteres
verify_hmac(cuerpo, firma_recibida, clave) -- true/false, en tiempo constante
Es el mecanismo de los webhooks de Stripe/GitHub/Shopify: quien conoce la clave puede verificar que el mensaje viene de quien dice venir y no fue tocado. La firma no es secreta, así que se puede mostrar en hex. verify_hmac acepta la firma en bytes, en hex o en base64 y compara en tiempo constante.
Comparar tokens: `constant_time_eq`
Comparar con == un token secreto abre un canal lateral: la comparación corta en el primer byte distinto y el tiempo de respuesta filtra información. constant_time_eq(a, b) tarda siempre lo mismo, y acepta secretos en cualquiera de los dos lados.
Contraseñas: NUNCA sha256
let hash be password_hash(pw) -- "$argon2id$v=19$..." con sal aleatoria
password_verify(pw, hash) -- true/false, constante
sha256/hmac son rápidos a propósito — perfectos para integridad, fatales para contraseñas (una GPU prueba miles de millones por segundo).
password_hash usa argon2id con parámetros OWASP y sal aleatoria: dos usuarios con la misma contraseña obtienen hashes distintos.
token() genera un identificador impredecible (sesiones, API keys) del CSPRNG del sistema — necesita require random. Nunca uses random() para seguridad.
Ejecuta el ejemplo: fíjate que el mismo password_hash("hola") da un hash distinto en cada corrida (sal aleatoria) y sin embargo password_verify siempre lo reconoce.