Every time you receive an email claiming to be from your bank, your SaaS tool, or a colleague, something needs to verify that claim. DKIM is one of the three pillars of email authentication (alongside SPF and DMARC) that makes that verification possible.
What Problem Does DKIM Solve?
Email’s original design from the 1970s has no built-in authentication. The From: header is a free-text field — any mail server can put any address there. Without authentication, spoofing support@yourbank.com requires only a mail server and about 30 seconds.
DKIM solves this by adding a cryptographic signature to outgoing email. The receiving server fetches your public key from DNS and verifies the signature. If it matches, the email demonstrably came from a server with access to your private key.
How DKIM Works: Step by Step
Sender (your mail server) Receiver (Gmail, Outlook, etc.)
───────────────────────── ───────────────────────────────
1. Compose email
2. Hash selected headers + body
3. Encrypt hash with private key ──▶ 4. Extract DKIM-Signature header
4. Add DKIM-Signature header 5. Look up public key in DNS:
selector._domainkey.domain.com
6. Decrypt signature with public key
7. Hash the same headers + body
8. Compare hashes → PASS or FAIL
The private key stays on your mail server (or your email provider’s infrastructure). The public key is published in DNS as a TXT record.
The DKIM-Signature Header
Every DKIM-signed email includes a header like this:
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=example.com; s=google;
h=from:to:subject:date:message-id:content-type;
bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
b=XG3jKpL9rT2mN8...
| Tag | Meaning |
|---|---|
v=1 | DKIM version |
a=rsa-sha256 | Algorithm: RSA signing with SHA-256 hash |
c=relaxed/relaxed | Canonicalization for headers/body (relaxed tolerates minor whitespace changes) |
d=example.com | Signing domain |
s=google | Selector — tells receiver which DNS record has the public key |
h=from:to:... | Which headers were signed |
bh=... | Body hash (base64) |
b=... | The actual cryptographic signature (base64) |
The DNS TXT Record
The public key lives at {selector}._domainkey.{domain}:
google._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."
| Tag | Meaning |
|---|---|
v=DKIM1 | Record version |
k=rsa | Key type (rsa is standard; ed25519 also supported) |
p=... | Base64-encoded public key |
t=s | Optional: s = strict subdomains, y = test mode |
An empty p= field (p=) signals a revoked key — receiving servers should treat signatures from this key as invalid.
Key Lengths and Algorithms
| Algorithm | Key Size | Recommendation |
|---|---|---|
| RSA | 1024-bit | Deprecated — avoid |
| RSA | 2048-bit | Current standard |
| RSA | 4096-bit | Higher security, slightly slower |
| Ed25519 | 256-bit (equivalent to 3000-bit RSA) | Modern, compact, faster |
Most email providers use 2048-bit RSA. Ed25519 support is growing but not universal — check your mail server’s documentation before switching.
Setting Up DKIM
With Google Workspace
- Admin Console → Apps → Google Workspace → Gmail → Authenticate email
- Select your domain, click Generate new record
- Copy the TXT record and add it to your DNS provider
- Wait for DNS propagation (up to 48h), then click Start authentication
With Microsoft 365
# PowerShell — Exchange Online
New-DkimSigningConfig -DomainName example.com -Enabled $true
Get-DkimSigningConfig -Identity example.com | Select-Object Selector1CNAME, Selector2CNAME
Add the two CNAME records to your DNS, then enable DKIM in the Microsoft 365 admin center under Settings → Domains → your domain → Email authentication.
Manual Setup (Postfix)
# Generate key pair
openssl genrsa -out dkim_private.pem 2048
openssl rsa -in dkim_private.pem -pubout -out dkim_public.pem
# Extract public key for DNS (remove headers/newlines)
grep -v "^-" dkim_public.pem | tr -d '\n'
# Postfix: install opendkim, configure /etc/opendkim.conf
# KeyFile /etc/opendkim/keys/example.com/default.private
# Domain example.com
# Selector default
DNS record to add:
default._domainkey.example.com. TXT "v=DKIM1; k=rsa; p=<base64-public-key>"
Verifying DKIM
Via DNS lookup:
dig TXT google._domainkey.example.com
# or
nslookup -type=TXT google._domainkey.example.com
Send a test email to a Gmail address, open the message, click the three-dot menu → Show original. Look for:
DKIM: 'PASS' with domain example.com
Using DomainScan: Enter your domain at /domain/email — it fetches all _domainkey selectors and validates the record format and key size.
DKIM and DMARC Alignment
DKIM alone doesn’t prevent spoofing at the From: header level. DMARC alignment is what closes that gap.
DMARC Alignment Check:
From: header domain = DKIM d= domain
example.com = example.com → ALIGNED ✓
example.com ≠ mailchimp.com → NOT aligned (unless relaxed)
With p=reject DMARC, an email that fails both SPF alignment AND DKIM alignment is rejected outright. This is why DKIM and SPF are the inputs to DMARC, not standalone solutions.
Common Misconfigurations
| Problem | Symptom | Fix |
|---|---|---|
| Key too short (1024-bit) | Warnings in mail headers | Rotate to 2048-bit |
| Wrong selector in DNS | DKIM: FAIL | Match selector in mail server config to DNS name |
| Public key truncated | Record won’t parse | Some DNS providers split long TXT records — wrap in quotes and concatenate |
| Mailing list breaks signature | DKIM: FAIL on forwarded mail | Use relaxed canonicalization; configure DMARC to allow SPF fallback |
| Key not yet propagated | DKIM: FAIL | Wait 24-48h after publishing; test with dig |
| CNAME pointing to wrong record | FAIL | For M365, verify both selector1 and selector2 CNAMEs |
Long TXT Record Splitting
Some DNS providers can’t store TXT records longer than 255 characters. DKIM public keys often exceed this. The solution is to split into multiple quoted strings:
google._domainkey.example.com. TXT (
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNA"
"DCBiQKBgQC2s7sWLEMgMfgb9dCaGOCl6UaXuRQvt3Ku..."
)
DNS resolvers concatenate quoted strings automatically. Your mail server handles the full key.
Summary
DKIM = public-key cryptography for email. Your private key signs outgoing messages. Your public key in DNS lets any receiver verify the signature. Without DKIM, there’s no cryptographic proof your email came from you — and DMARC, which protects your brand from spoofing, depends on DKIM (or SPF) passing.
Set it up once per sending domain, verify it, and rotate keys annually.
Common Questions
Does DKIM prevent spam?
Not directly. DKIM proves the email came from your domain and wasn't altered — it says nothing about whether the content is spam. However, a valid DKIM signature improves sender reputation scores, which indirectly helps deliverability. DMARC (which depends on DKIM or SPF alignment) can prevent spoofing, which is what keeps spam from appearing to come from your brand.
Can I have multiple DKIM keys for the same domain?
Yes. You can publish as many DKIM keys as you need, each with a different selector prefix (e.g., google._domainkey, mailchimp._domainkey, s1._domainkey). This is common when using multiple email platforms — each gets its own key pair.
What happens if my DKIM key is compromised?
Remove the public key TXT record from DNS immediately. The compromised key can no longer be used to verify signatures. Generate a new key pair, publish the new public key under a new selector, and reconfigure your mail server to sign with the new private key. This is why key rotation on a schedule (annually or more) is recommended.
Why do some legitimate emails fail DKIM?
Mailing lists and forwarding services often modify message headers or body (e.g., adding [List-Name] to the subject or rewriting links), which breaks the DKIM signature. This is why DMARC allows SPF-only alignment as a fallback. ARC (Authenticated Received Chain) is the modern solution for handling legitimate forwarding chains.
What is a DKIM selector?
A selector is a label you choose that forms the first part of the DKIM DNS record name: selector._domainkey.yourdomain.com. It lets you publish multiple DKIM keys (one per sending service) without conflict. The selector is embedded in every outgoing email's DKIM-Signature header so receiving servers know which DNS record to look up.