← Email SecurityEmail Auth / Cryptographic

DKIM — DomainKeys Identified Mail

A cryptographic signature standard that lets receiving mail servers verify that email content was not tampered with in transit and was authorized by the sending domain.

How It Works

Signing Email with Public-Key Cryptography

DKIM uses asymmetric cryptography. The sending mail server signs outbound messages with a private key and inserts a DKIM-Signature: header into the email. The corresponding public key is published in DNS as a TXT record at a selector subdomain: selector._domainkey.example.com.

When a receiving server gets the message, it retrieves the public key from DNS, decrypts the DKIM signature, and compares the resulting hash to the hash of the signed message headers and body. If they match, the signature is valid — confirming that the message was signed by a server holding the private key for example.com and that the signed content was not modified in transit.

Unlike SPF, DKIM signatures survive email forwarding because the signature travels with the message headers — as long as the forwarder does not modify the signed headers or body. This makes DKIM the more reliable authentication signal for DMARC when forwarding is involved.

DKIM Does Not Encrypt EmailDKIM provides integrity and authentication — not confidentiality. The message body is still transmitted in plain text (unless TLS is used for transport). DKIM only proves the message was signed by the domain and not tampered with after signing.
; DKIM public key DNS record ; Published at: selector._domainkey.example.com "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA2a6..."
Key Types

RSA vs. Ed25519 Keys

RSA 2048-bit (most common)

The original and universally supported DKIM key type. RSA 2048-bit provides solid security and is accepted by all major receiving servers. RSA 1024-bit keys are deprecated and should be replaced — they are considered weak and DMARC aggregate reports will flag them.

# Generate RSA 2048 DKIM keypair openssl genrsa -out dkim_private.pem 2048 openssl rsa -in dkim_private.pem \ -pubout -out dkim_public.pem # Extract public key for DNS record openssl rsa -in dkim_private.pem \ -pubout -outform DER | base64 -w0
Ed25519 (modern, compact)

RFC 8463 (2018) added Ed25519 support. Keys are much shorter (32 bytes vs 256+ bytes for RSA), faster to sign/verify, and equally secure with a smaller DNS record. Not yet universally supported — some older receiving servers do not verify Ed25519 signatures. Best practice: publish both RSA and Ed25519 selectors.

# Generate Ed25519 DKIM keypair openssl genpkey \ -algorithm ed25519 \ -out dkim_ed25519_private.pem openssl pkey \ -in dkim_ed25519_private.pem \ -pubout -out dkim_ed25519_public.pem
Key Management

Selectors and Key Rotation

A selector is a label you choose that namespaces DKIM public keys under your domain. The DNS record is published at <selector>._domainkey.example.com. You can have multiple selectors active simultaneously — one per mail system, one per key rotation cycle, or one per sending service.

Key rotation is critical for DKIM security. Generate a new keypair, publish the new public key under a new selector, configure your mail server to start signing with the new private key, then after a period (ensure all in-flight messages have been delivered and keys TTL has expired), remove the old selector record.

  • Naming conventions: default, google, sendgrid, s1/s2, or date-based like 20240101
  • Set TTL low (300–3600s) before rotation — allows faster propagation of key changes
  • Keep old selector active for at least 72 hours after switching to the new key
  • Rotate at minimum annually; quarterly for high-security environments
  • DKIM records support a t=s flag to restrict the key to exact domain (no subdomain signing)
; Two selectors — dual-key strategy ; for rotation with zero downtime ; Active signing key 20240101._domainkey.example.com TXT "v=DKIM1; k=rsa; p=<new-public-key>" ; Old key (kept during rotation period) 20230101._domainkey.example.com TXT "v=DKIM1; k=rsa; p=<old-public-key>" ; ESP-specific selector (Google Workspace) google._domainkey.example.com TXT "v=DKIM1; k=rsa; p=<google-public-key>" ; Key flags ; t=y = testing mode (receivers should not ; treat failures differently) ; t=s = strict (no subdomain signing) ; h=sha256 = hash algorithm (default) ; s=email = service type restriction
Technical Detail

Canonicalization: relaxed vs. simple

Canonicalization normalizes the email headers and body before hashing, to tolerate minor modifications made by intermediate servers. The DKIM-Signature header specifies canonicalization as c=header/body.

simple/simple — strict: no whitespace normalization. Breaks easily if any server adds a trailing newline or normalizes whitespace in headers. Not recommended for most deployments.

relaxed/relaxed — tolerant: whitespace sequences collapsed to single space, header names lowercased, trailing whitespace stripped from body. Survives most in-transit modifications. Strongly recommended.

Mailing lists often break DKIM signatures because they modify the subject line (prepend [list-name]), add footers to the body, or change the From header. ARC (Authenticated Received Chain) is designed to preserve authentication results across these legitimate modifications.

What Gets Signed
  • Specific headers (From, To, Subject, Date, Message-ID)
  • The message body (or a hash of it)
  • The signing domain (d=)
  • The selector (s=)
  • The list of signed headers (h=)

The From: header must be included in h= for DMARC alignment. Signing the From header ties the DKIM signature directly to the domain visible to users.

Diagnostics

Inspecting DKIM Records and Signatures

Look up a DKIM public key

# Query selector record dig TXT selector._domainkey.example.com # Google Workspace default selector dig TXT google._domainkey.example.com # Common selectors to check dig TXT s1._domainkey.example.com dig TXT default._domainkey.example.com dig TXT mail._domainkey.example.com

Verify a DKIM signature

# Save a raw email message (.eml) # and verify the DKIM signature # Using dkimverify (Python) pip install dkimpy dkimverify < message.eml # Or: mail-tester.com # Send test email, check report

Check email headers

# In Gmail: Show original # In Outlook: View message source # Look for: DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=google; h=from:to:subject:...; bh=<body-hash>; b=<signature> # Authentication-Results header shows # whether the check passed or failed

Discover all active selectors

# No standard method to enumerate # selectors — check mail headers # Common selector names: for sel in google mail s1 s2 k1 \ default dkim selector1 selector2; do dig +short TXT \ ${sel}._domainkey.example.com done