DKIM Debugger — débogueur DKIM
Collez la source brute d’un e-mail, en-têtes et corps compris. Le débogueur la canonicalise exactement comme le prescrit la RFC 6376, montre chaque modification, calcule les condensats du corps et des en-têtes, récupère les clés publiques via DNS-over-HTTPS à votre demande et identifie précisément pourquoi une signature échoue : un pied de page ajouté par une liste de diffusion, un [tag] ajouté au Subject, un corps réencodé, une clé qui a fait l’objet d’une rotation.
Votre message ne quitte jamais ce navigateur. Seuls les noms de clés auxquels renvoient les signatures (sélecteur._domainkey.domaine) sont envoyés au résolveur DNS-over-HTTPS de Cloudflare, et uniquement lorsque vous appuyez sur le bouton qui les recherche.
Le message reste dans ce navigateur : il est analysé et haché ici, et n’est jamais envoyé nulle part.
What a DKIM signature covers
A DKIM signature (RFC 6376) is a header field, DKIM-Signature, that a sending server adds to a message. It does not sign the message as a whole. It signs two hashes. The first is the hash of the body, written into the signature as bh=. The second is the hash of a chosen set of header fields — the ones named in h= — followed by the DKIM-Signature field itself with its b= value left empty. That second hash is what the private key signs, and the result is b=.
A verifier repeats the work. It finds the public key in DNS at selector._domainkey.domain (the s= and d= tags), recomputes both hashes from the message it received, and checks the signature. If the body hash differs, the body changed. If the body hash matches but the signature does not verify, either a signed header field changed or the key in DNS is not the one that signed.
Canonicalization: what may change in transit
Mail servers rewrite messages in small ways: they refold long header lines, change the case of header names, add or strip whitespace. To survive that, DKIM hashes a canonical form of the message instead of the raw bytes. The c= tag picks one of two algorithms for the header fields and one for the body.
- simple tolerates almost nothing. Header fields are hashed exactly as they are. The body only loses empty lines at its end, and an empty body becomes a single CRLF.
- relaxed lowercases header names, unfolds header values, reduces every run of spaces and tabs to one space and drops whitespace at the end of each line, in headers and body alike.
The debugger shows every one of these steps on your message. Each header field appears as received, with what canonicalization removes or rewrites marked, next to the exact canonical text that goes into the hash. The body is shown line by line the same way, with the empty lines at its end and anything after an l= limit flagged.
Why signatures break
Most failures come from an intermediary that changed the message after it was signed. The debugger does not stop at "body hash mismatch": it rebuilds what the signer probably saw and checks it against the hash in the signature. When the rebuilt data reproduces the signed hash exactly, the cause is confirmed, not guessed. It looks for:
- a footer appended by a mailing list, at the end of the body or just before the closing MIME boundary;
- a body re-encoded to quoted-printable or base64 by a relay, or SMTP dot-stuffing that was not undone;
- trailing whitespace added under
simplebody canonicalization; - a tag such as
[list]added to the Subject; - header names re-cased or lines refolded under
simpleheader canonicalization; - a Subject converted to or from RFC 2047 encoded-words;
- a header field added below the signed one, or instances reordered.
With an RSA key the debugger also recovers the digest that is inside the signature. If that digest differs from the header hash computed now, the key is the right one and the signed header fields changed. If the signature does not decrypt to a valid digest at all, the key in DNS is not the signer's — typically a rotated selector. You can paste the old key to confirm it.
A pass is not the whole story
A valid signature still has to be useful. The debugger checks the rules of RFC 8301: rsa-sha1 and RSA keys under 1024 bits must not be accepted, and keys under 2048 bits should be replaced. It verifies Ed25519 signatures of RFC 8463. It reports what an attacker could change without breaking the signature: header fields that are present but unsigned, a From field that is not over-signed, body text past an l= limit. It also tells you whether the signing domain is aligned with the From domain — a signature from an email service's own domain verifies, but does not count for DMARC (RFC 7489).
When the message carries an Authenticated Received Chain, the debugger validates it as well. The ARC viewer follows that chain hop by hop.
What runs in your browser
Parsing, canonicalization, both hashes, the RSA and Ed25519 checks and the failure analysis run in this page. The message is never uploaded. Opening an .eml file is better than pasting: a file keeps the exact bytes, while text copied from a mail client usually loses its CRLF line endings and any 8-bit characters, and the debugger warns when that has happened.
Only the public keys come from outside. When you press the button that looks up the keys, the page asks Cloudflare's resolver over DNS-over-HTTPS for the TXT records at the key names the signatures point to. Those names are public, and they are the only thing that is sent. You can skip DNS entirely and paste a key record or a PEM public key for each selector.
To publish a key of your own, the DKIM record generator creates the key pair in your browser and writes the DNS record.