DMARC Engine
Home/Articles/The complete guide to DKIM
Articles

The complete guide to DKIM

A definitive, standards-accurate guide to DKIM: how signing works, selectors, key length, canonicalisation, the t=y flag, safe key rotation and DKIM alignment for DMARC.

24 June 2026 · DMARC Engine · 14 min read

The complete guide to DKIM

DomainKeys Identified Mail (DKIM) is the cryptographic backbone of modern email authentication. Where SPF authorises which servers may send for your domain, DKIM proves that a message genuinely originated from your domain and that its key headers and body were not altered in transit. It is defined in RFC 6376, and together with SPF it provides the two authentication mechanisms that DMARC builds upon. This guide is the canonical reference for understanding DKIM end to end: how signatures are created and verified, how selectors and keys are published in DNS, the trade-offs around key length and canonicalisation, the meaning of the testing flag, how to rotate keys without breaking mail, and how DKIM alignment ultimately decides whether DMARC passes.

If you only remember one thing: DKIM is not a spam filter and not an encryption layer. It is a signature that lets a receiver verify integrity and origin, and, crucially, lets DMARC tie that verified domain back to the address your recipients actually see.

What DKIM actually does

When a sending mail server signs a message, it computes a cryptographic hash over the message body and a chosen set of headers, then encrypts that hash with a private key it holds secretly. The result is inserted into the message as a DKIM-Signature header. The matching public key is published in your DNS as a TXT record. Any receiving server can fetch that public key, recompute the hashes, and confirm two things:

  • Integrity: the signed headers and body have not been modified since signing.
  • Origin: the message was signed by someone holding the private key for the stated domain.

DKIM does not assert that the message is wanted, safe, or non-spam. A spammer can perfectly validly DKIM-sign their own domain. The value of DKIM comes from who signed and whether that signing domain aligns with the address the recipient sees, which is exactly what DMARC evaluates.

Anatomy of a DKIM-Signature header

A typical signature header looks like this:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
    d=example.com; s=s1._domainkey;
    h=from:to:subject:date:message-id;
    bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;
    b=AbCdEf...signature-bytes...XyZ

The key tags are:

  • v=: the DKIM version, always 1.
  • a=: the signing algorithm, normally rsa-sha256. (rsa-sha1 is deprecated and should never be used.)
  • c=: the canonicalisation used for header/body, e.g. relaxed/relaxed (covered below).
  • d=: the signing domain (the "d=domain"). This is the value DMARC alignment cares about.
  • s=: the selector, naming which public key in DNS to fetch.
  • h=: the ordered list of headers that were signed.
  • bh=: the body hash.
  • b=: the actual signature over the headers (and the body hash).

The receiver reads s= and d=, fetches the public key at <selector>._domainkey.<d-domain>, then verifies bh= against the body and b= against the signed headers. You can inspect any of your own messages with our DKIM checker or by analysing a raw message in the email header analyzer.

Selectors: how DNS finds your key

A selector is simply a label that lets one domain publish many DKIM keys at once. The public key lives at a deterministic DNS name:

<selector>._domainkey.<domain>

So a selector s1 for example.com is published at s1._domainkey.example.com as a TXT record:

s1._domainkey.example.com. IN TXT (
  "v=DKIM1; k=rsa; t=y; "
  "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQ...IDAQAB" )

The record tags are:

  • v=DKIM1: record version (optional but recommended; if present it must be first).
  • k=rsa: key type. RSA is universal; Ed25519 (k=ed25519) is defined but not yet widely verified, so RSA remains the safe default.
  • t=: flags (see the testing flag section).
  • p=: the base64-encoded public key. An empty p= (p=) explicitly revokes the key.
  • Optionally h= (acceptable hash algorithms) and s= (service type, normally * or email).

Selectors are the mechanism that makes everything else practical. Different sending services use different selectors, which is why a single domain commonly publishes several:

  • Google Workspace typically uses google._domainkey.
  • Microsoft 365 uses selector1 and selector2 (it rotates between the two).
  • Marketing and transactional platforms (e.g. SendGrid, Mailchimp, Amazon SES) each provide their own selector(s) for you to publish.

Because each sender has its own selector and key, you can run mail through many providers simultaneously and still sign everything correctly. There is no DKIM equivalent of SPF's 10 DNS-lookup limit. This is one of DKIM's structural advantages and a major reason it survives forwarding better than SPF.

Naming selectors

Selector names are free-form. A sensible convention is to encode rotation or service context, for example s2024q1, mail-202606, or mktg1. Avoid reusing the same selector name when you rotate keys: the whole point of selectors is to let an old and a new key coexist.

Key length: 1024 vs 2048 bits

For RSA keys you choose a modulus length, and the practical options are 1024-bit and 2048-bit.

  • 1024-bit keys were the historical default and are now considered the bare minimum. They are still verified everywhere but offer a smaller security margin. Some providers and security baselines now actively flag them as weak.
  • 2048-bit keys are the modern recommendation and are accepted by all major receivers. They are stronger and they future-proof your signing.

Use 2048-bit unless you have a specific constraint. There is essentially no verification-compatibility downside today; the only friction is publishing the longer key in DNS.

The 255-character DNS string limit

A 2048-bit public key in base64 is longer than the 255-character maximum length of a single character-string inside a TXT record. DNS itself permits a TXT record to contain multiple concatenated strings, so the record is split into several quoted chunks that the resolver rejoins:

s2024._domainkey.example.com. IN TXT (
  "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA"
  "kQ2x...first-half...8fT"
  "Rq9...second-half...IDAQAB" )

The splitting happens at the DNS string boundary, not inside the base64. The strings are concatenated with no separator before decoding. Most DNS providers' UIs handle this automatically when you paste a long value, but if you are editing zone files by hand this is a classic source of "key not found / invalid" errors. If a 2048-bit key won't validate, mis-splitting is the first thing to check. Our DKIM checker reports the reassembled key so you can confirm it decodes correctly, and the DNS record splitter will chunk a long value for you.

Canonicalisation: surviving the journey

Email is notoriously mangled in transit: mailing lists rewrite headers, gateways re-wrap lines, whitespace is normalised. If DKIM hashed the exact raw bytes, almost every forwarded message would fail. Canonicalisation defines how the message is normalised before hashing, and you choose one mode for the header and one for the body via the c= tag (c=header/body).

RFC 6376 defines two canonicalisation algorithms for each part:

  • simple: almost no tolerance. For headers it requires they be unaltered; for the body it only ignores trailing empty lines. Any whitespace or folding change breaks the signature.
  • relaxed: forgiving. It lowercases header names, unfolds and collapses whitespace within headers, removes trailing whitespace from lines, and collapses internal whitespace runs in the body to a single space.

The combinations you will see are written as header/body:

  • simple/simple: most fragile; rarely a good choice.
  • relaxed/relaxed: the recommended default, and what most providers use, because it survives benign reformatting in transit.
  • relaxed/simple: sometimes used where body fidelity matters but header reformatting is expected.

Unless you have a precise reason otherwise, sign with c=relaxed/relaxed. It maximises the chance the signature survives the path to the recipient, which directly improves your DKIM pass rate and therefore your DMARC results.

The l= body-length tag: avoid it

DKIM allows an optional l= tag specifying how many bytes of the body were signed. This was intended to tolerate footers appended by mailing lists, but it creates a real vulnerability: an attacker can append arbitrary content after the signed portion and the signature still verifies. Do not use l=; sign the whole body.

The t=y testing flag

The t= tag in the DNS record carries flags, and the one you must understand is t=y:

  • t=y: testing mode. It tells receivers that the domain is still trialling DKIM and that they should not treat a DKIM failure any more harshly than an unsigned message. In effect, signatures should not be used to make policy decisions.
  • t=s: a stricter flag meaning the i= (signing identity) domain must exactly match d= rather than being a subdomain.

The trap with t=y: it is meant only for the brief period while you confirm your signatures verify, and it must be removed once you go live. If you leave t=y in place, a compliant receiver may discount your valid DKIM signatures, undermining the protection you are paying for. Worse, because DMARC relies on DKIM (and SPF) passing and aligning, lingering test flags can quietly weaken your DMARC posture without any obvious error.

A safe rollout is: publish the key with t=y, send test traffic, confirm with a DKIM checker that messages verify, then remove t=y so the record reads simply v=DKIM1; k=rsa; p=.... Do not skip the removal step.

DKIM alignment: where DKIM meets DMARC

This is the part that ties everything together and the part most often misunderstood. A message can carry a perfectly valid DKIM signature and still fail DMARC, because DMARC does not merely ask "did DKIM verify?". It asks "did DKIM verify and does the signing domain align with the From address the user sees?"

DMARC compares the d= domain of a verified DKIM signature against the domain in the message's From: header (RFC 5322 From). Alignment can be evaluated in two modes, set by the adkim tag in your DMARC record:

  • Relaxed alignment (adkim=r, the default): the organisational domains must match. A d=mail.example.com signature aligns with a From: news@example.com because both share the organisational domain example.com.
  • Strict alignment (adkim=s): the d= domain must match the From domain exactly. d=mail.example.com would not align with From: news@example.com under strict mode.

Worked example. Suppose a marketing platform sends on your behalf and signs with its own domain:

From: news@example.com
DKIM-Signature: ... d=mktg-provider.net; s=abc; ...

That signature may verify cryptographically, but mktg-provider.net does not share an organisational domain with example.com, so DKIM alignment fails. To fix it you configure the provider to sign with your domain: they give you a CNAME or TXT selector to publish under example.com, after which the signature reads d=example.com (or a subdomain of it) and alignment passes. This "custom domain" or "domain authentication" step in your ESP is the single most common DKIM-for-DMARC task.

DMARC passes if either DKIM aligns or SPF aligns. But DKIM-based alignment is the more robust of the two because, unlike SPF, a valid DKIM signature survives most forwarding. The signature travels with the message rather than depending on the connecting IP. For that reason, getting aligned DKIM working for every sending source is the foundation of reaching p=reject safely. You can see exactly which sources are passing and aligning in your DMARC report analysis, and follow the staged rollout in the enforcement journey.

Key rotation with dual-publish overlap

DKIM keys should be rotated periodically, to limit exposure if a private key is ever compromised, and as good hygiene (many organisations rotate every 6-12 months). The danger in rotation is breaking in-flight mail: a message signed minutes ago might be verified hours later after passing through forwarders and queues. If you delete the old key too soon, those legitimately signed messages suddenly fail verification.

The solution is dual-publish overlap using a new selector; never overwrite the existing key in place. The procedure:

  1. Generate a new key pair with a brand-new selector (e.g. rotate from s2025h1 to s2025h2). Use 2048-bit RSA. Generate keys with our DKIM generator or your own tooling, keeping the private key secret.
  2. Publish the new public key in DNS under the new selector. Leave the old selector's record untouched. Both keys now resolve.
  3. Wait for DNS propagation, until TTLs have expired everywhere and the new record is globally visible. Verify with the DKIM checker and, if needed, a DNS propagation checker.
  4. Switch signing to the new key: update the sending system to sign with the new selector and private key. From this moment new mail carries the new selector; old mail in transit still references the old selector, which is still resolvable.
  5. Keep the old selector published through an overlap window, long enough to cover the maximum realistic delivery delay, typically a couple of weeks. Anything still verifying against the old key continues to pass.
  6. Retire the old key once the overlap window has elapsed. Either delete the old TXT record or, more explicitly, revoke it by publishing it with an empty p= (v=DKIM1; k=rsa; p=), which signals that the key is intentionally dead rather than missing.

The non-negotiable rule is never flip-and-delete in one step. Overlap is what makes rotation a zero-downtime operation. If you publish, switch, and immediately remove the old record, you guarantee verification failures for any message that was already signed and is still travelling.

A note on third-party rotation

Many ESPs rotate keys for you automatically when you use their CNAME-delegated selectors: you publish a CNAME pointing at their DNS, and they manage the underlying key and its rotation behind it. Microsoft 365's two-selector design (selector1/selector2) is a built-in dual-publish scheme: it alternates between the two so it can rotate without an outage. When you delegate via CNAME, your job is simply to keep the CNAME in place; the provider handles the overlap.

Common DKIM pitfalls

  • Forgetting to align. A verified signature with a third-party d= does nothing for DMARC. Configure every sender to sign with your domain.
  • Leaving t=y in production. Strip the testing flag once verified, or receivers may ignore your signatures.
  • Mis-split 2048-bit records. The base64 must reassemble exactly; broken quoting is the top cause of "invalid key" errors.
  • Deleting the old key during rotation. Always overlap with a new selector first.
  • Using rsa-sha1 or l=. Both are insecure; sign with rsa-sha256 over the full body.
  • Signing too few headers. At minimum sign From (DKIM requires it). Over-signing volatile headers like Date is usually fine; signing headers that downstream systems add can break verification.
  • Assuming DKIM encrypts mail. It does not. DKIM authenticates, it does not provide confidentiality. Use TLS (and consider MTA-STS) for transport security.

How DKIM fits the wider picture

DKIM is one pillar of a complete email-authentication stack. SPF authorises sending IPs; DKIM signs and proves integrity; DMARC ties both back to the visible From address and tells receivers what to do on failure; MTA-STS enforces TLS on the connection; and BIMI, which requires an enforced DMARC policy and aligned authentication, lets your brand logo appear in the inbox. None of the higher layers work reliably without solid, aligned DKIM underneath.

This is precisely where hosted DKIM earns its place. Managing selectors across half a dozen senders, publishing correctly split 2048-bit keys, remembering to strip t=y, and overlapping rotations by hand is error-prone. With DMARC Engine, key pairs are generated in your browser so the private key is never sent to or stored by us, and the service supports overlapping selectors and sends monthly "rotation due" reminders for any selector older than around 180 days. It prompts and helps you rotate rather than rotating automatically on your behalf. It also monitors that your signatures keep verifying, and surfaces alignment in your DMARC reports so you can reach p=reject without losing legitimate mail.

Next steps

  1. Audit what you have today: check every sending domain and selector with the DKIM checker and confirm each key verifies and decodes.
  2. Move to 2048-bit RSA + relaxed/relaxed wherever you control signing, and remove any leftover t=y flags.
  3. Align every sender: configure each ESP to sign with your domain so DKIM aligns under your DMARC policy.
  4. Adopt overlapping rotation: rotate with a new selector and a generous overlap window; never delete-then-switch.
  5. Watch the reports: use DMARC report analysis to confirm DKIM is passing and aligning across all sources before you tighten to enforcement.

Get DKIM right and aligned, and you have the most durable, forwarding-resilient leg of email authentication firmly in place: the foundation everything from DMARC enforcement to BIMI is built on.

Share

See where your domain stands today

Run a free DMARC scan, then let us take you to enforced p=reject with no email outage.