DKIM — DomainKeys Identified Mail
Why This RFC Exists
SPF verifies that a message came from an authorized IP address, but it says nothing about the message content. A message could pass SPF, then be modified by a compromised relay. SPF also breaks when mail is forwarded, because the sending IP changes.
DKIM solves both problems. By attaching a cryptographic signature to the message itself, it provides a domain-level identity assertion that survives forwarding (the signature travels with the message) and guarantees content integrity (any modification invalidates the signature).
RFC 6376, published in 2011, is the current DKIM specification. It obsoleted RFC 4871 and introduced improvements to canonicalization, key management, and signature semantics. It remains the foundation of modern email authentication alongside SPF and DMARC.
How It Works
Signing (Sender Side)
- The sending mail server (or a signing agent upstream) selects which headers and the body to sign.
- It canonicalizes the selected content using either
simpleorrelaxedalgorithms to normalize whitespace and casing. - It computes a hash of the canonicalized body, then a hash of the selected headers plus the body hash.
- It signs the header hash using the domain's private key (RSA or Ed25519).
- It adds a
DKIM-Signatureheader to the message containing the signature, the signing domain (d=), the selector (s=), and metadata about what was signed.
Verification (Receiver Side)
- The receiver extracts the
d=(domain) ands=(selector) values from theDKIM-Signatureheader. - It queries DNS for the public key at
<selector>._domainkey.<domain>. - It re-canonicalizes the signed headers and body using the same algorithm specified in the signature.
- It verifies the signature against the public key. If valid, the result is
pass.
Example DKIM-Signature Header
DNS Public Key Record
Key Technical Details
Canonicalization
Email can be subtly modified in transit (trailing whitespace stripped, headers re-folded). Canonicalization normalizes the content before hashing so that benign changes don't break the signature. Two algorithms are available, specified separately for headers and body:
| Algorithm | Headers | Body |
|---|---|---|
simple |
No changes except trailing whitespace on the header value | No changes except trailing empty lines |
relaxed |
Lowercases header names, unfolds lines, compresses whitespace | Compresses whitespace, removes trailing whitespace per line |
The most common setting is c=relaxed/relaxed, which tolerates the most common in-transit modifications.
Key Types
RFC 6376 defined RSA signatures. RFC 8463 later added Ed25519 support. RSA keys should be at least 2048 bits; 1024-bit keys are considered weak and are rejected by some receivers. Ed25519 keys are much smaller (44 characters in DNS) and faster to verify.
Selectors
The selector (s= tag) lets a domain publish multiple DKIM keys simultaneously. This is essential for key rotation: publish a new key under a new selector, start signing with it, then remove the old selector's DNS record after a transition period.
The l= Tag (Body Length Limit)
The optional l= tag limits how many bytes of the body are signed. This was intended to allow mailing lists to append footers without breaking signatures. In practice, it creates a security vulnerability: an attacker can append malicious content after the signed portion. Most security-conscious implementations avoid using l=.
Header Signing
The h= tag lists which headers are included in the signature. Best practice is to sign at least: From, To, Subject, Date, Message-ID, MIME-Version, and Content-Type. The From header is required by specification. Signing a header that doesn't exist prevents it from being added after signing (an important anti-replay measure).
Common Mistakes
- Using 1024-bit RSA keys: These are cryptographically weak by modern standards. Gmail and other major receivers may downgrade trust. Always use 2048-bit RSA or Ed25519.
- Not rotating keys: DKIM private keys should be rotated periodically (every 6-12 months). Selectors make this seamless — publish the new key, switch signing, retire the old key.
-
Signing with a misaligned domain: For DMARC to pass via DKIM, the
d=domain in the signature must align with theFrom:header domain (exact match or subdomain, depending on DMARC policy). If your ESP signs asd=esp.com, DMARC alignment fails unless you configure custom DKIM signing. -
Over-signing vs. under-signing headers: Not signing important headers (like
Subject) lets attackers modify them. Over-signing headers that intermediaries legitimately add can cause false failures. - DNS record propagation lag: After publishing a new DKIM key, wait for DNS propagation before signing with the new selector. A signature referencing a nonexistent public key will fail verification.
-
Using the
l=body length tag: This allows unsigned content to be appended to the message. Avoid it.
Deliverability Impact
- Foundation for DMARC: DKIM alignment is one of the two paths to DMARC pass (the other being SPF alignment). Since DKIM survives forwarding while SPF does not, DKIM is often the more reliable authentication path.
-
Reputation binding: DKIM ties messages to the signing domain (via the
d=tag). Mailbox providers use this to build domain reputation. Consistent DKIM signing builds positive reputation over time. - Required by major providers: Gmail and Yahoo require either SPF or DKIM to pass for all senders. Bulk senders (5,000+ messages/day to Gmail) must have both SPF and DKIM passing, plus a DMARC policy.
- Survives forwarding: Unlike SPF, a DKIM signature travels with the message. When mail is forwarded through mailing lists, .forward rules, or alias expansions, DKIM can still validate (provided the forwarding system doesn't modify signed content). This makes DKIM essential for mailing list compatibility.
- Content integrity: Beyond authentication, DKIM proves the message wasn't tampered with in transit. This protects against man-in-the-middle modifications and increases receiver trust.