Learn/ Docs/ Email/ Dkim

email

DKIM (DomainKeys Identified Mail)

How cryptographic signatures prove an email hasn't been tampered with

In 2012, a vulnerability researcher demonstrated that he could send emails as any @gmail.com address and have them land in inboxes without a single warning. The trick was straightforward: Google’s DKIM signing key for Gmail was only 512 bits long. He factored it in about 72 hours using commodity hardware. With the private key in hand, he could sign messages that passed DKIM verification perfectly — Google’s own cryptographic seal, applied to forged messages.

Google rotated the key within days and upgraded to 2048-bit RSA. But the incident exposed a fundamental truth about DKIM: the system is only as strong as the keys behind it, and those keys live in plain sight, published in DNS for the world to read.

DKIM is the cryptographic layer of email authentication. Where SPF answers “did this message come from an authorized server?”, DKIM answers a different and equally important question: “has this message been tampered with since it was sent, and can the sending domain prove it?”

The Problem: Messages Can Be Altered in Transit

Email travels through multiple servers on its way from sender to recipient. Any of those intermediate servers — or any attacker with network access — could theoretically modify the message contents. Change an invoice amount, replace a link, alter instructions. SPF cannot detect this. SPF only validates that the sending server’s IP address was authorized; it says nothing about what happened to the message after it left.

DKIM solves this by attaching a cryptographic signature to every outgoing message. The signature covers specific headers and a hash of the message body. If anything is altered after signing, the signature will not verify. The recipient can confirm, cryptographically, that the message arrived exactly as the sender intended.

How DKIM Works

DKIM uses asymmetric cryptography — a private/public key pair. The process has two sides:

Signing (Sender Side)

  1. The sending mail server generates a hash of selected email headers (From, To, Subject, Date, etc.) and the message body
  2. It encrypts that hash using the domain’s private key (kept secret on the mail server)
  3. The resulting signature is added to the email as a DKIM-Signature header

Verification (Recipient Side)

  1. The receiving mail server reads the DKIM-Signature header
  2. It extracts two critical values: d= (the signing domain) and s= (the selector)
  3. It performs a DNS TXT lookup for <selector>._domainkey.<domain> — for example, google._domainkey.example.com
  4. It retrieves the public key from the DNS record
  5. It uses the public key to decrypt the signature, revealing the original hash
  6. It independently computes the hash of the received message’s headers and body
  7. If the two hashes match, the DKIM check passes — the message has not been tampered with and was signed by the claimed domain

The elegance of this system is that the public key lives in DNS, which is a globally distributed, cached, and highly available infrastructure. No special key exchange protocol is needed. Any receiving server in the world can verify a signature by performing a single DNS lookup.

Anatomy of a DKIM-Signature Header

Here is a real-world DKIM-Signature header, broken across lines for readability:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
    d=example.com; s=selector1;
    h=from:to:subject:date:message-id;
    bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;
    b=AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk2P...

Each tag serves a specific purpose:

TagMeaningExample Value
vVersion (always 1)1
aSigning algorithmrsa-sha256
cCanonicalization (how headers/body are normalized before hashing)relaxed/relaxed
dSigning domainexample.com
sSelector (identifies which key pair was used)selector1
hList of headers included in the signaturefrom:to:subject:date:message-id
bhBody hash (base64-encoded hash of the message body)2jUSOH9N...
bThe signature itself (base64-encoded)AuUoFEfD...

The canonicalization field (c=) deserves a note. Email messages frequently get subtly reformatted as they pass through servers — trailing whitespace added, header fields re-wrapped. The relaxed mode tolerates these cosmetic changes (ignoring extra whitespace, lowercasing header names). The simple mode requires exact byte-for-byte matches. Most deployments use relaxed/relaxed to avoid false failures from benign reformatting.

The DKIM DNS Record

The public key is published as a TXT record at a specific location: <selector>._domainkey.<domain>.

selector1._domainkey.example.com.  IN TXT  "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."

Record Tags

TagRequiredDescriptionExample
vRecommendedVersion (always DKIM1)v=DKIM1
kOptionalKey type (default: rsa)k=rsa or k=ed25519
pRequiredPublic key, base64-encodedp=MIGfMA0...
tOptionalFlagst=s (strict alignment) or t=y (testing mode)
hOptionalAcceptable hash algorithmsh=sha256
sOptionalService types=email or s=* (all services)
nOptionalNotes (human-readable)n=Production signing key

Selectors: Why They Exist

The selector mechanism allows a single domain to have multiple active DKIM keys simultaneously. This is essential because:

  • Different email services sign with different keys (your corporate mail uses one key, your marketing platform uses another)
  • Key rotation requires a transition period where both old and new keys are valid
  • Different departments or systems may manage their own signing infrastructure

Each email service has its own conventional selector names:

ProviderTypical Selector(s)DNS Record Location
Google Workspacegooglegoogle._domainkey.example.com
Microsoft 365selector1, selector2selector1._domainkey.example.com
Amazon SESCustom (e.g., 224i4yxa5dv7c2xz...)Via CNAME to amazonses.com
Mailchimpk1k1._domainkey.example.com
SendGrids1, s2s1._domainkey.example.com

Microsoft uses two selectors (selector1 and selector2) to facilitate automatic key rotation — one is active while the other is being prepared for the next rotation.

Key Sizes: How Strong Is Strong Enough?

The public key in DNS is visible to everyone. An attacker who can factor it (derive the private key from the public key) can forge DKIM signatures for that domain. Key size determines how difficult this is.

Key SizeStatusNotes
512-bit RSABrokenCan be factored in hours on consumer hardware; never use
1024-bit RSADeprecatedCan be broken in under 4 days using cloud computing; Google and Yahoo recommend against it
2048-bit RSACurrent standardRecommended by NIST, Google, Yahoo, and Microsoft as the minimum
4096-bit RSAMaximum practicalRarely used; the base64-encoded key can exceed DNS TXT record size limits
Ed25519EmergingMuch smaller keys, faster computation; defined in RFC 8463 (2018); limited receiver support

The DNS constraint is worth understanding. A single DNS TXT record string can hold 255 bytes. A 2048-bit RSA key encodes to roughly 392 base64 characters, which fits. A 4096-bit key doubles that, requiring the TXT record to be split across multiple strings within a single record — which is valid per the DNS specification but can cause issues with some DNS providers and resolvers.

Ed25519 is the future-looking option: an Ed25519 public key is only 44 base64 characters, trivially fitting in DNS. It is faster to compute and cryptographically strong with much smaller keys. However, as of 2025, receiver support remains limited, so most deployments stick with 2048-bit RSA.

Key Rotation

DKIM keys should be rotated periodically. If a private key is compromised, all messages signed with it can be forged until the key is revoked.

Recommended rotation frequency:

Key SizeRotation Interval
1024-bitEvery 3 months (upgrade to 2048-bit immediately)
2048-bitEvery 6-12 months
4096-bitEvery 12 months

The rotation procedure:

  1. Generate a new key pair with a new selector name (e.g., selector202501)
  2. Publish the new public key in DNS under the new selector
  3. Wait for DNS propagation — 24 to 48 hours to be safe
  4. Configure the sending server to sign outgoing mail with the new private key and new selector
  5. Keep the old public key in DNS for a transition period (messages signed with the old key may still be in transit or in recipients’ inboxes awaiting verification)
  6. After the transition, revoke the old key by publishing an empty p= tag:
old-selector._domainkey.example.com.  IN TXT  "v=DKIM1; p="

An empty p= tag is the standard signal that a key has been revoked. Any message bearing a signature with this selector will fail DKIM verification.

What DKIM Does and Does Not Protect

DKIM proves:

  • The message was signed by the domain in the d= tag
  • The signed headers and body have not been altered since signing
  • The signing domain takes responsibility for the message

DKIM does not prove:

  • That the From: header matches the signing domain (that is DMARC’s job through alignment)
  • That the message was not sent by a compromised account (the signature is valid regardless of who triggered the send)
  • That unsigned headers were not added or modified (only headers listed in the h= tag are covered)
  • That the message is not spam or malicious (DKIM is an identity assertion, not a content filter)

A critical nuance: DKIM survives forwarding. Unlike SPF, which breaks when a message is forwarded (the forwarding server’s IP is not in the original SPF record), the DKIM signature travels with the message. As long as the signed headers and body are not modified, verification still passes. This is why DMARC can fall back to DKIM alignment when SPF fails due to forwarding.

How to Verify DKIM with dig

To look up a DKIM public key, you need to know the selector. You can find the selector by examining the DKIM-Signature header of a received email (look for the s= tag). Then query DNS:

dig +short TXT google._domainkey.example.com

If the domain uses Google Workspace, this might return:

"v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."

For Microsoft 365:

dig +short TXT selector1._domainkey.example.com

If the record is a CNAME (common with hosted email services), follow the chain:

dig +short CNAME selector1._domainkey.example.com
selector1-example-com._domainkey.example.onmicrosoft.com.

Then resolve the final TXT:

dig +short TXT selector1-example-com._domainkey.example.onmicrosoft.com

To check if a key has been revoked, look for an empty p= tag in the response.

Adoption

DKIM adoption has historically lagged behind SPF because it requires more than a DNS record. It demands cryptographic key generation, mail server configuration to sign outgoing messages, and ongoing key rotation — operational overhead that SPF does not impose.

MetricValueSource
Alexa Top 1M domains with DKIM~28.1%USENIX Security (2022)
French .fr domains with DKIM40.7%AFNIC (2025)
DKIM records that fail validation3.4%dmarcchecker.app (2024)
Misconfigured DKIM records2.9% of adoptersUSENIX Security (2022)

The growth trajectory is encouraging. French .fr domains saw DKIM adoption nearly double from 22.6% in 2023 to 40.7% in 2025, driven largely by Google and Yahoo’s February 2024 enforcement requirements that mandate both SPF and DKIM for bulk senders.

DKIM was born from the merger of two competing proposals: Yahoo’s DomainKeys (2004) and Cisco’s Identified Internet Mail (2005). The combined specification was published as RFC 4871 in 2007, updated to the current standard RFC 6376 in September 2011, and extended with Ed25519 key support in RFC 8463 in September 2018.

Together with SPF and DMARC, DKIM forms the email authentication triad. SPF validates the sending server. DKIM validates the message integrity. And DMARC ties them both to the domain visible in the From: header, adding the policy layer that tells receivers what to do when authentication fails.

Related Resources