UnveilTech

UnveilScan Blog

← All articles

Try UnveilScan free

DKIM key rotation: why nobody does it (and why you should)

Posted 2026-04-29 · 6 min read · EMAILDKIM

DKIM signs every outbound message with an asymmetric key. The public half lives in DNS at selector._domainkey.example.com; the private half lives in your mail server. Industry guidance (Google, Microsoft, NIST) recommends rotating every 6 months. The modal age in our scan database: 4-7 years. Some are pre-2018.

Why rotate

Crypto keys age in three ways:

  1. Algorithmic deprecation. Pre-2018 keys are usually 1024-bit RSA. NIST classified RSA-1024 as "legacy" since 2013 and as "disallowed" since 2030 is the projected deadline. RFC 8301 mandates 2048+ for DKIM.
  2. Server compromise. If your mail server has been touched by an attacker over its lifetime — even briefly — the private key may have been exfiltrated. You don't always notice. Rotation is the only reliable mitigation.
  3. Cryptographic forward secrecy. Long-lived keys mean the same key signs years of historical mail. A future leak retroactively allows attackers to forge "from-the-past" messages.

Why nobody rotates

Because the rotation procedure is annoying and the consequences of getting it wrong are "all your mail goes to spam". Specifically:

The protocol designers anticipated this with selectors.

The dual-selector rotation pattern

A DKIM signature in a message header references its selector by name:

DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=2024a; ...
                                                  ^^^^^
                                                  selector

Receivers fetch 2024a._domainkey.example.com for that specific message's verification. Multiple selectors can coexist. So:

  1. Day 0. Generate new keypair. Publish public key as 2026b._domainkey.example.com (a new selector). Old key stays as 2024a._domainkey.example.com.
  2. Day 7. Configure mail server to sign new outbound mail with selector 2026b. Both records live in DNS; receivers verify whichever signature each message references.
  3. Day 60. Old in-flight mail has cleared. Remove the old 2024a DNS record. Done.

Total downtime: zero. Mail signed with the old key continues to verify until day 60; mail signed with the new key verifies from day 7 onwards. The window in between is the only "both records live" period — harmless.

Generating the keypair

$ openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out dkim-2026b.private.pem
$ openssl pkey -in dkim-2026b.private.pem -pubout -outform DER 2>/dev/null \
  | base64 -w0
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA....

The base64 string is your p= value. The DNS record:

2026b._domainkey.example.com.  IN  TXT  "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...."

Most DNS providers reject TXT records longer than 255 chars. Split into multiple quoted strings:

"v=DKIM1; k=rsa; " "p=MIIBIjANBg... " "AQEFAAOCAQ8A...."

The DNS server concatenates them on read. Cosmetically ugly, semantically equivalent.

For SaaS-vendor DKIM (SendGrid, Mailgun, etc.)

You don't manage the private key — the vendor does. Rotation procedure varies but is usually one click in their dashboard. Re-publish their new CNAME or TXT record. Same dual-selector window applies.

How UnveilScan flags this

Our dkim checker (Extended profile) probes 41 known selectors and parses the public key for:

We don't currently flag "this key looks old" because age can't be determined from DNS alone. But if your scan reports modulus < 2048, that's a 2018-era keypair you should rotate today.

Audit your DKIM keys now

Extended scan probes 41 selectors and reports modulus size + signing algorithm.

See pricing