The DKIM-Signature header carries everything a receiver needs to check it. Being able to read one turns a DKIM failure from a mystery into one of about four specific causes.
The header, annotated
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;d=example.com; s=sel1; t=1757635200;h=from:to:subject:date:message-id;bh=2jmj7l5rSw0yVb/vlWAYkK/YBwk=;b=dzdVyOfAKCdLXdJOc9G2q8LoXSlEniSbav+yuU4zGeeruD00lszZ...
d=— the signing domain. The domain taking responsibility. This is the tag that alignment will compare against the From header, so it is the most important one on the line.s=— the selector. Combined withd=it gives the DNS name of the public key:sel1._domainkey.example.com.a=— the algorithm.rsa-sha256in practice;rsa-sha1is deprecated by RFC 8301 and should be treated as a finding.c=— canonicalisation, header then body.h=— the list of headers covered. Anything not in this list is unsigned and can be changed or added in transit without breaking the signature.bh=— the body hash. Checked first, and separately from the signature.b=— the signature itself, over the headers inh=plus this header withb=emptied.
Verification is two checks, not one
This is the part worth remembering, because it tells you where a failure came from:
- The body hash. The receiver canonicalises the body, hashes it, and compares with
bh=. If this fails, the body changed in transit — and the signature is never even checked. - The signature. Over the headers listed in
h=. If the body hash matched but this fails, a signed header changed, or the key does not match the one that signed.
Good diagnostics report these separately. "Body hash did not verify" means something rewrote the message — a mailing list footer, a link-rewriting gateway, a disclaimer appender. "Signature did not verify" with a good body hash means a header problem or a key mismatch. Those are different investigations.
The h= tag, and what it leaves open
A signature only covers the headers it names. RFC 6376 §5.4 requires From and nothing else, so a minimal signature covering only from is valid and leaves the subject line free to be altered in transit without any signature breaking.
| Header in h= | Consequence |
|---|---|
from | Required. Without it the signature would assert nothing about who the message is from. |
subject | Strongly advisable. Otherwise the subject is modifiable in transit. |
to, date, message-id | Usual, and sensible. |
A header listed twice | Over-signing: it signs the absence of a second copy, so an intermediary cannot add one. |
Over-signing, briefly
Listing a header name in h= more times than it appears in the message signs the fact that there is no further copy. Without it, an intermediary can prepend a second Subject: header; the original is still signed and still verifies, while many mail clients display the new one. Most sending platforms do this for you and it is not something you normally configure.
More than one signature
A message may carry several DKIM-Signature headers, and this is normal rather than suspicious. A platform commonly signs with its own domain while also signing with yours. A receiver evaluates each independently, and for DMARC purposes it only takes one valid signature whose d= aligns with the From header.
This is why "DKIM passed" is an incomplete statement. The useful question is always which domain passed, and that is the d= tag.