DKIM in 2026: selectors, key rotation, and the signature that breaks in ways you can't see.
DKIM is the strongest evidence in email authentication and the least maintained, because it sits at the awkward junction of cryptography, DNS and organisational ownership. Keys from 2019 still signing, test mode left on for years, selectors nobody can name. Here is how the signature really works, the rotation that doesn't break mail, the weaknesses worth knowing, and an inspector that reads your record.
DKIM, DomainKeys Identified Mail, attaches a cryptographic signature to each outgoing message, made with a private key you hold and verified against a public key you publish in DNS. It proves two things SPF cannot: that the message was signed by someone holding your domain's key, and that the signed content arrived unaltered. The moving parts are few and unforgiving. A selector names which key verifies which signature, and is never reused. The key itself should be 2048-bit RSA in 2026, with shorter keys ranging from weak to already-cracked. Rotation, every six months or so, bounds the damage of a leak you do not know about, and is done with overlapping selectors and a drain period so no mail in transit breaks. Around that core sit the details that decide whether the signature protects you or merely exists: canonicalization that survives real mail servers, an h= list that oversigns the headers attackers duplicate, the l= tag never used, test mode never forgotten, and an inventory so that every key has an owner and a calendar date. DKIM's recurring failure is not cryptographic; it is that nobody owns it.
How the signature works, in the order it happens.
The DKIM-Signature header looks like noise until you know what each part does. Four tags carry the mechanism; the rest are settings.
When your server sends a signed message, it computes two hashes: one of the body, stored in the bh= tag, and one of a chosen set of headers plus the signature header itself, which it then signs with your private key to produce the b= tag, the signature proper. The d= tag names the signing domain and the s= tag names the selector, and together they tell the receiver where to fetch the public key: a TXT record at selector._domainkey.domain. The receiver fetches it, recomputes both hashes from the message as received, and checks the signature. If the body changed, bh= no longer matches; if a signed header changed, the signature fails; if everything matches, the receiver records dkim=pass along with the d= domain, and that domain is what DMARC then compares against your From address for alignment.
Two properties of that flow explain DKIM's place in the stack. The first is that the seal travels with the message: a forwarder that passes the message along untouched passes the signature along too, which is why DKIM survives the forwarding that breaks SPF and why it is usually the sturdier leg for DMARC alignment. The second is that the seal covers exactly what was signed and nothing else. Headers not listed in h= can be added or altered freely; body content beyond an l= limit, if one is set, is invisible to the signature. Most of DKIM's sharp edges live in that gap between what the signature appears to promise and what it was configured to cover, which is why the configuration tags deserve more attention than they usually get.
Selectors: the address system for your keys.
The selector is the most misunderstood part of DKIM, partly because it looks like it should mean something. It is an address, and its rules are about traffic management, not secrecy.
A domain can publish any number of DKIM keys at once, and the selector is what keeps them apart: each signature's s= tag points the receiver at exactly the key that verifies it. That multiplicity is the design, not an edge case. A healthy domain has one selector per sending platform, the workspace mail on one, the campaign platform on another, the transactional sender on a third, plus, during any rotation, the old and new selectors of the same platform live side by side. Per-platform selectors are what make incidents containable: a key leaked from one vendor is one selector revoked, one stream re-keyed, and nothing else touched, and your DMARC reports attribute every signature to the system that made it because the s= tag says so.
The one hard rule is that a selector name, once retired, is never reused. DNS caches records on their own schedules, and mail signed today can be verified days from now after sitting in queues or crossing forwarders, so the old and new contents of a reused name coexist in the wild unpredictably: messages signed with the old key get checked against the new one and fail, and cached old records fail fresh signatures. The cost of a new name is zero, date-based names like s202606 make the register self-documenting, and the discipline removes an entire class of rotation accidents. Naming carries no security, a selector is public the moment a message uses it, so the goal is clarity: a name that tells your future self which platform, which generation, and when.
The DNS record, tag by tag.
The public half of DKIM is one TXT record. Most of its tags are optional, and two of the optional ones cause a disproportionate share of real-world weakness.
The record at selector._domainkey.domain carries v=DKIM1, the version; k=, the key type, rsa by default or ed25519; and p=, the base64-encoded public key, the only truly required payload. Around those sit the tags that change behaviour. t=y marks the key as test mode, a flag meant for the first days of a deployment that tells receivers to go easy on failures, and which quietly discounts your signatures for as long as it remains, which in audits is frequently years. An empty p= is the standard's revocation signal, deliberately distinct from deleting the record: it tells receivers this selector existed and its key is withdrawn, so signatures made with it should fail now, which is exactly what you want after a compromise and indistinguishable from a DNS outage if you delete instead. The h= tag in the record can restrict acceptable hash algorithms, and s= can restrict the key to email service; both are rarely needed and worth leaving alone unless you know why you are setting them.
| Tag | Meaning | Operational note |
|---|---|---|
| v=DKIM1 | Version | First, always |
| k= | Key type (rsa / ed25519) | rsa default; ed25519 per RFC 8463 |
| p= | Public key (base64) | Empty p= = revoked, on purpose |
| t=y | Test mode | Remove after go-live — audit finding #1 |
| h= / s= | Hash / service restriction | Rarely needed |
Inspect a DKIM record.
Paste the TXT value of any DKIM record, yours or a vendor's, and this parses the tags, estimates the key strength from the encoded length, and flags the findings an audit would.
The key-strength estimate is derived from the encoded key length, which maps closely to RSA modulus size; it is a strong heuristic, not a parse of the DER structure. For the signature side, h= lists, canonicalization and l=, read the DKIM-Signature header of a real sent message, since those live in the signature, not the DNS record.
Key length: where the line sits in 2026.
The key-strength question has a settled answer this year, and the history of how it settled is worth thirty seconds because it explains the urgency behind the audits.
RFC 8301 set the modern baseline: rsa-sha256 as the algorithm, 1024-bit keys as the minimum a receiver must accept, 2048 as the practical target. The threat side has since moved faster than the standards side. A 512-bit RSA key, the kind still found signing mail from forgotten appliances, has been factored for a few dollars of cloud compute, which is to say it offers no protection at all; 1024-bit is rated weak, with some receivers flagging it; and 2048 is the working standard that the mailbox providers' bulk-sender rules point at, Gmail naming 1024 as its minimum and recommending 2048 where supported. Longer RSA keys exist, 3072 and 4096, and buy little in practice for DKIM's threat model while costing DNS record size and signing time, which is why 2048 is the consensus rather than the ceiling being pushed.
The interesting 2026 question is Ed25519, added by RFC 8463: keys and signatures a fraction of the size, modern cryptography, and a genuinely cleaner fit for DNS. The honest status is asymmetric adoption, signers support it widely, receivers incompletely, so a domain that switches to Ed25519 alone will fail verification at the laggards, silently, on real mail. The deliberate path is dual-signing, each message carrying an RSA signature and an Ed25519 one under separate selectors, then reading your own DMARC reports to see how the receivers in your actual traffic treat the pair, and deciding from evidence rather than enthusiasm. Default to 2048-bit rsa-sha256 for every new selector, allow 1024 only where a platform documents the limit, treat Ed25519 as a rollout to plan, and inventory any key older or shorter than that as the finding it is.
Canonicalization: why valid signatures fail on valid mail.
The most common DKIM mystery, signatures failing on mail nobody tampered with, usually traces to one setting almost nobody reviews.
Mail servers rewrite messages in small, legal ways as a matter of routine: headers get re-folded across lines, whitespace gets adjusted, trailing blank lines appear and disappear. None of it changes meaning; all of it changes bytes, and a cryptographic hash is a function of bytes. Canonicalization, the c= tag in the signature, is DKIM's answer: it defines how the content is normalised before hashing, so that harmless rewrites do not change the hash. Simple mode normalises almost nothing, so almost any rewrite breaks the signature; relaxed mode collapses whitespace and unfolds headers before hashing, so routine handling leaves the hash intact. The tag takes two values, header and body, written as c=relaxed/relaxed in the configuration that survives the real internet.
The operational rule is short: sign relaxed/relaxed unless you can articulate why not. A simple-mode signature is not more secure in any way that matters, since the hash still covers the same content, and it fails on a meaningful slice of legitimately handled mail, mail that crossed a gateway that re-wrapped a long Subject, a list that adjusted spacing, an appliance that normalised line endings. Those failures are invisible from your side and surface only as a DKIM pass-rate that is mysteriously below 100% in your DMARC reports, the same reports that will show the failures clustering around particular intermediaries. When a sender arrives with that exact symptom, the c= tag is the first thing we read, and more often than not it is the answer.
The weaknesses worth knowing: l=, header injection, and replay.
DKIM has three sharp edges that are exploited in practice, and all three are closed by configuration rather than cryptography.
The l= tag limits the body hash to the first N bytes of the body, a misguided convenience from the standard's early days meant to let mailing lists append footers without breaking signatures. What it means in practice is that everything after the signed length is invisible to the signature: an attacker takes your legitimately signed message and appends their own content, links, payment instructions, an entire fake message body, and the signature still verifies, your domain vouching for content you never wrote. Public demonstrations of exactly this abuse settled the argument. The guidance has no nuance: never sign with l=, audit for it, and treat its presence as a finding to fix the same week.
Header injection is subtler. The h= list in the signature names the headers covered, and a quirk of the standard means that a header listed once is covered once: if the message later gains a second header of the same name, the signature, which covered the first instance, can still verify while the receiver displays the second. The fix is oversigning: list the critical headers, From, Subject, To, Date, one more time than they appear, which signs their absence as well as their presence, so any injected duplicate breaks verification. It costs nothing, is supported everywhere that matters, and closes a real path to displaying a Subject or From that was never signed. Replay is the third edge, and the only one without a clean fix: an attacker who obtains one legitimately signed message, often by sending it to themselves through a platform that signs customer mail, can re-send that exact message at scale, signature intact, your reputation absorbing the result. The mitigations are operational, short signature expiry via the x= tag where your queues allow it, oversigning so the replayed copy cannot be retargeted by added headers, care about which platforms can produce signatures bearing your domain, and an eye on DMARC reports for your own signatures appearing from infrastructure that is not yours, at volumes that are not yours.
Reading the signature header of a real message.
The DNS record is half the picture. The other half lives in the DKIM-Signature header of every message you send, and reading one takes two minutes once you know what each tag is telling you.
Open the raw source of a message your platform sent, find the DKIM-Signature header, and walk it. The d= tag is the signing domain, the identity that DMARC will compare against your From address, and on vendor-signed mail it is the first thing to check, because a vendor signing with its own domain instead of yours produces a valid signature that contributes nothing to your alignment. The s= tag is the selector, which should match an entry in your register; a selector you do not recognise on mail you legitimately sent is the inventory gap this note keeps returning to. The a= tag names the algorithm, rsa-sha256 in almost every healthy configuration, with rsa-sha1 a finding to escalate, since RFC 8301 removed SHA-1 from the standard. The c= tag shows the canonicalization pair, where relaxed/relaxed is the survivable setting, and bh= and b= are the body hash and the signature itself, machine-checked rather than human-read.
Three more tags reward a glance. The h= list is where oversigning is visible: count the occurrences of from in the list, and one occurrence means the header-injection door is open while two means it is closed, the same check applying to subject, to and date. The l= tag should be absent, full stop, and its presence on production mail is the finding to fix this week. The x= tag, if present, is the signature's expiry timestamp, the replay mitigation, and its value is a judgment call: tight enough to limit a replayed message's useful life, loose enough that your own queued and greylisted mail still verifies on delayed delivery, which in practice lands in the range of days rather than hours for most streams. The t= tag here is the signing timestamp, not the test flag of the DNS record, a naming collision in the standard that has confused more than one audit.
This header read is the verification step in every procedure this note describes. After a rotation, the proof is the new s= appearing with dkim=pass in the Authentication-Results of real received mail at several providers. When the DMARC reports show a pass rate below 100%, the headers of the failing slice show whether the c= mode, an intermediary, or a wrong d= is the cause. And when a vendor claims their DKIM is configured, the header settles it in one message: the d=, the s=, the h= list and the absence of l= are all sitting there, readable by anyone who knows the tags, which after this section is you. The DNS record says what a key is; the signature header says what your mail is doing with it, and the two together are the whole observable truth of a DKIM deployment.
Rotation: the procedure that doesn't break mail.
Rotation is where DKIM theory meets the fear of touching production email. The procedure that removes the fear is overlap and drain, and it is the same every time.
The cadence first. M3AAWG guidance says at least every six months, quarterly where the operation supports it; practitioner schedules in 2026 cluster between 90 and 180 days, with twelve months as the outer bound for low-risk domains, and immediate rotation, off any calendar, after a suspected exposure, a vendor offboarding, or a server compromise. The honest qualifier matters more than the number: a messy quarterly rotation causes more damage than a clean annual one, so the right cadence is the fastest your team can execute reliably, tightened as the procedure becomes routine. The reason to rotate at all, absent an incident, is that a private key is a standing credential whose copies accumulate, in backups, in configuration management, in the hands of departed staff and offboarded vendors, and rotation bounds the value of the leak you have not detected. It also keeps the procedure rehearsed, which is the difference between a calm emergency rotation and a panicked one.
The procedure: generate the new pair at 2048 bits; publish the new public key under a new selector, never the old name; verify the record resolves from outside your network. Switch signing to the new selector, and verify dkim=pass with the new s= in the headers of real received mail, several messages, several receivers, because one successful test message is not evidence. Then the step everyone is tempted to skip: leave the old selector published while mail signed with it drains, queued retries, greylisted deliveries, forwarded copies, at least seven to fourteen days, longer for streams with slow queues or heavy forwarding. Two live selectors during the window is the correct state. Only when the old selector's signatures have stopped appearing in your reports does the old record come down, retired, its name never reused. Run per platform, on each platform's own schedule, the whole thing reduces to a calendar entry and a checklist, which is precisely the point.
| Step | Action | Gate before next step |
|---|---|---|
| 1 · Generate | New 2048-bit pair, new selector name | Record resolves externally |
| 2 · Switch | Signing moves to new selector | dkim=pass in real received headers |
| 3 · Drain | Old selector stays published | 7–14+ days, old s= gone from reports |
| 4 · Retire | Old record removed, name never reused | Register updated, next date set |
CNAME delegation: rotation you don't perform, and visibility you give up.
Most vendor DKIM in 2026 is set up a particular way, and it is worth understanding exactly what that way trades.
When a sending platform asks you to publish two or three CNAME records instead of TXT keys, you are delegating the selector: your selector name points into the vendor's DNS, and the vendor hosts the actual key record at the other end. The benefit is real and is why the pattern won: the vendor rotates the key on their side, on their schedule, and your CNAME keeps resolving to the current record, so rotation happens without tickets, change windows, or your involvement at all. For platforms signing on your behalf at volume, that is rotation done more reliably than most internal teams manage, and refusing the pattern to keep TXT control usually buys worse rotation, not better security.
What you give up is visibility and lifecycle control, and both are recoverable with process. The key material, its length and its rotation schedule live with the vendor, so your register records the delegation rather than the key: which selectors are CNAMEs, which vendor each points to, and what the vendor's documented practice is. The lifecycle risk is offboarding: a CNAME left pointing into a former vendor's DNS is a standing grant, a path by which that vendor, or whoever later controls that DNS, can publish a key your domain will vouch for. Vendor offboarding therefore includes the DNS step, the CNAMEs removed the same week the contract ends, and the periodic audit includes walking every _domainkey CNAME and confirming the relationship on the other end still exists and is still wanted. Delegation is the right default for vendor streams; undocumented delegation is how domains end up signing for companies they stopped paying years ago.
The real DKIM problem is that nobody owns it.
The pattern behind almost every weak DKIM posture is organisational, and naming it is most of the cure.
DKIM sits at a seam: DNS belongs to one team, the signing configuration lives with whoever runs mail or with a vendor, and security writes the policy without operating either system. Each party reasonably assumes another owns the keys, and the result is the posture audits find everywhere, 1024-bit keys generated years ago and never touched, t=y still set from a deployment someone tested and forgot to finish, selectors whose purpose nobody can state, CNAMEs pointing at vendors no longer under contract. None of it is a technology failure; the cryptography has been fine for a decade. It is unowned infrastructure decaying at the rate unowned infrastructure decays.
The cure costs one page and one name. The page is the selector register: every selector on every domain, with its key length, its owner, whether it is direct or delegated, the platform it serves, its created date and its next rotation date. The name is the person who owns the page, runs the calendar, and is the answer to "who do I ask about DKIM." Building the register is an afternoon, since your DMARC aggregate reports already list every d= and s= seen signing as your domains, your own message headers show what each platform signs with, and a walk through DNS confirms what is published; reconciling the three lists surfaces the forgotten selectors and the orphaned CNAMEs in one pass. With the register in place, every practice in this note becomes a checklist line instead of a project, and the half of DKIM risk that comes from nobody looking disappears the day someone is assigned to look.
Running it yourself, and where it connects.
On a self-hosted stack the seams disappear, because signing, DNS and policy answer to the same operator. That concentration is the advantage, and it is also the responsibility.
An operator running PowerMTA signs per virtual MTA, which maps key boundaries onto stream boundaries exactly the way the selector-per-platform layout wants: the transactional stream signs with its key under its selector, the campaign stream with another, each on its own subdomain with its own rotation date, and a problem with any one of them is contained by construction. Key generation, the signing configuration and the DNS records are all yours, so there is no vendor to wait on for a 2048-bit upgrade, no delegation to audit, and no ambiguity about who owns the register, while the signatures themselves are verifiable end to end in your own logs and in the DMARC reports you already parse. The same concentration means the discipline is also all yours: the calendar, the drain periods, the oversigned h= lists, the c=relaxed/relaxed, the l= that never appears, because there is no platform upstream quietly doing any of it for you.
DKIM is the third leg of the architecture this cluster has been assembling. The SPF note covers the authorisation layer and its lookup budget, the subdomain strategy gives each stream its own identity to sign for, and the DMARC journey is what turns the evidence into enforcement, with the bulk sender requirements as the floor the providers now hold everyone to. A sender with all four in order, every stream dual-pathed with aligned SPF and a 2048-bit DKIM signature, rotated on a calendar, at DMARC enforcement, is a sender whose authentication survives any single failure, which is the entire design goal. Where it helps to have the keys inventoried, the rotations run, and the whole stack audited by people who operate it daily, that is the work our deliverability audit exists to do, with the ongoing operation running through our email infrastructure and deliverability practice.
Questions senders are asking in 2026.
What does DKIM do that SPF doesn't?
What is a DKIM selector?
Why should I never reuse a selector name?
What key length should DKIM keys be in 2026?
What about Ed25519 keys?
How often should DKIM keys be rotated?
Why rotate keys at all if nothing has gone wrong?
How do I rotate DKIM keys without breaking mail?
What is the t=y tag, and should I use it?
How do I revoke a DKIM key?
What is canonicalization, and why does it break signatures?
What is the DKIM l= tag, and why is it dangerous?
What is header oversigning?
What is a DKIM replay attack?
Should each sending service have its own selector and key?
What is CNAME delegation for DKIM?
How do I find all the DKIM selectors my domain uses?
Does DKIM alone stop spoofing?
A signature is only as good as the key behind it and the calendar in front of it.
We inventory every selector on every domain, flag the weak keys, the test flags and the orphaned delegations, fix the h= lists and the canonicalization, and put the rotations on a schedule your team can run without fear. DKIM that nobody owns decays; DKIM with a register and a name on it just works.