DKIM: selectors, key rotation and 2048-bit keys
How DKIM selectors work, how to publish 2048-bit keys that fit in DNS, and a rotation procedure that never breaks signatures on mail in transit.
How DKIM works
DomainKeys Identified Mail (RFC 6376) lets a sending system sign selected headers and the body of a message with a private key. The signature is added as a DKIM-Signature header, and the matching public key is published in DNS. A receiver fetches the key, verifies the signature and knows the signed parts were not changed since signing.
Two tags in the signature decide where the key lives: d= is the signing domain and s= is the selector. The receiver combines them into a DNS name and looks up a TXT record there. For DMARC, the d= domain must align with the From domain of the message.
Choosing selectors
A selector is just a label, so pick names that make operations easy. Selectors let each sending system have its own key, and they let an old and a new key exist side by side during rotation. The name appears in every signature, so avoid anything you would not want to be public.
| Pattern | Example | Good for |
|---|---|---|
| Per service | mail, news, helpdesk | Knowing which system a key belongs to |
| Per period | s2026a, s2026b | Rotation on a fixed schedule |
| Service plus period | news2026a | Several services with independent rotation |
| Provider default | selector1, selector2, google | Hosted mailbox providers that manage keys for you |
Hosted providers often choose the selector for you. Microsoft 365 uses selector1 and selector2 published as CNAME records pointing to keys it manages, and Google Workspace uses google by default. Other sending services document their own names in their domain authentication settings.
You cannot list a domain's selectors from DNS, because DNS has no directory of names under _domainkey. To find the selector a system uses, read the s= tag in a received message's DKIM-Signature header, for example with the Email Header Analyzer.
The key record
The public key is a TXT record whose value is a tag list. Only p= is required; v=DKIM1 should come first when present. An empty p= means the key has been revoked.
| Tag | Meaning |
|---|---|
v=DKIM1 | Version; recommended, must be first if used. |
k=rsa / k=ed25519 | Key type; rsa is the default. Ed25519 is defined in RFC 8463. |
p= | Base64 public key. Empty means revoked. |
h=sha256 | Acceptable hash algorithms; omitted means all. |
t=y | Testing mode: receivers should not treat failures differently from unsigned mail. |
t=s | Strict: the i= identity domain must equal d=, not a subdomain. |
s=email | Service type; * (default) or email. |
s2026a._domainkey.example.com. 3600 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxyz...IDAQAB"Remove t=y when you are done testing
t=y was meant for trials. Leaving it on production keys invites receivers to ignore verification failures, which weakens the protection DKIM is supposed to give.Moving to 2048-bit keys
RFC 8301 updated DKIM's cryptographic requirements in 2018. Signers must use RSA keys of at least 1024 bits and should use at least 2048 bits, and verifiers must be able to validate keys from 1024 up to 4096 bits. The same RFC says rsa-sha1 must not be used for signing, so every signature should use a=rsa-sha256.
A 1024-bit key still verifies, but it offers a much smaller security margin, and 2048 bits is the norm for new keys. Larger keys than 4096 bits are not guaranteed to verify, so there is no benefit in going beyond that. Ed25519 keys (RFC 8463) are short and strong, but support among receivers is still incomplete, so they are used alongside an RSA signature rather than instead of it.
Fitting a 2048-bit key into DNS
The base64 public key for 2048-bit RSA is around 400 characters. A single TXT string holds at most 255, so the value must be split into several quoted strings that receivers join without spaces. Many DNS panels do this automatically; others need the strings entered separately or reject long values.
s2026a._domainkey.example.com. IN TXT ( "v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu1SU1LfVLPHCozMxH2Mo4lgOEePzNm0tRgeLezV6ffAt0gunVTLw7onLRnrq0/IzW7yWR7QkrmBL7jTKEn5u+qKhbwKfBstIs+bMY2Zkp18gnTxKLxoS2tFczGkPLPgizskuemMghRniWaoLcyehkd3qqGElvW/VDL5AaWTg0nLVkjRo9z+40RQzuVaE8AkAFmxZzow3x+VJYKdr0"
"CDy4jW3O/DmMvPiLqxgPVdl2i1tq+cn8hNQfvCyYe7Tnz4hWDYO0H1vPD1xJyV04BGcoJp1stVpvYy23wu8bN7DI+CWVuW5emFS2bIyCj3Q1YeW4+sPvgOvzP99l1OjMrBb4FBHGKQIDAQAB" )Check the published result with the DNS Lookup using record type TXT for the selector name. The joined value must be exactly the key your signing system uses; a single missing character makes every signature fail with dkim=fail.
CNAME delegation avoids the problem
s1._domainkey.example.com pointing into their DNS. They host the long TXT record and can rotate it without asking you to change anything.Rotating keys without breaking mail
Rotation limits the damage of a leaked private key and retires old, weak keys. The trick is that signatures are verified when mail arrives, which can be minutes or days after signing if a message is delayed or re-verified later. The old public key must therefore stay published for a while after you stop signing with it.
- Generate a new key pair and choose a new selector, for example
s2026b. - Publish the new public key at
s2026b._domainkey.example.comand wait at least the TTL of the record so every resolver can see it. - Verify the record by querying it and, if your system supports it, by sending a test message signed with the new selector.
- Switch signing to the new selector on every system that uses the old one.
- Keep the old public key published for a grace period, commonly one to several weeks, so delayed messages still verify.
- Revoke the old key by publishing
v=DKIM1; p=for the old selector, then remove the record later.
s2026a._domainkey.example.com. IN TXT "v=DKIM1; p="How often to rotate is a policy decision. Many organisations rotate every six to twelve months, and immediately when a private key may have been exposed, for example after a server compromise or when a vendor relationship ends. Hosted providers with CNAME delegation rotate on their own schedule.
Testing a new key before switching
A key that is published incorrectly fails every signature that uses it, so verify before switching production traffic. First query the TXT record for the new selector and compare the p= value with the public key derived from your private key. A single wrong character, a missing string in a split record or an accidental space is enough to break verification.
# public key derived from the private key, as one base64 line
openssl rsa -in s2026b.private.pem -pubout -outform DER 2>/dev/null | openssl base64 -A; echo
# published value (strings joined)
dig +short TXT s2026b._domainkey.example.com | tr -d '" \n'; echoThen sign a test message with the new selector, if your system allows choosing it, and send it to a mailbox at a large provider. The Authentication-Results header should show dkim=pass with header.s=s2026b. Only after that switch all traffic to the new selector.
Signing choices that matter
Canonicalization
The c= tag decides how strictly whitespace and header case are compared. c=relaxed/relaxed tolerates small changes made by mail servers along the way and is the common choice; simple breaks more easily.
Which headers to sign
The From header must always be signed (RFC 6376 §5.4). Sign the headers that give a message its meaning, such as Subject, Date, To, Message-ID and Reply-To. Listing a header name one more time than it appears prevents anyone from adding a second copy of that header without breaking the signature.
Avoid the l= tag
The l= tag signs only the first part of the body. RFC 6376 §8.2 warns that it lets someone append content to a signed message while the signature still verifies, so leave it out.
DKIM and DMARC alignment in practice
A message can carry more than one DKIM signature, and that is common. A newsletter service may add its own signature with d=esp.example.net next to yours with d=example.com. DMARC passes when any signature that verifies is aligned with the From domain, so an extra provider signature does no harm.
Relaxed alignment, the DMARC default, accepts signing domains that share the organizational domain. A signature with d=mail.example.com aligns with a From address at example.com, which lets you give each sending system its own signing subdomain. Strict alignment (adkim=s) requires an exact match and is rarely worth the extra breakage.
| Signature d= | Verifies | Aligned (relaxed) | Helps DMARC |
|---|---|---|---|
example.com | Yes | Yes | Yes |
news.example.com | Yes | Yes | Yes |
esp.example.net | Yes | No | No |
example.com | No (body changed) | Yes | No |
When a service offers "automatic DKIM" without asking for DNS records, it usually signs with its own domain. That passes DKIM but not DMARC alignment, which is exactly the situation the DMARC rollout plan tells you to fix before enforcing.
Protecting private keys
Anyone with your DKIM private key can sign mail that passes DKIM and DMARC as your domain. Treat it like a TLS private key: store it with restricted permissions, keep it out of source repositories and backups that many people can read, and prefer a key management service or the signing platform's own key store. Hosted providers that use CNAME delegation never give you the private key at all, which removes this risk.
Use a separate key per sending system rather than one shared key. When a vendor relationship ends or a server is compromised, you revoke one selector and the rest of your mail keeps passing. Separate keys also make it clear in reports and headers which system signed a given message.
- Generate keys on the system that signs, or in a key management service, not on a laptop.
- Record which selector belongs to which system and who owns it.
- Revoke keys for systems you decommission, instead of leaving them published.
- Rotate immediately when a private key may have been exposed.
DKIM replay and how to limit it
A DKIM signature proves that a message was signed by your domain, not who it was sent to. In a replay attack, someone obtains one legitimately signed message, for example by signing up to a service that lets users send mail, and re-sends it to many recipients. The signature still verifies, so the spam inherits your domain's reputation.
The main defence is not to sign messages whose content an untrusted user controls without rate limits and abuse monitoring. Signing more headers helps, because the attacker cannot change the subject or add headers without breaking the signature. The optional x= tag sets a signature expiry time, which shortens the window in which a copied message still verifies, at the cost of failing genuinely delayed mail.
Troubleshooting dkim=fail
| Symptom in Authentication-Results | Likely cause | Fix |
|---|---|---|
dkim=fail (no key for signature) | Selector record missing or wrong name | Publish the key at <s>._domainkey.<d>; check the zone name is not doubled |
dkim=fail (bad signature) | Key in DNS does not match the private key, or message modified | Compare the published key; check footers added after signing |
dkim=fail (body hash did not verify) | Body changed after signing | Sign after all content filters and disclaimers are applied |
dkim=pass but DMARC fails | d= is the provider's domain, not yours | Enable custom-domain signing in the service |
dkim=neutral / permerror | Syntax error in the key record or unsupported algorithm | Fix the TXT value; use rsa-sha256 |
Send a test message to a mailbox you control, open the original message and paste the headers into the Email Header Analyzer. It shows the SPF, DKIM and DMARC results at a glance, and its JSON export contains every parsed header, including the Authentication-Results line with header.d and header.s.
FAQ
Can a domain have several DKIM keys at once?
Yes. Each selector is a separate DNS name, so every sending system can have its own key, and old and new keys can coexist during rotation.
Is a 1024-bit DKIM key still acceptable?
It still verifies and meets the RFC 8301 minimum, but 2048 bits is the recommended size. Use 2048 bits for new keys and replace 1024-bit keys at the next rotation.
Should I use Ed25519?
Only in addition to RSA. RFC 8463 defines Ed25519 for DKIM, but not every receiver verifies it, so dual signing with an RSA key keeps mail passing everywhere.
How do I find which selector a service uses?
Look at the s= tag in the DKIM-Signature header of a message from that service, or in the DNS records its setup page asks you to add.
What does t=y do?
It marks the key as being tested, asking receivers not to treat verification failures differently from unsigned mail. Remove it once signing works.
Does DKIM survive forwarding?
Usually, as long as the forwarder does not change the signed headers or body. That is why DKIM is the more reliable path to DMARC alignment than SPF.