Generar y verificar firmas de webhooks

Pega el cuerpo original y el secreto para generar o verificar su firma HMAC. Incluye formatos GitHub y Stripe; una firma válida no comprueba la vigencia del timestamp ni evita la repetición de eventos.

Se ejecuta localmente en tu navegador
Signature inputs
Los saltos de línea pegados se convierten en LF. Actívalo para reproducir un cuerpo firmado con bytes CRLF.
Generated signature
Enter a secret and payload to generate a signature.
Verify a received signature
Genera una firma o pega una firma recibida para verificarla localmente.
Vista previa de la cabecera
Generate a signature to see the corresponding request header.
Server-side verification patterns
Generate a signature to see Node.js and PHP verification patterns.

Firma exactamente los bytes recibidos

La verificación de webhooks falla si el middleware analiza o reformatea el body antes de comprobarlo. Conserva el body original, aplica la entrada de firma documentada por el proveedor y usa una comparación de tiempo constante en el servidor. Esta página no envía el payload ni el secreto.

Cómo generar o verificar una firma de webhook

Firma el cuerpo exacto que pegas con HMAC-SHA-256, SHA-384 o SHA-512, reproduce los formatos X-Hub-Signature-256 de GitHub y v1 de Stripe, y compara una firma recibida byte a byte con el mismo secreto.

El cálculo se hace en esta pestaña con Web Crypto. El cuerpo, el secreto y las firmas no salen del navegador; una coincidencia confirma los bytes, no la antigüedad del evento.

  1. Elige el formato de firma: HMAC genérico, GitHub X-Hub-Signature-256 o Stripe v1. Los dos formatos de proveedor usan siempre SHA-256.
  2. Pega el cuerpo original exacto y el secreto. Para Stripe, pulsa Usar hora actual o escribe la marca de tiempo enviada; activa Firmar con saltos de línea CRLF si el emisor firmó bytes CRLF.
  3. Pulsa Generar firma para ver la cabecera correspondiente y ejemplos de verificación en Node.js y PHP. Si cambias cualquier dato después, el valor se atenúa hasta que vuelvas a generar.
  4. Para comprobar un valor recibido, pégalo en Verificar una firma recibida y pulsa Verificar firma. El hexadecimal funciona siempre, base64 funciona en webhooks genéricos y una cabecera Stripe-Signature completa se lee junto con su marca de tiempo t=.
  5. Usa Copiar firma para llevarte el valor de la cabecera y Limpiar para vaciar los campos y volver a HMAC genérico.

Qué contiene el resultado generado

Entrada firmada en cada formato

HMAC genérico firma el cuerpo original. GitHub firma ese mismo cuerpo y envía sha256=<hex> en X-Hub-Signature-256. Stripe firma la cadena <timestamp>.<cuerpo> y envía t=<timestamp>,v1=<hex> en Stripe-Signature.

Al pegar una cabecera de Stripe, el t de la cabecera forma la entrada firmada; el campo de marca de tiempo solo se usa si la cabecera no trae t=. Con secretos rotados puede haber varios v1, y la comprobación pasa si coincide cualquiera.

Por qué un cuerpo idéntico puede fallar

El área de texto convierte los CR y CRLF pegados en LF. Si el emisor firmó bytes CRLF, activa Firmar con saltos de línea CRLF: cada LF se reconstruye como CRLF antes de calcular el HMAC.

Cualquier diferencia textual importa: un JSON reserializado, un salto de línea final eliminado, un espacio cambiado, un componente de URL decodificado o leer el cuerpo ya parseado dan otro resumen. Copiar solo la parte hexadecimal de una cabecera elimina el prefijo sha256= o v1= que espera el formato, aunque la herramienta acepta las dos formas.

Qué no comprueba esta página

La verificación solo compara bytes HMAC. No rechaza marcas de tiempo antiguas ni eventos repetidos, no conoce la ventana de tolerancia del proveedor y no contacta con el emisor.

Base64 se acepta en webhooks genéricos; GitHub y Stripe transmiten hexadecimal, así que para ellos no se ofrece verificación en base64. Rotar o revocar un secreto filtrado sigue siendo una tarea del servidor.

Herramientas recientes: