Mensagem de erro
dkim=fail (body hash did not verify)
Também aparece como
- dkim=neutral (body hash did not verify)
O mailauth grava `dkim=fail (body hash did not verify)` no modo estrito e `dkim=neutral (body hash did not verify)` no modo tolerante, que é o padrão (os dois reproduzidos com a versão 8.0.1). O OpenDKIM relata a mesma situação como `dkim=fail reason="signature verification failed"` (reproduzido com a versão 2.11.0).
DKIM verifiers (Gmail, mailauth, Rspamd…) — Authentication-Results after the body changed in transit
O que significa
A tag `bh=` da assinatura DKIM contém um hash do corpo da mensagem tal como o remetente o assinou. O receptor calculou o hash do corpo que recebeu (após a canonicalização) e obteve um valor diferente, então o corpo mudou no caminho. A assinatura dos cabeçalhos nem era o problema: a RFC 6376 define a divergência do hash do corpo como falha permanente. Os culpados clássicos são rodapés de listas de discussão, avisos legais e gateways de segurança que reescrevem links.
Por que acontece
Um rodapé ou aviso legal foi adicionado
comumListas de discussão (rodapé para cancelar a inscrição), avisos legais corporativos adicionados por um gateway de saída ou linhas “Sent from…” adicionadas por servidores de retransmissão alteram o corpo canonicalizado.
Um gateway de segurança reescreveu o corpo
comumReescrita de links (Safe Links, URL defense), remoção de anexos ou inserção de banners por filtros de entrada ou de saída.
A codificação de transferência MIME mudou
ocasionalUm servidor de retransmissão sem 8BITMIME converte conteúdo de 8 bits em quoted-printable ou base64. O texto decodificado é idêntico; os bytes assinados, não.
O signatário calculou o hash com outras terminações de linha
ocasionalUm código de assinatura que calcula o hash com terminações de linha LF enquanto a mensagem é enviada com CRLF (ou tem os espaços em branco no fim das linhas removidos depois) gera um hash do corpo que nunca corresponde com a canonicalização `simple`.
Como corrigir
- 1.
Recalcular o bh= por conta própria
Comparar o hash do corpo recalculado na cópia enviada e na cópia recebida mostra se a culpa é do signatário ou de um servidor de retransmissão.
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.
Assinar depois de todas as modificações
Faça do signatário DKIM a última etapa do seu caminho de saída; para intermediários que você não controla, conte com o ARC e com o alinhamento DMARC via SPF sempre que possível.
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)
Erros 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)