DKIM (DomainKeys Identified Mail) is an email authentication method that uses cryptographic signatures to verify that an email message was sent by an authorized mail server and hasn't been altered in transit. DKIM adds a digital signature to the email headers using public-key cryptography.
- Signing: Sending mail server signs outgoing emails with a private key
- Publishing: Domain publishes public key in DNS as a TXT record
- Verification: Receiving server retrieves public key and verifies signature
DKIM records are published at:
selector._domainkey.domain.com
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQ...
v=: Version (always "DKIM1")p=: Public key data (base64 encoded)
k=: Key type (default: "rsa")h=: Acceptable hash algorithms (default: all)s=: Service type (default: "*")t=: Flagsn=: Notes for administratorsg=: Granularity of the key
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgdfgQIDAQAB"
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; t=s; n=This is our production key; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfgdfgdfgdfgdfgdfgdfgdfgdfgdfgQIDAQAB"
selector._domainkey.example.com TXT "v=DKIM1; p="
selector._domainkey.example.com TXT ( "v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1234567890"
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567"
"890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ..." )
- Minimum: 1024 bits (being phased out)
- Recommended: 2048 bits
- Maximum: 4096 bits (may cause DNS issues)
# Generate 2048-bit key pair
openssl genrsa -out private.key 2048
openssl rsa -in private.key -pubout -out public.keySelectors allow multiple DKIM keys per domain:
- Key rotation
- Different keys for different systems
- Testing new keys
# Date-based
202501._domainkey.example.com
20250115._domainkey.example.com
# Service-based
google._domainkey.example.com
mandrill._domainkey.example.com
# Environment-based
prod._domainkey.example.com
test._domainkey.example.com
# Generic
s1._domainkey.example.com
default._domainkey.example.com
k1._domainkey.example.com
# GOOD: 2048-bit key
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
# AVOID: 1024-bit key (too weak)
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."
# Current key
202501._domainkey.example.com TXT "v=DKIM1; k=rsa; p=CURRENT_KEY"
# New key (during transition)
202502._domainkey.example.com TXT "v=DKIM1; k=rsa; p=NEW_KEY"
# Old key (keep for verification of old emails)
202412._domainkey.example.com TXT "v=DKIM1; k=rsa; p=OLD_KEY"
Configure your mail server to sign:
- From
- To
- Subject
- Date
- Message-ID
- Content-Type
- Reply-To (if present)
# GOOD: Meaningful selectors
google-2025._domainkey.example.com
marketing-prod._domainkey.example.com
transactional-01._domainkey.example.com
# POOR: Non-descriptive
x._domainkey.example.com
key._domainkey.example.com
dkim._domainkey.example.com
Track which keys are being used:
- Review DMARC reports
- Monitor mail logs
- Set up alerts for signing failures
# WRONG: Missing quotes
selector._domainkey.example.com TXT v=DKIM1; k=rsa; p=MIGfMA...
# WRONG: Line breaks in key
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MIGfMA
0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC"
# CORRECT: Proper quoting and no line breaks in key
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC..."
# TOO LARGE: 4096-bit keys may exceed DNS limits
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MIICIQC..."
# Solution: Use 2048-bit keys
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MIIBIjA..."
# WRONG: Missing ._domainkey
selector.example.com TXT "v=DKIM1; k=rsa; p=..."
# WRONG: Wrong subdomain format
_domainkey.selector.example.com TXT "v=DKIM1; k=rsa; p=..."
# CORRECT: selector._domainkey.domain
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; p=..."
# NEVER publish private keys!
# This is a PUBLIC key record - only publish the public key
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; p=PUBLIC_KEY_HERE"
The t=y flag indicates that the DKIM record is in testing mode. Verifiers may ignore the DKIM signature if this flag is present, even if the signature is valid. This flag should not be used for production keys.
# WRONG: Production key in test mode
prod._domainkey.example.com TXT "v=DKIM1; t=y; p=..."
# CORRECT: Remove t=y for production
prod._domainkey.example.com TXT "v=DKIM1; p=..."
# Main domain key
selector._domainkey.example.com TXT "v=DKIM1; k=rsa; p=..."
# Don't forget subdomain keys if they send mail
selector._domainkey.mail.example.com TXT "v=DKIM1; k=rsa; p=..."
selector._domainkey.newsletter.example.com TXT "v=DKIM1; k=rsa; p=..."
# Google Workspace
google._domainkey.example.com TXT "v=DKIM1; k=rsa; p=GOOGLE_PROVIDED_KEY"
# SendGrid
s1._domainkey.example.com CNAME s1.domainkey.u1234567.wl.sendgrid.net
s2._domainkey.example.com CNAME s2.domainkey.u1234567.wl.sendgrid.net
# Multiple providers
mandrill._domainkey.example.com TXT "v=DKIM1; k=rsa; p=MANDRILL_KEY"
ses._domainkey.example.com TXT "v=DKIM1; k=rsa; p=AWS_SES_KEY"
# Wildcard to prevent unauthorized DKIM signing
*._domainkey.example.com TXT "v=DKIM1; p="
# Production key
prod._domainkey.example.com TXT "v=DKIM1; k=rsa; p=PRODUCTION_KEY"
# Test key (with restricted flag)
test._domainkey.example.com TXT "v=DKIM1; k=rsa; t=y; p=TEST_KEY"
# Current active key
current._domainkey.example.com TXT "v=DKIM1; k=rsa; p=CURRENT_KEY"
# Keep current key
current._domainkey.example.com TXT "v=DKIM1; k=rsa; p=CURRENT_KEY"
# Add new key
new._domainkey.example.com TXT "v=DKIM1; k=rsa; p=NEW_KEY"
- Start signing with new selector
- Monitor both keys
- Verify new key is working
# Old key (keep for 30+ days for in-transit mail)
old._domainkey.example.com TXT "v=DKIM1; k=rsa; p=CURRENT_KEY"
# New key becomes current
current._domainkey.example.com TXT "v=DKIM1; k=rsa; p=NEW_KEY"
# Remove or revoke old key
old._domainkey.example.com TXT "v=DKIM1; p="
# Only current key remains
current._domainkey.example.com TXT "v=DKIM1; k=rsa; p=NEW_KEY"
-
Check DNS propagation
dig TXT selector._domainkey.example.com +short
-
Verify key format
- No line breaks in public key
- Proper base64 encoding
- Correct record syntax
-
Confirm selector matches
- Email header selector matches DNS record
- No typos in selector name
- Check for content modification in transit
- Verify mail server isn't altering messages
- Look for security appliances modifying content
- Ensure record is published at correct location
- Check for DNS server issues
- Verify no DNSSEC problems
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=example.com; s=selector;
h=from:to:cc:subject:date:message-id:content-type;
bh=rBTqc1nOyXBOoV9aGJPzGdRkpgUBZ8EwQVpQ8FwpA=;
b=dQgQkP3JoF3lAClB3EoQQOx3TnuBFBhGp1TtlhGOEfQP7lkQ...
- v=: Version (always "1")
- a=: Algorithm (e.g., rsa-sha256)
- c=: Canonicalization (header/body)
- d=: Signing domain
- s=: Selector
- h=: Signed headers
- bh=: Body hash
- b=: Signature
- Send test email to a DKIM validator
- Check email headers for DKIM-Signature
- Verify Authentication-Results header
# Check DKIM record exists
dig TXT selector._domainkey.example.com
# Verify record format
echo "record_content" | grep "v=DKIM1"# PASS
Authentication-Results: mx.google.com;
dkim=pass header.i=@example.com header.s=selector
# FAIL - Key not found
Authentication-Results: mx.google.com;
dkim=fail (key not found) header.i=@example.com
# FAIL - Signature verification failed
Authentication-Results: mx.google.com;
dkim=fail (signature verification failed) header.i=@example.com
DKIM is a crucial email authentication technology that requires careful implementation and maintenance:
- Use 2048-bit RSA keys for optimal security
- Implement proper key rotation procedures
- Use meaningful selector names
- Monitor DKIM signing and validation
- Keep DNS records properly formatted
- Coordinate with DMARC for alignment
- Test thoroughly before and after changes
Combined with SPF and DMARC, DKIM forms a comprehensive email authentication strategy that protects against forgery and phishing.