Verificar la firma
Cada aviso viene firmado con el secreto de tu destino. Verificar la firma es lo que te asegura que el aviso lo envió Hablame y que nadie lo cambió en el camino.
4 min de lectura
Cómo se calcula
- 01Toma la hora tal como llega
Es el texto de la cabecera
X-Hablame-Timestamp: segundos Unix, sin convertirlo. - 02Arma el mensaje firmado
La hora, un punto y el cuerpo crudo, byte por byte:
"<timestamp>.. No lo leas como JSON para volverlo a escribir: con un solo espacio de diferencia la firma ya no coincide.<cuerpo>" - 03Calcula el HMAC-SHA256
Con tu secreto de firma completo como llave,
whsec_incluido. Pásalo a hexadecimal en minúsculas y antepónsha256=. - 04Compara en tiempo constante
Con
X-Hablame-Signature. Si no coincide y llegóX-Hablame-Signature-Prev, compárala también. Si ninguna coincide, responde401y no proceses el aviso.
Nunca compares con =
Una comparación normal se detiene en el primer carácter distinto, y el tiempo que tarda le dice a un atacante cuántos acertó. Usa la función de tiempo constante de tu lenguaje: timingSafeEqual, hmac., hash_equals, hmac., MessageDigest. o CryptographicOperations..
Revisa la hora
La hora entra en la firma para que un aviso capturado no sirva para siempre. Acepta solo avisos cuya hora sea un entero a 300 segundos o menos de tu reloj, y mantén tu reloj sincronizado. Un reintento legítimo nunca llega con una hora vieja: la hora y la firma se calculan de nuevo en cada intento, sobre el mismo cuerpo.
Prueba tu código con este ejemplo
Este aviso está firmado con un secreto de ejemplo. Si tu función, con ese secreto, esa hora y el cuerpo exacto de la petición de ejemplo, produce la firma esperada, tu cálculo es correcto. Para esta prueba omite la revisión de la hora: el ejemplo tiene fecha fija.
| Dato | Valor |
|---|---|
| Secreto de ejemplo (no es real) | whsec_TU_SECRETO_DE_FIRMA |
X-Hablame-Timestamp | 1792854247 |
| Cuerpo | El de la petición de ejemplo, en una sola línea |
X-Hablame-Signature esperada | sha256= |
# Debe imprimir el mismo hexadecimal de la firma esperada, sin el prefijo sha256=
printf '%s' '1792854247.{"id":"0192f0c47b1e7a3d9c553e2a1b4c5d6e","type":"sms.mo.87654","data":{"shortCode":"87654","from":"573001234567","text":"Hola, quiero más información","receivedAt":"2026-10-24T15:04:05Z","messageId":"0192f0c4-7b1e-7a3d-9c55-3e2a1b4c5d6e"}}' \
| openssl dgst -sha256 -hmac 'whsec_TU_SECRETO_DE_FIRMA'Cuando se rota el secreto
Durante las 24 horas siguientes a una rotación, cada aviso trae dos firmas con la misma hora y el mismo cuerpo: X-Hablame-Signature con el secreto nuevo y X-Hablame-Signature-Prev con el anterior. Si tu código compara con las dos, puedes cambiar el secreto en tu sistema en cualquier momento de esa ventana sin rechazar ningún aviso. Pasada la ventana, solo llega la firma nueva.
Errores habituales
whsec_.whsec_ al secreto.= = o equals.X-Hablame-Signature-Prev.