Resources / Authentication
DKIM Deep Dive (RFC 6376)
DKIM signs a message so a domain can take cryptographic responsibility for it. This is the full RFC 6376 picture: selectors, the signature and key tags, simple vs relaxed canonicalization, the l= body-length trap, key rotation, and the crypto updates from RFC 8301 and RFC 8463.
Last checked: June 21, 2026
DKIM (DomainKeys Identified Mail) lets a domain “claim some responsibility for a message by associating the domain with the message via a cryptographic signature” (RFC 6376 §1). Unlike SPF, it does not care about the connecting IP. It cares about a signature, computed over chosen headers and the body, that a receiver can verify using a public key the signing domain publishes in DNS. That difference - signature over content versus check on an IP - is why DKIM survives forwarding where SPF does not.
The 60-second version
- The signer adds a
DKIM-Signature:header. The two load-bearing tags ared=(the signing domain) ands=(the selector); together they form the DNS lookups._domainkey.d(RFC 6376 §3.1, §3.6.2.1). - A valid signature proves only two things: the
d=domain signed it, and the signed parts were not modified in transit. Nothing more (RFC 6376 §1.5). - A signature failure does not force rejection (RFC 6376 §1).
c=selects canonicalization. Default issimple/simple; most senders userelaxed/relaxedbecausesimpleis brittle (RFC 6376 §3.5, §3.4).l=(body length) is a footgun: it lets content be appended after the signed region. Avoid it.- No certificate authority is involved; the public key comes straight from the signer’s DNS (RFC 6376 §1.4).
Selectors, d=, and s=
A domain can have many keys live at once. DKIM subdivides the key namespace with selectors: the s= tag in the signature names which key, and the verifier looks it up under the _domainkey subtree (RFC 6376 §3.1).
DKIM-Signature: ... d=example.com; s=mar2026; ...
│ │
│ └── selector
└──────────────── signing domain (SDID)
DNS query: mar2026._domainkey.example.com (TXT record holding the public key)
Selector names may contain periods, which act as DNS label separators: for d=example.com and s=foo.bar, the query is foo.bar._domainkey.example.com (RFC 6376 §3.6.2.1). All keys live under the _domainkey subdomain, and the TXT RR for a given selector MUST be unique - multiple records for one selector gives undefined results (RFC 6376 §3.6.2.1).
The d= value is the Signing Domain Identifier (SDID), the mandatory output of DKIM and the domain a receiver treats as having taken responsibility (RFC 6376 §2.5). For DMARC, the DKIM-Authenticated Identifier is exactly this d= value (RFC 9989 §4.4.1).
The DKIM-Signature header tags
All defined in RFC 6376 §3.5. Tag values are case-sensitive unless noted.
| Tag | Required | What it is |
|---|---|---|
v= | REQUIRED | version; MUST be 1 |
a= | REQUIRED | signing algorithm, e.g. rsa-sha256 |
b= | REQUIRED | the base64 signature value |
bh= | REQUIRED | base64 hash of the canonicalized body |
d= | REQUIRED | signing domain (SDID); the domain queried for the key |
s= | REQUIRED | selector; with d= forms s._domainkey.d |
h= | REQUIRED | colon-separated list of signed header names; MUST NOT be empty |
c= | OPTIONAL | header/body canonicalization (default simple/simple) |
i= | OPTIONAL | AUID; its domain MUST equal or be a subdomain of d= |
l= | OPTIONAL | body length count - see the warning below |
q= | OPTIONAL | query method (default and only defined value dns/txt) |
t= | RECOMMENDED | signature creation time (Unix epoch) |
x= | RECOMMENDED | signature expiration (Unix epoch); MUST be greater than t= |
z= | OPTIONAL | diagnostic copy of selected headers at signing time |
The h= tag is worth dwelling on: it lists which headers are protected. Anything not in h= is unsigned and can be altered or added without breaking the signature. Sensible signers include From: (and DMARC effectively requires the From: to be signed for the DKIM identifier to be meaningful).
The published key record
The public key lives at <selector>._domainkey.<domain> as a TXT record (RFC 6376 §3.6.1).
mar2026._domainkey.example.com. 3600 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkq...QAB"
| Tag | Required | What it is |
|---|---|---|
v= | RECOMMENDED | version; MUST be DKIM1 if present, and MUST be the first tag; other values -> record discarded |
h= | OPTIONAL | acceptable hash algorithms (default: all) |
k= | OPTIONAL | key type (default rsa) |
n= | OPTIONAL | human notes |
p= | REQUIRED | base64 public key; an empty p= means the key is revoked |
s= | OPTIONAL | service type (default *; or email) |
t= | OPTIONAL | flags: y = testing mode, s = i= must not be a subdomain of d= |
Two facts to internalize: an empty p= is the revocation signal, and the t=y testing flag means verifiers “MUST NOT treat differently from unsigned email” (RFC 6376 §3.6.1). Leaving t=y on a production key effectively neuters it.
Canonicalization: simple vs relaxed
Mail is modified in transit in trivial ways - whitespace gets rewritten, lines get re-folded, a trailing blank line appears. Canonicalization decides how forgiving the signature is about that. There are two algorithms each for the header and the body, chosen by c=header/body; the default is simple/simple (RFC 6376 §3.4, §3.5).
| Algorithm | Header behavior | Body behavior |
|---|---|---|
| simple | no changes at all; header names not case-folded, whitespace untouched (§3.4.1) | ignores empty lines at end of body; folds trailing *CRLF to one CRLF; empty body canonicalizes to a single CRLF (§3.4.3) |
| relaxed | lowercases header names, unfolds continuations, collapses WSP runs to one SP, strips trailing WSP and WSP around the colon (§3.4.2) | strips trailing-of-line whitespace, collapses internal WSP runs to one SP, ignores trailing empty lines (§3.4.4) |
simple is strict to the point of fragility: a single mail server that adjusts whitespace can break a simple signature. relaxed/relaxed tolerates the cosmetic rewrites that normal relays perform, which is why it is the common production choice. Neither tolerates a content change inside the signed region - that is the point.
The l= body-length trap
l= tells the verifier how many octets of the body are covered by the hash. Anything past that count is unsigned. RFC 6376 §3.5 flags this directly: misuse “allows appending content.” An attacker (or a careless intermediary) can add text, HTML, or an entire trailing message after the signed region and the signature still validates over the original l= octets. Unless you have a very specific reason and understand the exposure, do not set l=; sign the whole body.
Key rotation (and why you never reuse a selector)
Rotation is just publishing a new key under a new selector and moving signing to it, then retiring the old one. The spec is blunt about the wrong way to do it: reusing a selector with a new key “makes it impossible to tell forged messages from messages that failed due to key rotation,” and “signers are ill-advised to reuse selectors for new keys” (RFC 6376 §3.1).
A safe rotation looks like:
1. Publish new key: mar2026._domainkey.example.com (v=DKIM1; p=<new>)
2. Switch signing to s=mar2026 once DNS has propagated.
3. Leave the old selector published long enough for in-flight mail to verify.
4. Revoke the old key by setting its p= to empty, or remove the record.
New selector per rotation, overlap during propagation, and revoke (empty p=) rather than silently delete if you want the revocation to be explicit.
Algorithms and the crypto updates
RFC 6376 itself defines two signing algorithms, rsa-sha1 and rsa-sha256, and says signers MUST implement and SHOULD sign with rsa-sha256, while verifiers MUST implement both (RFC 6376 §3.3). Its original key-size baseline was RSA keys of at least 1024 bits for long-lived keys (RFC 6376 §3.3.3).
Two later RFCs update this:
- RFC 8301 updates DKIM’s cryptographic algorithm and key-usage requirements, raising the minimum acceptable RSA key length above the original 1024-bit baseline and tightening hash-algorithm guidance. (We are deliberately not stating its exact threshold here; see the note at the end of this page.)
- RFC 8463 adds a new signature method, Ed25519-SHA256 (
ed25519-sha256), as an alternative to RSA (confirmed from RFC 6376’s “Updated by” record). Ed25519 keys are far shorter than RSA keys for comparable strength, which also helps them fit in a DNS TXT record without splitting.
Practically: sign with rsa-sha256 (or Ed25519 where your platform and receivers support it), use a comfortably modern RSA key length, and do not sign with rsa-sha1.
What DKIM survives that SPF does not
This is the reason DMARC accepts DKIM as an alternative path. SPF checks the connecting IP; the moment a message is forwarded or relayed, the IP changes and SPF fails for your domain. DKIM checks a signature over the message content, so it keeps validating as long as the signed parts are not modified (RFC 6376 §1.5; the forwarding/IP failure mode is described in RFC 8617 §1, §2).
The flip side: DKIM breaks when an intermediary changes signed content - a mailing list that rewrites the Subject: or appends a footer alters bytes inside the signed region, and the signature fails. So DKIM survives a plain forward but not a modifying list. That residual gap is exactly what ARC was built to bridge.
For DMARC, a message can carry multiple DKIM signatures, and DMARC passes if any DKIM-Authenticated Identifier (d=) aligns with the Author (From:) domain (RFC 9989 §4.4.1).
Common confusion / what does NOT change
- “A DKIM pass proves who wrote the email.” No. It proves the
d=domain signed it and the signed bytes are intact (RFC 6376 §1.5). - “DKIM needs a CA / a paid certificate.” No. The key is published in your own DNS; there is no certificate authority (RFC 6376 §1.4).
- “A DKIM failure should bounce the mail.” Not on its own; RFC 6376 §1 says failure does not force rejection. Rejection policy is DMARC’s job.
- “Set
l=to be tolerant of footers.” That is the appending vulnerability. Don’t. - “Reuse one selector forever.” That makes rotation and forgery indistinguishable (RFC 6376 §3.1).
- “
t=yis harmless.” On a live key it tells verifiers to treat your signed mail as unsigned.
What Egressif does
We sign with aligned DKIM on your domain using a modern key, so that DMARC has a path that survives forwarding even when SPF cannot. We sign the headers that matter (including From:), avoid l= entirely, and rotate keys by publishing a fresh selector and revoking the old key with an empty p= rather than reusing a name. Because DKIM is the half of DMARC that holds up across relays and lists, we treat a broken or t=y key as a real incident, not a cosmetic one.
Note on RFC 8301: our verified research confirms the original RFC 6376 §3.3.3 baseline of 1024-bit RSA and that RFC 8301 raised the minimum, but the exact updated key length and the precise hash-deprecation wording were not independently verified against RFC 8301’s text at author time, so this page does not assert a specific number for them.
Related references
- Email Authentication: SPF, DKIM, DMARC, ARC, BIMI SPF, DKIM, and DMARC are not interchangeable, and none of them on their own tells a receiver a message is safe. This is the map: what each layer checks, what a pass actually proves, and how alignment, ARC, and BIMI sit on top.
- DMARC in 2026 (RFC 9989, 9990, 9991) The RFC most "DMARC explained" articles still cite is obsolete. In May 2026 DMARC was re-issued as three Standards-Track RFCs. Here is everything that changed - tags, the Tree Walk, reporting, and the new p=reject guidance - in plain language, with records you can copy.
- SPF Deep Dive (RFC 7208) SPF authorizes which hosts may use your domain in the SMTP envelope. This is the full RFC 7208 picture: record format, every mechanism and qualifier, the hard 10-lookup limit that breaks records, the result codes, and the mistakes that quietly cause permerror.
- ARC: Authenticated Received Chain (RFC 8617) ARC preserves a message's authentication result across the intermediaries that break SPF and DKIM. This is the RFC 8617 picture: the three header fields, how a chain is built and validated, the chain-validation states, and the honest limits - ARC is advisory, not a pass.
- BIMI: Logos, DMARC, and Mark Certificates BIMI puts a brand logo next to authenticated mail, but it authenticates nothing itself - it rides on enforced DMARC. This covers the prerequisites, the SVG Tiny PS logo, VMC and CMC mark certificates, the DNS record, and the honest provider-support reality.
Tell us what you run today.
Domains, rough volume, current providers, and what hurts. You will get a straight answer on fit, and a real number, in one conversation.