DKIM · Key rotation
Rotate your DKIM keys without breaking a single message
Why rotate at all
- Compromise: a private key leaked is a forgery licence for your domain — the emergency case (§5).
- The 1024→2048 upgrade: RFC 8301 — signers MUST ≥1024, SHOULD ≥2048; verifiers MUST NOT accept <1024. Upgrading is prudent, schedulable, and done via a new selector, never an in-place record edit.
- Hygiene: keys age with staff, vendors and infrastructure. No authority mandates a cadence (“every 6–12 months” is practice, labelled as such) — but a rotation you have rehearsed is worth more than a rotation you improvise during an incident.
- Provider changes: migrations are rotations whether you call them that or not; the overlap method is the safe shape.
The overlap method — four phases
- Publish NEW, old untouched. Generate the new keypair; publish its public key under a new selector name (two records can never share one selector name — RFC 6376 makes multiple records at one name undefined behaviour; coexistence REQUIRES two names). Naming discipline is yours: dated selectors (the RFC's own example style is
january2005/february2005) keep audits sane. - Wait for propagation — verify by querying the new selector's name at your authoritative nameserver (the anatomy from our selector guide).
- Switch signing to the new key. From this moment new mail signs new; old mail in queues/inboxes still validates against the still-published old key. §5.2: “signing should immediately commence with the new private key, and the old public key should be retained for a reasonable validation interval.”
- Retire OLD — later, on evidence. After the interval (§3) AND after DMARC reports show the old selector's volume at zero (§4), remove the old record — or publish it with an empty
p=(explicit revocation, spec-equivalent for verifiers) if you want the tombstone visible.
§3 — how long is the interval? (derived, not decreed)
| Anchor | Number |
|---|---|
| Mail queue lifetimes (RFC 5321 guidance; Postfix default queue life) | ~4–5 days for the last old-signed message to be delivered or die |
| Google's stated DKIM-change window | Up to 48 hours |
| Microsoft's built-in rotation overlap | 96 hours |
| This guide's rule (synthesis, labelled) | Retire no earlier than 7 days after the signing switch (14 = conservative), and only with the §4 report proof |
Why patience is principled, not paranoid — §5.2 again: verifiers “can choose to defer validation, perhaps until the message is actually read.” A message delivered Monday may be validated Friday. The interval serves the reader's pace, not the sender's.
Provider machinery — three different worlds
| Platform | How rotation actually works (per its docs) |
|---|---|
| Google Workspace | Regeneration only — there is no Google “rotation” button. Generate new record: the prefix is your free-text choice (default google; Google's caution: if a key with that prefix already exists, choose a different one) and you pick the bit length (choose 2048). Publish the new selector's TXT, leave the old TXT in place, then Start authentication. (A console warning that generating stops authentication until restarted circulates via practitioner accounts — treat the post-generation state as “verify headers immediately,” which the method requires anyway.) |
| Microsoft 365 | The two-selector machine: both CNAMEs (selector1/selector2) were published at setup; Rotate (Defender portal or Rotate-DkimSigningConfig) flips which selector signs, with the old key continuing to sign through a 96-hour overlap — zero DNS work. One rotation at a time. The upgrade trap: -KeySize 2048 upgrades the next active selector on rotation #1; the standby selector upgrades at rotation #2. One rotation ≠ a fully-2048 domain. |
| SendGrid (the contrast) | With Automatic Security ON, SendGrid “automatically rotates DKIM selector records… periodically” behind your s1/s2 CNAMEs — your rotation plan is no plan (cadence unpublished). With it OFF, you own a static m1 TXT and the manual overlap method above, with no SendGrid-published procedure. |
| Self-hosted / other ESPs | The four-phase method verbatim; your MTA's selector configuration is the switch in phase 3. |
§4 — verification per phase (evidence, not hope)
- After publish: the new selector's exact name returns the new key at the authoritative server.
- After switch: test mail's
DKIM-Signatureshows the news=, and receivers returndkim=pass. Old-signed mail in your own inbox still passes (the old key is up). - Before retire: DMARC aggregate reports grouped by selector (current report format requires the selector in each DKIM auth result — Article #36's reading method) show the old selector at zero volume across a full cycle. That zero is your retirement certificate.
§5 — the exception: compromise inverts the rule
If the private key is compromised, patience becomes the vulnerability: publish the new key, switch signing, and revoke the old key immediately (delete it or empty its p=) — accepting that in-flight old-signed mail will fail, because every hour the old key lives is another hour anyone holding it can sign as you perfectly. The RFC grounds key-compromise handling (§8.3); the trade is deliberate: a bounded set of legitimate failures in exchange for closing a forgery channel. Everything else in this guide assumes a planned rotation.
Traps
| Trap | Reality |
|---|---|
| Editing the key in place under the same selector | Instant mismatch for every message signed by either version during caches' lifetimes; two-keys-one-name is undefined. New selector, always. |
| Rotating M365 once and declaring “2048 done” | Only the active selector upgraded; the standby awaits rotation #2 (documented behaviour, §3 table). |
| Retiring on the calendar instead of the reports | Long-tail mail (queued, deferred-validated, slow lists) outlives tidy schedules. The selector-zero report is the gate. |
| Reusing a selector name across domains/subdomains | Selectors are per-domain keys; reuse muddles reports (the selector in auth_results is how you attribute volume) and audits. |
| Expecting ed25519 from hosted providers | Ed25519 DKIM exists (RFC 8463) with a dual-signing model — in self-hosted stacks. Google/Microsoft's hosted signing documentation doesn't offer it; don't plan a hosted rotation around it. |
FAQ
SHA-1 signatures — urgent?
RFC 8301 prohibits rsa-sha1 (MUST NOT). If your signer still offers it, that's configuration debt to fix in the same calm project as the 2048 upgrade — via the overlap method, not a panicked toggle.
Can I keep the old key forever “just in case”?
An old published key whose private half still exists anywhere is standing forgery surface if it ever leaks. Retire on evidence; archive the record in your notes, not in DNS.
Does rotation affect DMARC?
Alignment follows the signature, so a correct overlap is invisible to DMARC. A botched one shows up exactly where §4 looks: DKIM failures by selector in your aggregate reports.
Sources
RFC 6376 — §3.1 (selector practice, advance publication, retirement interval), §3.6.2.2 (one record per selector), §5.2 (immediate new signing + retained old key; deferred validation), §6.1.2/§8.3 · RFC 8301 (SHA-1 prohibition; 1024 floor/2048 SHOULD) · RFC 5321 §4.5.4.1 + Postfix (queue lifetimes) · Google Workspace Admin Help (generate/prefix/48 h) · Microsoft Learn (DKIM rotation, 96 h, -KeySize semantics) · SendGrid (automatic rotation behind CNAMEs) · RFC 9990 via Article #36 (selector in reports).
Did this guide work for you?
Your reaction tells us whether this guide solved the problem it promised to solve.