Mensaje de error
dkim=fail (body hash did not verify)
También se muestra como
- dkim=neutral (body hash did not verify)
mailauth escribe `dkim=fail (body hash did not verify)` en modo estricto y `dkim=neutral (body hash did not verify)` en su modo permisivo predeterminado (ambos reproducidos con 8.0.1). OpenDKIM notifica la misma situación como `dkim=fail reason="signature verification failed"` (reproducido con 2.11.0).
DKIM verifiers (Gmail, mailauth, Rspamd…) — Authentication-Results after the body changed in transit
Qué significa
La etiqueta `bh=` de la firma DKIM contiene un hash del cuerpo del mensaje tal como lo firmó el remitente. El receptor calculó el hash del cuerpo que recibió (después de la canonicalización) y obtuvo otro valor, así que el cuerpo cambió por el camino. El problema ni siquiera era la firma de los encabezados: el RFC 6376 hace de una discrepancia del hash del cuerpo un fallo permanente. Los culpables clásicos son los pies de página de las listas de correo, los avisos legales y las pasarelas de seguridad que reescriben enlaces.
Por qué ocurre
Se añadió un pie de página o un aviso legal
frecuenteLas listas de correo (pie de página para cancelar la suscripción), los avisos legales corporativos que añade una pasarela de salida o las líneas «Sent from…» que añaden los servidores de retransmisión cambian el cuerpo canonicalizado.
Una pasarela de seguridad reescribió el cuerpo
frecuenteLa reescritura de enlaces (Safe Links, URL Defense), la eliminación de adjuntos o la inserción de avisos por parte de filtros de entrada o de salida.
Cambió la codificación de transferencia MIME
ocasionalUn servidor de retransmisión sin 8BITMIME convierte el contenido de 8 bits a quoted-printable o base64. El texto decodificado es idéntico; los bytes firmados, no.
El firmante calculó el hash con otros finales de línea
ocasionalUn código de firma que calcula el hash con finales de línea LF mientras el mensaje se envía con CRLF (o con los espacios en blanco finales eliminados más tarde) produce un hash del cuerpo que nunca coincide con la canonicalización `simple`.
Cómo solucionarlo
- 1.
Recalcular bh= por tu cuenta
Comparar el hash del cuerpo recalculado en la copia enviada y en la recibida te indica si la culpa es del firmante o de un servidor de retransmisión.
bash # Recompute bh= for relaxed body canonicalization and compare with the header's bh= value python3 - message.eml <<'EOF' import base64, hashlib, re, sys raw = open(sys.argv[1], "rb").read().replace(b"\r\n", b"\n") body = raw.split(b"\n\n", 1)[1] lines = [re.sub(rb"[ \t]+", b" ", l).rstrip(b" \t") for l in body.split(b"\n")] canon = b"\r\n".join(lines).rstrip(b"\r\n") + b"\r\n" print("computed bh=", base64.b64encode(hashlib.sha256(canon).digest()).decode()) EOF grep -o "bh=[^;]*" message.eml - 2.
Firmar después de cualquier modificación
Haz que el firmante DKIM sea el último paso de tu ruta de salida; para los intermediarios que no controlas, confía en ARC y en la alineación DMARC mediante SPF cuando sea posible.
text # Postfix: run content filters (disclaimers, antivirus) BEFORE the DKIM signing milter smtpd_milters = inet:127.0.0.1:10025, inet:127.0.0.1:8891 # ^ disclaimer milter ^ OpenDKIM (signs last)
Errores relacionados
dkim=fail reason="signature verification failed"OpenDKIM (Authentication-Results header added by the opendkim milter); mailauth reports the same as "bad signature"dkim=permerrorOpenDKIM (Authentication-Results); mailauth reports syntax errors as dkim=neutraldkim=fail reason="key not found in DNS"OpenDKIM (Authentication-Results); mailauth reports it as dkim=neutral (no key)