Tema: hmac
-
La especificación Standard Webhooks frente a la cabecera HMAC de Shopify y al token de secreto compartido de GitLab
La especificación Standard Webhooks define las cabeceras webhook-id, webhook-timestamp y webhook-signature, un secreto en base64 con prefijo whsec_ cuyos bytes decodificados son la clave HMAC y una firma v1,<base64> sobre "{id}.{timestamp}.{payload}"; los tokens de firma de GitLab (GitLab 19.0, disponibilidad general en 19.1) la implementan tal cual. Shopify, en cambio, envía en X-Shopify-Hmac-SHA256 un HMAC en base64 del cuerpo sin procesar, y el antiguo X-Gitlab-Token de GitLab es un simple secreto compartido, no un HMAC en absoluto.
-
Verificación de firmas de solicitudes de Slack: X-Slack-Signature, la ventana de repetición de 5 minutos y la regla de los 3 segundos
Slack firma sus solicitudes con el valor v0=<HMAC-SHA256 en hexadecimal> de la cadena "v0:{timestamp}:{raw body}" en la cabecera X-Slack-Signature, junto con X-Slack-Request-Timestamp; el ejemplo de Slack rechaza la solicitud si esa marca de tiempo difiere de la hora local en más de cinco minutos. Además, los slash commands y las cargas interactivas deben confirmarse en un plazo de tres segundos, antes de cualquier procesamiento lento.
-
Verificación de firmas de webhooks de Stripe: Stripe-Signature, tolerancia de marca de tiempo y rotación de secretos
Stripe envía un encabezado Stripe-Signature con la forma t=<timestamp>,v1=<firma hex>, calculado como HMAC-SHA256 sobre la cadena "{timestamp}.{raw body}" con el secreto completo del endpoint whsec_ como clave. Por defecto, las bibliotecas de Stripe rechazan las firmas cuya marca de tiempo tenga más de cinco minutos (300 segundos) de antigüedad y, mientras un secreto rotado sigue activo (hasta 24 horas), el encabezado incluye un valor v1 por cada secreto activo.
-
Verificación de firmas de webhooks de GitHub: X-Hub-Signature-256, comparación en tiempo constante e IDs de entrega
GitHub firma cada entrega de webhook con HMAC-SHA256 sobre el cuerpo sin procesar de la petición y la envía como sha256=<hex digest> en la cabecera X-Hub-Signature-256. El receptor debe recalcular el digest a partir de los bytes exactos recibidos, compararlo con una función de tiempo constante y usar X-GitHub-Delivery para reconocer eventos reenviados; la antigua X-Hub-Signature (HMAC-SHA1) se mantiene solo por compatibilidad.
-
La trampa del cuerpo en bruto: por qué los parsers de JSON rompen la verificación de firmas de webhooks
Las firmas de webhooks basadas en HMAC se calculan sobre los bytes exactos que envió el proveedor; cualquier middleware JSON que interprete, reordene o vuelva a serializar el cuerpo antes de que llegue a tu handler altera esos bytes e invalida la firma. Express, FastAPI, Flask, Django y Go requieren cada uno una forma concreta de capturar el cuerpo intacto antes del parseo normal o en lugar de él.
Legible por máquina: JSON