Firmas HTTP y replay en una integración de multas
Una firma válida puede reenviarse si no cubre método, destino, contenido y tiempo. Nonce, ventana de vigencia y almacenamiento atómico permiten detectar duplicados.
Por Marco Ferreiro ·
Una integración de flota recibe un aviso de multa correctamente firmado, lo procesa y devuelve éxito. Minutos después llega exactamente el mismo mensaje con la misma firma. La criptografía sigue validando: los bytes no cambiaron. Si el sistema ejecuta el efecto otra vez, sufrió un replay.
RFC 9421 ofrece parámetros y componentes para reducir ese riesgo, pero la política y el estado de detección pertenecen a la aplicación que carga el acta.
Qué demuestra una firma HTTP válida
Una firma prueba que los componentes cubiertos son equivalentes a los firmados con una clave aceptada. No dice nada sobre campos que quedaron afuera, ni garantiza que esa infracción no haya sido informada ya.
Si sólo se firma el cuerpo, ese cuerpo podría adjuntarse a otra ruta o método según el perfil. Si no se firma el digest, un intermediario o error podría cambiar contenido no cubierto.
La integración debe definir un conjunto obligatorio, algoritmo, clave, ventana y comportamiento ante campos ausentes. “Soporta RFC 9421” no es un contrato suficiente.
Componentes que distinguen una operación
Para un aviso que da de alta un acta, evaluá cubrir:
@method;@authority;@target-urio componentes equivalentes del destino;content-digestcuando hay cuerpo;- tipo de contenido relevante;
- parámetros de firma, incluidos creación y expiración.
RFC 9421 aconseja incluir datos de control como método, autoridad y destino. El receptor sólo confía en las partes firmadas. Agregar encabezados no cubiertos después de verificar puede cambiar el comportamiento, por lo que la aplicación debe rechazarlos o tratarlos como no confiables.
El digest vincula el cuerpo
RFC 9530 define campos de digestión de contenido. El emisor calcula el digest sobre la representación acordada y lo incluye entre los componentes firmados.
El receptor primero valida sintaxis, calcula el digest del cuerpo recibido y compara; luego construye la base de firma exactamente según el estándar. Parsear JSON y volver a serializarlo antes de verificar puede cambiar espacios, orden o números.
El límite de tamaño se aplica antes de almacenar cuerpos grandes: un lote de mil actas firmado sigue siendo un lote de mil actas.
Created, expires y tolerancia de reloj
created indica cuándo se creó la firma y expires cuándo el firmante deja de respaldarla. El verificador define una edad máxima y una tolerancia de reloj explícitas.
Un mensaje con creación futura fuera de tolerancia se rechaza. Uno expirado también. Una ventana corta reduce el tiempo de replay, pero debe contemplar la latencia real de un portal lento y los reintentos.
Sin métricas de desvío de reloj, ampliar silenciosamente la ventana oculta problemas. Sincronizá servidores y alertá cuando las firmas válidas se acercan repetidamente al límite.
Nonce: unicidad con estado
RFC 9421 permite un parámetro nonce para detectar repetición. El receptor necesita recordar los nonces aceptados durante al menos la ventana de replay.
La clave de almacenamiento puede incluir identidad de firmante, clave y nonce. La operación “si no existe, guardar” debe ser atómica. Dos nodos que consultan y después insertan por separado podrían aceptar simultáneamente el mismo valor.
El TTL del registro debe superar la ventana aceptada y la tolerancia. Al reiniciar, borrar prematuramente la memoria reabre el replay; por eso el estado suele ser durable o coordinado.
TLS no cubre todos los reintentos
TLS 1.3 protege datos ordinarios en tránsito, pero RFC 8446 advierte que 0-RTT tiene garantías más débiles frente a replay y que la aplicación debe ser segura para repetición. Incluso sin 0-RTT, un cliente o proxy puede reenviar una solicitud por timeout.
La firma autentica el mensaje reenviado: eso es correcto. La novedad se controla con nonce, tiempo e idempotencia. No desactives TLS por usar firmas; cumplen capas distintas.
Para operaciones con efectos, evitá 0-RTT salvo que exista un perfil explícito y el mensaje sea seguro ante repetición.
Replay e idempotencia
Un replay hostil y un reintento legítimo pueden transportar los mismos bytes: en los dos casos llega la misma acta. La política puede:
- rechazar un nonce repetido como replay;
- permitir que una clave de idempotencia devuelva el resultado previo;
- relacionar nonce e idempotencia sin confundir sus propósitos.
Si el contrato admite reintentos, el cliente genera una clave de idempotencia estable para esa infracción y una nueva firma según lo acordado. El servidor no vuelve a ejecutar el efecto.
Una firma nueva sobre el mismo comando no debería eludir la idempotencia. Por eso ambas defensas se prueban en conjunto.
Matriz mínima de pruebas negativas
Con un aviso de acta ficticio y firmado, ejecutá estas mutaciones de a una:
| Mutación | Resultado esperado |
|---|---|
| cambiar método | firma inválida |
| cambiar destino | firma inválida |
| modificar un byte del cuerpo | digest o firma inválidos |
| repetir nonce | rechazo antes del efecto |
| usar firma expirada | rechazo temporal |
enviar created futuro |
rechazo fuera de tolerancia |
| omitir componente obligatorio | rechazo de política |
La prueba cuenta efectos en una base sintética. Una respuesta de error no alcanza si el acta ya quedó cargada dos veces.
Claves, rotación y algoritmos
keyid permite localizar material y política, pero no debería aceptar arbitrariamente el algoritmo indicado por el mensaje. El servidor mantiene una asociación confiable entre clave, firmante, algoritmo, tenant y vigencia.
Durante rotación puede aceptar dos claves por un período, registrando cuál verificó. Revocar una clave exige decidir qué pasa con mensajes creados antes de la revocación pero recibidos después.
Los secretos no aparecen en logs. Se registran hash del nonce, key ID no sensible, edad, componentes cubiertos y razón de rechazo.
Fallas distribuidas
En múltiples regiones, el mismo nonce podría llegar a dos nodos antes de replicarse. Las opciones son un almacén consistente, enrutar cada firmante a una autoridad de nonce o diseñar operaciones idempotentes que toleren duplicados.
Una caché local por proceso sólo ofrece protección parcial y debe declararse como tal. Las pruebas envían el mismo mensaje en paralelo a nodos diferentes y verifican que el acta se cargue como máximo una vez.
La propiedad que buscamos
Una implementación correcta no se resume en “la firma validó”. La secuencia es: validar contrato, digest, firma, tiempo, nonce, autorización e idempotencia antes del efecto.
La afirmación comprobable es: un aviso de multa firmado y capturado no puede ejecutarse otra vez dentro ni fuera de su ventana bajo los escenarios distribuidos probados. Esa propiedad requiere criptografía y estado, no sólo un encabezado.
Metodología
- Alcance
- Vectores sintéticos de RFC 9421 que alteran método, destino, cuerpo, tiempos y nonce para observar aceptación o rechazo antes de ejecutar efectos.
- Unidad de análisis
- Una petición HTTP ficticia, su base de firma, parámetros temporales, nonce y resultado de verificación o consumo.
- Cobertura
- RFC vigentes consultados el 14 de agosto de 2026; el algoritmo criptográfico y la distribución de claves deben definirse en el perfil de cada integración.
Limitaciones
- La guía no entrega un perfil interoperable completo ni reemplaza revisión criptográfica, rotación de claves y modelado de amenazas.
- Un control anti-replay local puede fallar en despliegues distribuidos si los nodos no comparten estado o particionan la autoridad del nonce.
Fuentes
- RFC 9421 — HTTP Message Signatures — RFC Editor (consultada el )
- RFC 9530 — Digest Fields — RFC Editor (consultada el )
- RFC 8446 — The Transport Layer Security Protocol Version 1.3 — RFC Editor (consultada el )
- RFC 9110 — HTTP Semantics — RFC Editor (consultada el )
- RFC 8941 — Structured Field Values for HTTP — RFC Editor (consultada el )
Preguntas frecuentes
¿TLS vuelve innecesaria una firma HTTP?
No siempre. TLS protege el canal entre extremos, mientras una firma de mensaje puede autenticar componentes y atravesar determinadas arquitecturas; la aplicación todavía debe controlar duplicados y autorización.
¿El timestamp por sí solo impide un replay?
No. Limita la ventana, pero una petición puede repetirse varias veces dentro de ella. Un nonce o identificador único consumido atómicamente permite detectar la repetición.
¿Firma e idempotencia son la misma defensa?
No. La firma autentica el mensaje y el nonce ayuda contra replays; la idempotencia define qué resultado obtiene un reintento legítimo. Su almacenamiento puede coordinarse, pero los contratos son distintos.
Notas relacionadas
Webhooks de nuevas multas: idempotencia, reintentos y trazabilidad
Un webhook confiable puede llegar más de una vez, demorarse o fallar después de ser procesado. El diseño debe deduplicar eventos, reintentar con límites y conservar evidencia de punta a punta.
Timeout no significa “sin multas”: cómo informar resultados parciales en una integración
Cuando una fuente no responde, el resultado es parcial o indeterminado, nunca cero. Un contrato explícito permite reintentar, alertar y decidir sin producir falsos negativos.
Códigos estables para jurisdicciones: por qué el nombre visible no alcanza
Un nombre puede cambiar de abreviatura, tilde o formato. Una integración confiable separa el identificador canónico, el nivel territorial, el nombre mostrado y el organismo emisor.