Email learning series

DKIM: how an email carries a verifiable signature

By Pedro Paiva

SPF checks a connecting server against an envelope domain. DKIM attaches evidence to the message itself: a signing domain claims responsibility for selected message content using a digital signature.

The sender holds a private key. A receiver retrieves the corresponding public key from DNS and verifies the signature. The private key must remain private; DNS publishes only the public material.

Locate the key from the header

This is an illustrative, deliberately invalid signature. Placeholder values are not cryptographic evidence:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=example.org; s=welcome2026;
 h=from:to:subject:date;
 bh=PLACEHOLDER; b=PLACEHOLDER

d names the signing domain, s names its selector, and h lists signed header fields. The From field must be signed. c=relaxed/relaxed chooses relaxed header and body canonicalization. bh is the hash of the canonicalized body; b contains the cryptographic signature over selected headers and the DKIM-Signature header with its signature value emptied.

The lookup follows directly from selector and domain:

dig welcome2026._domainkey.example.org TXT

The reserved domain has no promised public fixture. On a reader-owned domain, a key record can have the shape v=DKIM1; k=rsa; p=..., where p is base64-encoded public-key material. An empty p revokes that key. Multiple TXT character strings can comprise one record. SES Easy DKIM can use provider-managed keys with CNAME records delegating these lookups, so follow the actual setup instructions instead of inventing a key.

A selector lets a domain rotate keys without changing its domain identity. Publish the new key before signing with it, and keep the old public key available long enough for queued messages signed with the old selector to be evaluated.

A body hash is only one check

A matching bh tells a verifier that the canonicalized body matches the body hash recorded in the header. An attacker could compute a new hash for altered content, so this alone proves no signing authority. Full verification checks the public-key signature, signed headers, algorithms and applicable constraints.

Likewise, finding a key in DNS doesn’t mean the message verifies. You need the actual received bytes and a DKIM verifier. The placeholder header above cannot pass that test.

Some changes are tolerated; others aren’t

Canonicalization turns message bytes into the form used for hashing and signing. Simple header canonicalization preserves header bytes; relaxed header canonicalization lowercases field names, unfolds lines and normalizes whitespace as specified. Neither permits arbitrary changes to header values.

For the illustrative relaxed/relaxed setting:

Change Effect on the canonicalized content
Subject: Welcome → subject: Welcome Header field-name case is normalized; can be tolerated.
More spaces between words in a signed header Relaxed whitespace normalization can tolerate it.
Spaces at the end of a body line Removed under relaxed body canonicalization.
Extra empty lines at the end of the body Ignored by the defined body canonicalization.
Welcome → Goodbye in the signed subject Changes signed content; verification fails.
Add a mailing-list footer to the signed body Changes the full signed body; normally fails.

These examples assume no l= body-length tag, which can limit the signed body prefix and has security implications. Adding unsigned headers can leave a signature valid; DKIM isn’t automatically a signature over every header. Duplicate signed-header handling also matters, so avoid general claims that all formatting changes either pass or fail.

What a valid signature does establish

A valid DKIM signature associates signed content with the signing domain. It does not encrypt the email, certify the sender’s human identity, guarantee safe content, or independently authenticate visible From. d=sender.example.net can sign a message displaying From: hello@example.org; DMARC decides whether an authenticated domain aligns.

Use current algorithm guidance: RFC 8301 disallows RSA-SHA1 and requires stronger RSA keys than early DKIM deployments; RFC 8463 defines Ed25519-SHA256. Provider support varies. For managed SES signing, use supported key lengths and its rotation facilities rather than exposing keys in application logs.

References

  • RFC 6376 — signature fields, canonicalization and verification.
  • RFC 8301 — updated algorithm and key-size requirements.
  • RFC 8463 — Ed25519-SHA256.
  • AWS SES: Easy DKIM — managed signing and DNS configuration.