Saltar al contenido

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

  1. 01
    Toma la hora tal como llega

    Es el texto de la cabecera X-Hablame-Timestamp: segundos Unix, sin convertirlo.

  2. 02
    Arma el mensaje firmado

    La hora, un punto y el cuerpo crudo, byte por byte: "<timestamp>.<cuerpo>". No lo leas como JSON para volverlo a escribir: con un solo espacio de diferencia la firma ya no coincide.

  3. 03
    Calcula el HMAC-SHA256

    Con tu secreto de firma completo como llave, whsec_ incluido. Pásalo a hexadecimal en minúsculas y antepón sha256=.

  4. 04
    Compara en tiempo constante

    Con X-Hablame-Signature. Si no coincide y llegó X-Hablame-Signature-Prev, compárala también. Si ninguna coincide, responde 401 y 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.compare_digest, hash_equals, hmac.Equal, MessageDigest.isEqual o CryptographicOperations.FixedTimeEquals.

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.

Lo mismo desde la terminal, con OpenSSL
# 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

Haz esto
En vez de esto
Firma el cuerpo crudo, tal como llegó.
Leer el JSON con el marco web y volverlo a escribir antes de firmar.
Usa el secreto completo como llave, con whsec_.
Quitarle el prefijo whsec_ al secreto.
Compara en tiempo constante.
Comparar con == o equals.
Acepta también X-Hablame-Signature-Prev.
Rechazar avisos durante una rotación porque solo miras la firma principal.

¿Necesitas ayuda?

¿Te sirvió esta página?

Ver todos los canales de soporte