Skip to content
Back to Blog
Email SecurityApril 1, 2026·13 min read

DKIM Explained: How Email Digital Signatures Protect Your Domain

DKIM adds a cryptographic signature proving emails are authentic and unaltered. Learn selectors, key rotation, RSA vs Ed25519.

Wooden blocks spelling encryption symbolizing DKIM email signatures

DKIM (DomainKeys Identified Mail) adds a cryptographic signature to every outgoing email, allowing recipients to verify that the message was authorized by the domain owner and was not tampered with in transit. Defined in RFC 6376, DKIM is the most resilient authentication mechanism in the email stack — unlike SPF, it survives forwarding. This guide details the signing architecture, dissects every tag in the DKIM-Signature header, compares RSA and Ed25519 algorithms, and covers key rotation, canonicalization, over-signing, and common failure modes.


1. How DKIM Works

DKIM uses asymmetric cryptography (public/private key pair) to sign emails. The sending server holds the private key; the public key is published in DNS. When a recipient receives the message, it retrieves the public key and verifies the signature.

Key Generation
The domain owner generates an RSA (or Ed25519) key pair. The private key is installed on the mail server or ESP. The public key is published as a DNS TXT record at selector._domainkey.example.com.

Message Signing
The sending MTA selects headers to sign (e.g., From, To, Subject, Date) and the message body. It canonicalizes them (normalizes whitespace), hashes the result, and encrypts the hash with the private key.

Signature Insertion
The encrypted hash (signature) and metadata are placed in a DKIM-Signature header prepended to the message. This header includes the selector, algorithm, signed headers list, and the base64-encoded signature value.

DNS Lookup
The receiving MTA reads the DKIM-Signature header, extracts the selector (s=) and domain (d=), and queries s._domainkey.d for the public key TXT record.

Verification
The receiver re-canonicalizes the signed headers and body, computes the hash, and uses the public key to decrypt the signature. If the hashes match, the signature is valid — the message is authentic and unmodified.

DMARC Evaluation
If the d= domain aligns with the From: header domain (relaxed or strict), DMARC considers DKIM as a passing authentication result.

💡 DKIM does not encrypt the message content. It only provides a digital signature that proves origin and integrity. The message itself is still transmitted in cleartext (unless TLS is used at the transport layer).


2. DKIM-Signature Header Anatomy

Every DKIM-signed message contains a DKIM-Signature header with the following tags:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
  d=example.com; s=selector1; t=1712880000;
  x=1713484800; h=from:to:subject:date:message-id:mime-version;
  bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;
  b=LjxLMKpHN2kQz... (signature value)
Tag Required Meaning Values
vYesVersion1 (always)
aYesSigning algorithmrsa-sha256, rsa-sha1 (deprecated), ed25519-sha256
dYesSigning domain (DMARC alignment key)e.g., example.com
sYesSelector (lookup key for public key)e.g., selector1, google, s1
hYesSigned header fieldsColon-separated list of header names
bYesSignature data (base64)Cryptographic signature value
bhYesBody hash (base64)Hash of the canonicalized body
cNoCanonicalization (header/body)simple/simple (default), relaxed/relaxed, relaxed/simple
tNoSignature timestamp (Unix epoch)e.g., 1712880000
xNoSignature expiration (Unix epoch)e.g., 1713484800
lNoBody length limit (bytes signed)Integer — avoid using
iNoAgent or user identifierMust be a subdomain of d=
qNoQuery methoddns/txt (default, only value)
zNoCopied header fields (for diagnostics)Pipe-separated copies of signed headers

🚫 Never use the l= (body length) tag. It tells verifiers to only check the first N bytes of the body, allowing attackers to append malicious content after the signed portion. RFC 6376 §8.2 explicitly warns about this vulnerability.


3. The Selector Concept

A selector is a label that lets a single domain have multiple DKIM keys simultaneously — essential for key rotation and multi-service environments. The public key is published at <selector>._domainkey.<domain>.

📖 Definition — A DKIM selector is an arbitrary string chosen by the domain owner that identifies a specific public key record in DNS. It is specified in the s= tag of the DKIM-Signature header and used to construct the DNS query: selector._domainkey.domain.com.

Selectors by Provider

Provider Typical Selector(s) DNS Record Location
Google Workspacegooglegoogle._domainkey.example.com
Microsoft 365selector1, selector2selector1._domainkey.example.com
SendGrids1, s2s1._domainkey.example.com
Mailchimpk1k1._domainkey.example.com
Amazon SESAuto-generated (CNAME-based)3 CNAME records per domain
Postmark20240101 (date-based)CNAME to Postmark DNS

Use descriptive selectors that include the date or purpose: google-2024, marketing-q1. This makes key rotation audits much easier — you can tell at a glance which keys are current and which are deprecated.


4. RSA vs Ed25519

RFC 8463 (2018) introduced Ed25519 as an alternative to RSA for DKIM signatures. Here's how they compare:

Property RSA-SHA256 Ed25519-SHA256
RFCRFC 6376RFC 8463
Key Size1024–4096 bits (2048 recommended)256 bits (fixed)
Signature Size~342 bytes (2048-bit)88 bytes (fixed)
DNS TXT Record Size~400 bytes (2048-bit public key)~60 bytes
PerformanceSlower signing & verificationSignificantly faster
SecuritySecure at 2048+ bits128-bit equivalent security
Receiver SupportUniversalGrowing (Gmail, Fastmail support it)

🎯 Dual-sign with both RSA-2048 and Ed25519. Receivers that support Ed25519 benefit from smaller signatures and faster verification. Receivers that don't will fall back to the RSA signature. Each signature uses a different selector.

⚠️ 1024-bit RSA keys are deprecated. RFC 8301 (2018) requires a minimum of 2048 bits for RSA DKIM keys. Some receivers (notably Gmail) will reject 1024-bit signatures. Rotate immediately if you're still using 1024-bit keys.


5. Canonicalization: Simple vs Relaxed

Canonicalization normalizes the message before hashing to tolerate minor modifications by intermediate mail servers. The c= tag specifies the algorithm for headers and body separately (e.g., c=relaxed/relaxed).

Mode Headers Body
Simple No changes — headers must be byte-identical Trailing empty lines removed; no other changes
Relaxed Header names lowercased; whitespace folding normalized; trailing whitespace removed Whitespace sequences reduced to single space; trailing whitespace on lines removed; trailing empty lines removed
# simple/simple — very strict, breaks easily:
Subject: Hello World     ←  exact bytes must match

# relaxed/relaxed — tolerant of whitespace changes:
Subject:Hello World      ←  extra spaces and case changes are normalized
subject: hello world     ←  both canonicalize to the same form

Always use c=relaxed/relaxed. Intermediate servers (mailing lists, forwarding services, antivirus gateways) frequently modify whitespace. Simple canonicalization causes unnecessary DKIM failures in real-world mail flows.


6. Key Rotation Procedure

DKIM keys should be rotated periodically (every 6–12 months) to limit exposure if a private key is compromised. The selector mechanism makes zero-downtime rotation straightforward.

Generate new key pair
Create a new RSA-2048 or Ed25519 key pair with a new selector (e.g., dkim-202604).

Publish new public key
Add the new TXT record at dkim-202604._domainkey.example.com. Wait for DNS propagation (TTL).

Switch signing to new selector
Configure your MTA/ESP to sign outgoing mail with the new private key and selector.

Monitor for failures
Watch DMARC reports and DKIM verification headers for a few days. Ensure the new key passes.

Revoke old key
After the overlap period (1–2 weeks), publish an empty p= tag for the old selector: v=DKIM1; p=. This tells receivers the key is revoked.

Remove old DNS record
After another TTL cycle, delete the old selector's DNS record entirely.

💡 An empty p= tag in a DKIM DNS record (RFC 6376 §3.6.1) is the official revocation signal. It tells verifiers that the key has been deliberately revoked, as opposed to a missing record which could be a DNS failure.


7. DKIM + DMARC Alignment

For DMARC to consider DKIM as a passing result, two conditions must be met:

  1. DKIM signature must verify (valid cryptographic signature).
  2. The d= domain must align with the From: header domain.
Scenario DKIM d= From Header DMARC adkim Aligned?
Exact matchexample.comuser@example.comAnyYes
Subdomain (relaxed)mail.example.comuser@example.comrYes
Subdomain (strict)mail.example.comuser@example.comsNo
Third-party domainsendgrid.netuser@example.comAnyNo

⚠️ Many ESPs sign with d=esp-domain.com by default. You must configure custom DKIM signing so the d= tag uses your domain (or a subdomain of it in relaxed mode) for DMARC alignment to work.


8. Over-Signing

📖 Definition — Over-signing is a DKIM best practice where the h= tag includes headers that are not present in the message (e.g., listing Reply-To twice). This prevents attackers from adding a spoofed Reply-To header after signing — any addition would invalidate the signature.

# Over-signing example: listing headers that don't exist in the message
h=from:to:subject:date:reply-to:reply-to:cc:cc

# "reply-to" is listed twice:
# First instance covers the actual Reply-To header (if present)
# Second instance "seals" the slot — adding a new Reply-To breaks the signature

🎯 Over-sign these headers at minimum: From, To, Subject, Date, Reply-To, CC, Content-Type, MIME-Version, Message-ID. Over-signing prevents post-signature header injection attacks.


9. Best Practices

Use 2048-bit RSA minimum
1024-bit keys are deprecated (RFC 8301). Generate 2048-bit keys for all selectors.

Use relaxed/relaxed canonicalization
Simple canonicalization fails too easily with intermediate MTAs. Relaxed is the industry standard.

Sign with your domain
Ensure the d= tag matches your From: domain for DMARC alignment. Configure custom DKIM on every ESP.

Rotate keys every 6–12 months
Use the selector system for zero-downtime rotation. Revoke old keys with an empty p= tag.

Over-sign critical headers
List From, Reply-To, Subject, and CC twice in the h= tag to prevent header injection.

Never use the l= tag
Body length limits allow content to be appended to signed messages. Always sign the full body.


10. Common Failures

🚫 DNS record not found. The most common DKIM failure. Usually caused by a typo in the selector name, missing CNAME, or DNS propagation delay. Always verify with dig TXT selector._domainkey.example.com.

🚫 Body hash mismatch (bh= tag). The body was modified after signing — typically by a mailing list, antivirus gateway, or footer-appending service. Use relaxed body canonicalization and investigate the specific MTAs in the delivery chain.

⚠️ Key too short. 512-bit and 1024-bit RSA keys are rejected by many receivers. Gmail logs dkim=neutral (body hash did not verify) for weak keys even when the signature is mathematically valid.

⚠️ Expired signature. If the x= tag is set and the current time exceeds it, the signature is treated as invalid. Use generous expiration windows (7+ days) or omit x= entirely.

⚠️ Testing with email headers. To debug DKIM, view the full message headers and look for Authentication-Results. Gmail shows dkim=pass, dkim=fail, or dkim=neutral with a reason string.

# Gmail Authentication-Results header example:
Authentication-Results: mx.google.com;
  dkim=pass header.i=@example.com header.s=selector1 header.b=LjxLMKpH;
  spf=pass (google.com: domain of user@example.com designates 198.51.100.42 as permitted sender);
  dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=example.com

11. Tools

Tool Purpose
DKIM Record CheckerLook up any selector's public key and validate record syntax

12. Sources & References


DKIM is the most durable email authentication mechanism — it survives forwarding, validates message integrity, and provides the preferred alignment path for DMARC. Use 2048-bit RSA or Ed25519, always choose relaxed/relaxed canonicalization, sign with your own domain for DMARC alignment, over-sign critical headers, rotate keys every 6–12 months, and never use the l= body length tag.

🚀 Free ToolZilla tools used in this article

All client-side, no signup, no upload — open them in a new tab while you read:

Continue Reading

Related Articles

Free & Private

Explore Our Free Tools

40+ browser-based utilities — fast, private, and always free. No sign-up required.

Browse All Tools