Contexto
Al implementar validacion HMAC para webhooks, el primer instinto es comparar las firmas con ==. Funciona, da el resultado correcto. Pero tiene una vulnerabilidad sutil.
Lo que aprendi
== en Python compara strings caracter por caracter y retorna False en el primer caracter diferente. Un atacante puede medir el tiempo de respuesta: si tarda mas, significa que mas caracteres coincidieron. Repitiendo miles de veces, puede deducir la firma correcta byte por byte. Se llama timing attack.
# MAL - vulnerable a timing attacks
if received_hash == expected_hash:
process_message()
# BIEN - tiempo constante
import hmac
if hmac.compare_digest(received_hash, expected_hash):
process_message()
hmac.compare_digest() siempre tarda lo mismo sin importar cuantos caracteres coincidan. Compara todos los bytes antes de retornar el resultado.
Cuando importa
En la practica, para webhooks internos detras de un firewall probablemente no te van a hacer timing attacks. Pero compare_digest no cuesta nada extra y es el estandar. No hay razon para usar == cuando existe la alternativa segura.
El pattern completo esta en whatsapp-webhook-patterns/src/hmac_signature.py.