How DKIM Signing Works
DKIM (DomainKeys Identified Mail) uses asymmetric cryptography — a public/private key pair — to sign outgoing email and allow receivers to verify that signature.
The process works as follows:
At the sending side (your mail server or ESP):
- When a message is ready to send, the signing server selects specific message headers and the message body (or a portion of it) to include in the signature.
- Those selected elements are hashed using a canonicalisation algorithm (typically
relaxed/relaxed, which tolerates minor whitespace changes). - The hash is encrypted with the private key — which only the signing server holds.
- The resulting signature is added to the message as a
DKIM-Signatureheader.
At the receiving side:
- The receiving mail server reads the
DKIM-Signatureheader and extracts thed=(signing domain) ands=(selector) values. - It constructs the selector DNS name:
<selector>._domainkey.<domain>and queries for the TXT record at that location. - The TXT record contains the public key for that selector.
- The receiver uses the public key to decrypt the signature and recover the original hash.
- It independently computes the hash of the same headers and body.
- If the two hashes match, the signature is valid — the message was signed by whoever holds the private key for that selector, and the signed content has not been modified.
DKIM SIGNING AND VERIFICATION FLOW
SENDER RECEIVER
────── ────────
Message + Headers Incoming Message
│ │
▼ ▼
Hash selected headers Read DKIM-Signature header
+ body with private key → extract d= and s=
│ │
▼ ▼
Add DKIM-Signature header ──────► DNS query: s._domainkey.d (TXT)
to outgoing message │
▼
Retrieve public key
│
▼
Decrypt signature → expected hash
Compute hash of headers + body
│
▼
Hashes match? → DKIM=pass
Hashes differ? → DKIM=fail
The DKIM-Signature header that travels with the message looks like this:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=example.com; s=mail2024;
h=from:to:subject:date:message-id:content-type;
bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
b=abc123...base64encodedSignature...==
The key fields: d= is the signing domain, s= is the selector (used to look up the public key), h= lists which headers were included in the signature, bh= is the hash of the message body, and b= is the actual signature value.
The DKIM DNS Record: Selector and Structure
The DKIM public key is published as a DNS TXT record at a predictable location:
<selector>._domainkey.<domain>
Examples:
mail2024._domainkey.example.com— selector namedmail2024google._domainkey.example.com— Google Workspace's default selectors1._domainkey.example.com— SendGrid's typical selector format
The selector name is chosen by whoever generates the key pair — your mail server software, your ESP, or you. It can be any string of letters, numbers, and hyphens. The selector has no inherent meaning; it's a lookup key that connects the signature in the message to the right public key in DNS.
A DKIM TXT record looks like this:
mail2024._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQ..."
The p= value is the Base64-encoded public key — typically RSA (2048-bit recommended, 1024-bit minimum per Google/Yahoo requirements) or Ed25519.
DKIM Record Tags Explained
| Tag | Meaning | Values | Notes |
|---|---|---|---|
v= | Version | DKIM1 | Required; always DKIM1 |
k= | Key type | rsa, ed25519 | Default is rsa if omitted |
p= | Public key (Base64) | Base64-encoded key data | Required; empty p= revokes the key |
h= | Acceptable hash algorithms | sha256, sha1 | Omit to allow all; sha1 deprecated |
t= | Flags | y (testing), s (strict) | y = testing mode (receivers should not use for authentication decisions); s = i= domain must exactly match d= |
n= | Notes | Freeform text | Human-readable; ignored by verifiers |
The most common record uses only v=, k=, and p=. The t=y testing flag is useful when initially configuring a new selector — it signals that receivers should not treat validation failures as authentication failures during your testing phase.
ℹ️ Tip: An empty
p=value (p=) is the standard way to revoke a DKIM key. When a receiver looks up a selector and findsp=, it treats any message signed with that selector as having failed authentication. This is the recommended approach for retiring a compromised or rotated key.
Setting Up DKIM: The Standard Workflow
If your DNS and mail are managed by a single provider
Most hosted mail providers (Google Workspace, Microsoft 365) generate the key pair internally and provide you with a CNAME or TXT record to add to your DNS zone. The private key never leaves their infrastructure.
Google Workspace:
- Go to Admin Console → Apps → Google Workspace → Gmail → Authenticate email
- Select your domain, generate a new record
- Copy the TXT record value and publish it at
google._domainkey.yourdomain.com - Wait for DNS propagation, then click "Start authentication"
Microsoft 365:
- Go to Microsoft 365 Defender (security.microsoft.com) → Email & Collaboration → Policies & Rules → Threat policies → Email authentication settings → DKIM
- Select your domain and enable DKIM
- Microsoft provides two CNAME records (
selector1._domainkeyandselector2._domainkey) — publish both in your DNS zone - Once CNAMEs propagate, enable signing
If you're using a transactional ESP (SendGrid, Mailgun, Postmark, etc.)
ESPs generate the key pair and provide you with CNAME records pointing to their infrastructure. The CNAME approach means the ESP can rotate the underlying key without requiring DNS changes on your side.
; Example SendGrid CNAME-based DKIM setup
s1._domainkey.example.com. CNAME s1.domainkey.u12345678.wl123.sendgrid.net.
s2._domainkey.example.com. CNAME s2.domainkey.u12345678.wl123.sendgrid.net.
The CNAME record resolves to SendGrid's TXT record containing the current public key. When SendGrid rotates their keys, your CNAME continues to resolve to the updated key — no DNS action required on your part.
If you're managing your own mail server
Generate a key pair with your MTA's tooling:
# Generate a 2048-bit RSA key pair (OpenSSL)
openssl genrsa -out dkim_private.pem 2048
openssl rsa -in dkim_private.pem -pubout -out dkim_public.pem
# Extract just the public key value for the DNS record
openssl rsa -in dkim_private.pem -pubout -outform der 2>/dev/null | base64 | tr -d '\n'
Publish the public key in DNS:
mail2024._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=<base64-public-key>"
Configure your MTA (Postfix with opendkim, Exim, Haraka, etc.) to sign outgoing mail with the private key using selector mail2024 for domain example.com.
Multi-Selector Strategy: One Domain, Multiple Senders
One of DKIM's most important properties is that a single domain can have an unlimited number of active selectors simultaneously. This makes it possible for multiple different sending systems to sign with the same domain without sharing keys.
A typical production setup might look like:
; Google Workspace — transactional and internal mail
google._domainkey.example.com. CNAME [Google's DKIM record]
; SendGrid — marketing email
s1._domainkey.example.com. CNAME [SendGrid's DKIM record]
s2._domainkey.example.com. CNAME [SendGrid's DKIM record]
; Postmark — transactional notifications
pm._domainkey.example.com. CNAME [Postmark's DKIM record]
; Zendesk — support email
zendesk1._domainkey.example.com. CNAME [Zendesk's DKIM record]
; Self-hosted server — internal tooling
server2024._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=..."
Each selector is independent. Rotating the server2024 key doesn't affect Google Workspace or SendGrid. Removing the zendesk1 selector revokes DKIM for Zendesk without affecting any other sender.
Keep a record of every active selector and which sending system it belongs to. This inventory is essential for:
- Knowing which selectors to revoke when offboarding a vendor
- Understanding DMARC aggregate reports when unexpected selectors appear
- Auditing your authentication surface for selectors that shouldn't exist
DKIM Key Rotation: Why, When, and How
Why rotate DKIM keys?
DKIM private key compromise allows an attacker to sign arbitrary email as your domain — creating perfectly authenticated phishing messages that pass DKIM verification. Key rotation limits the exposure window: even if a key is compromised, it's only valid until the next rotation.
Beyond security, Google's and Yahoo's bulk sender requirements specify a minimum key size of 1024 bits, with 2048 bits recommended. Many organisations with older DKIM setups have 1024-bit keys that should be upgraded.
When to rotate
- Annually as a routine practice for self-managed keys
- Immediately if you suspect a private key has been exposed (server breach, former employee with key access, key stored insecurely)
- On vendor changes — when switching ESPs or removing a sender, retire their selector
- On key size upgrade — moving from 1024-bit to 2048-bit RSA, or adopting Ed25519
How to rotate without disrupting mail flow
The risk in DKIM key rotation is a window where messages signed with the new key are in transit while the old DNS record is still cached, or vice versa. The safe rotation sequence avoids this.
SAFE DKIM KEY ROTATION SEQUENCE
Step 1: Generate new key pair
→ New private key stored on signing server (NOT yet active for signing)
→ New selector name chosen (e.g., mail2025 replacing mail2024)
Step 2: Publish new selector in DNS
mail2025._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=<new-public-key>"
(Keep mail2024 active — both selectors now exist simultaneously)
Step 3: Wait for DNS propagation
→ Minimum TTL of the new record (typically 1 hour)
→ Verify: dig mail2025._domainkey.example.com TXT
Step 4: Switch signing to new key
→ Update MTA/ESP configuration to sign with mail2025 / new private key
→ All new outbound messages now signed with mail2025
Step 5: Wait for in-flight messages to clear
→ Allow 24–48 hours for any messages signed with mail2024 still in transit
→ Messages signed with mail2024 still verify correctly during this window
Step 6: Revoke old selector
→ Either: delete mail2024._domainkey.example.com TXT record
→ Or: set p= to empty: "v=DKIM1; k=rsa; p=" (explicit revocation)
⚠️ Warning: Never delete the old selector record before switching signing to the new key. Messages already signed and in transit will fail verification if the old public key disappears from DNS before they are delivered. The overlap period (Steps 2–5) is essential.
For CNAME-based ESP selectors, the rotation is handled by the ESP — your DNS CNAME continues to resolve to their updated key automatically. Check with your ESP about their rotation schedule and notification process.
DKIM and DMARC Alignment
DKIM by itself provides signing and verification, but doesn't prevent an attacker from signing with a completely different domain. DMARC alignment is what ties DKIM to the visible From: header.
DKIM alignment requires the d= domain in the DKIM signature to match the domain in the From: header:
- Relaxed alignment (default,
adkim=r): The organisational domain must match.d=mail.example.comaligns withFrom: user@example.combecause both share the organisational domainexample.com. - Strict alignment (
adkim=s): The domains must match exactly.d=mail.example.comdoes not align withFrom: user@example.com— onlyd=example.comwould satisfy strict alignment.
For DMARC to pass via DKIM, you need both: a valid DKIM signature, and that signature's d= domain must align with the From: domain under your DMARC policy's alignment mode.
This is why DKIM signing at the d=yourmaindomain.com level — rather than d=theirESP.com — is critical for DMARC enforcement. An ESP that signs only with their own domain (e.g., d=sendgrid.net) provides DKIM authentication but not DMARC alignment for yourdomain.com.
Common DKIM Failures and What They Mean
dkim=fail (body hash did not verify)
The message body was modified after signing. Common causes: mailing lists that add footers, spam filters that modify content, or forwarding services that alter messages. DKIM is deliberately sensitive to body modification — even a single added character in the message body will invalidate the signature.
DKIM's body canonicalisation mode (c=relaxed/relaxed) tolerates whitespace changes but not content additions. Mailing lists that append footers will typically break DKIM for forwarded messages — this is expected behaviour.
dkim=fail (signature verification failed)
The signature itself couldn't be verified. Possible causes: the private key used for signing doesn't match the public key in DNS (key mismatch after a rotation that wasn't coordinated), the DKIM-Signature header was modified in transit, or the selector record has been removed or revoked.
Diagnosis: Retrieve the selector from the DKIM-Signature header (s= field), then query DNS for that selector: dig <selector>._domainkey.<domain> TXT. If the record is missing or shows p= (revoked), that's the cause.
dkim=temperror or dkim=permerror
temperror means the receiver couldn't look up the DKIM DNS record (DNS timeout or SERVFAIL) — likely transient. permerror means the DKIM record is malformed or the selector doesn't exist. Check the record syntax and confirm the TXT record is published.
dkim=none
The message has no DKIM signature at all. The sending system isn't configured to sign, or the signing configuration is for a different domain/selector than the From: address.
How to Verify a DKIM Record
Via dig
# Look up a DKIM selector record
dig TXT google._domainkey.example.com +short
# If the selector uses CNAME indirection
dig CNAME s1._domainkey.example.com +short
# Then follow the CNAME:
dig TXT s1.domainkey.u12345678.wl123.sendgrid.net +short
# Check for multiple selectors
for selector in google s1 s2 pm zendesk1 mail2024 mail2025; do
result=$(dig TXT "${selector}._domainkey.example.com" +short 2>/dev/null)
if [ -n "$result" ]; then
echo "${selector}: FOUND"
else
echo "${selector}: not found"
fi
done
Via the DKIM Checker tool
Use our DKIM Checker to look up and validate any DKIM selector for any domain — it checks the record syntax, key size, and algorithm, and flags common issues like missing p= values, undersized keys, and t=y testing mode left enabled in production.
Checking a received message's DKIM result
Every mail server that processes a message adds an Authentication-Results header recording the DKIM (and SPF and DMARC) outcome. To inspect DKIM results on received messages:
; In Gmail: open message → three-dot menu → "Show original"
; In Outlook: File → Properties → Internet headers
Authentication-Results: mx.google.com;
dkim=pass header.i=@example.com header.s=mail2024 header.b=abc123;
spf=pass (google.com: domain of bounce@example.com designates 198.51.100.1 as permitted sender);
dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com
Look for dkim=pass with the correct header.i=@yourdomain.com — this confirms DKIM alignment with your From: domain, not just signing by an ESP's domain.
Post-setup verification checklist
- Selector DNS TXT record resolves correctly:
dig TXT <selector>._domainkey.<domain> - Key size is 2048-bit or larger (check
p=length — 2048-bit RSA keys produce ~350+ character Base64 strings) -
t=ytesting flag removed from production record - At least one test message sent and
Authentication-Resultsshowsdkim=pass - DMARC aggregate reports show DKIM passing for the configured selector
- Selector inventory documented (which sender uses which selector)
Frequently Asked Questions
Q: Does DKIM protect against phishing emails that spoof my domain?
DKIM alone doesn't — a phisher simply won't sign their message with your domain's DKIM key (they don't have the private key). But DKIM becomes a phishing defence when combined with DMARC: once you enforce p=reject, any message claiming to be from your domain that lacks a valid DKIM signature (or a valid SPF alignment) will be rejected by receiving servers. The combination of DKIM + DMARC is the protection; DKIM alone is just authentication evidence.
Q: Does DKIM survive email forwarding?
DKIM signatures survive forwarding as long as the message content isn't modified. Simple forwarding (reusing the original message unaltered) typically preserves DKIM. Forwarding that adds a footer, rewrites headers, or re-encodes the message breaks DKIM. This is why SPF almost always breaks in forwarding scenarios (the forwarding server's IP isn't in your SPF), but DKIM often survives — making DKIM the preferred DMARC alignment mechanism for domains whose mail is frequently forwarded.
Q: What's the difference between 1024-bit and 2048-bit DKIM keys?
Key length determines resistance to factorisation attacks — longer keys are harder to crack. 1024-bit RSA keys are now considered insufficiently secure by modern cryptographic standards; Google and Yahoo's bulk sender requirements specify 1024-bit as the minimum but recommend 2048-bit. 2048-bit keys should be the standard for new setups. The practical difference for deliverability: Google may reject DKIM signatures from 1024-bit keys in future enforcement updates. If your keys are 1024-bit, rotating to 2048-bit should be a near-term priority.
Q: Can I use the same DKIM key for multiple domains?
Technically yes — nothing prevents publishing the same public key under selector records for multiple domains. But it's poor security practice: a single compromised private key then undermines authentication for all those domains. The standard approach is separate key pairs per domain, and per sending system within each domain.
Q: My ESP set up DKIM for me using CNAMEs. Do I need to do anything for key rotation?
For CNAME-based DKIM, the ESP manages key rotation transparently — your DNS CNAME continues to point to their infrastructure, and they update the underlying public key on their side. You typically don't need to take any action, but you should verify that your ESP performs regular key rotation (ask them, or check their documentation). Some ESPs rotate annually; others rotate less frequently. If your ESP uses direct TXT records rather than CNAMEs, you'll need to coordinate rotation with them manually.
Q: How long does DKIM propagation take after adding a new selector record?
DKIM selector records are standard DNS TXT records and propagate on the same timeline as any other DNS change — typically minutes to an hour for most resolvers, with full global propagation within 24–48 hours depending on the record's TTL. Set a low TTL (300–900 seconds) on new selector records initially so that any corrections propagate quickly. Once the record is stable and verified, you can raise the TTL.
Next Steps
Use our DKIM Checker to look up and validate any selector for your domain — confirming the record exists, the key size meets requirements, and testing mode isn't left enabled in production.
For the full DMARC alignment picture — how DKIM d= alignment interacts with your DMARC policy, and how to read DMARC aggregate reports that show per-selector pass/fail rates — see our DMARC Policy Enforcement guide.
For Google's and Yahoo's specific requirements around DKIM key size and signing configuration for bulk senders, see our Google & Yahoo Bulk Sender Requirements guide.
Browse all email authentication guides on DNSnexus for related topics.