The DKIM-Signature Header

The DKIM-Signature header

Every DKIM-signed message carries a header named DKIM-Signature:. Open any signed message in Outlook (File → Properties → Internet headers) or Gmail (Show original) and the header is there, usually near the top of the raw source.

It is dense. The first time you read one it looks like noise. Once you know what each field carries, you can read DKIM at the same speed you read SPF.

This lesson walks the header end to end on a real message from isidoregroup.com.

A real example

The full header from a message sent through M365:

DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
    d=isidoregroup.com; s=selector1;
    h=From:To:Subject:Date:Message-ID:Content-Type:MIME-Version;
    bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
    b=KQjW6Yp8H0pNiOoFvdEKvCs2A1qf7uK3JZcLn3xQNb8H+r4d9rTfH1y9...

Eight fields separated by semicolons. Each is a single letter or pair of letters, then =, then a value. We will take them in the order they typically appear.

v — version

v=1

DKIM has had exactly one version since the standard stabilized. You will always see v=1. If you see anything else, it is not DKIM as we know it.

a — algorithm

a=rsa-sha256

The signing algorithm. Two values appear in production:

  • rsa-sha256 — the modern default. RSA signature, SHA-256 hash. Most messages you see will use this.
  • rsa-sha1 — deprecated. SHA-1 is considered broken for collision resistance. Some legacy senders still use it. If you see it, the sender’s DKIM configuration is old.

ed25519-sha256 exists in the spec but is rare. M365 and Google Workspace both use rsa-sha256 by default.

c — canonicalization

c=relaxed/relaxed

How the message was normalized before hashing. Two formats, separated by a slash — first one applies to headers, second to the body.

  • simple — no normalization. The hash covers the exact bytes.
  • relaxed — whitespace and header field names get normalized. Two consecutive spaces collapse to one. Header names lowercase. Trailing whitespace on body lines strips.

relaxed/relaxed is by far the most common. It survives the small modifications mail gateways and mailing lists sometimes make (trimming trailing spaces, re-wrapping headers) without invalidating the signature.

simple/simple is stricter. It survives less. Some high-security setups use it. M365 and Google Workspace both default to relaxed/relaxed.

d — signing domain

d=isidoregroup.com

The domain claiming responsibility for the signature. This is the field that matters for DMARC alignment. DMARC requires the d= value to align with the From: header — strictly (exact match) or relaxed (same organizational domain).

If a message has From: ceo@isidoregroup.com and the DKIM signature has d=isidoregroup.com, DKIM aligns. If the signature instead has d=tenant.onmicrosoft.com, DKIM is valid but does not align — DMARC will not credit it.

When you debug DMARC failures, this is the field you read first.

s — selector

s=selector1

The label that names which public key to fetch. The receiver constructs the DNS hostname:

selector1._domainkey.isidoregroup.com

That is where the public key lives. Different selectors let a domain publish multiple keys at once — important for rotation, covered in 4.6.

This is also the field Cathedra implicitly probes. Lesson 4.3 covers exactly which selectors Cathedra tries.

h — signed headers

h=From:To:Subject:Date:Message-ID:Content-Type:MIME-Version

The list of headers the signature covers. Colon-separated. The receiver re-hashes these specific headers (in the order they appear in the message) and includes them in the verification step.

From: is almost always in this list. A signature that excludes From: from h= is technically valid but worthless — an attacker could rewrite the From line and the signature would still verify. Real senders always include From:. M365 includes a long list by default; Google Workspace’s is similar.

bh — body hash

bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=

The base64-encoded hash of the message body after canonicalization. The receiver re-computes the body hash and compares to this value. If they differ — body modified in transit — the signature fails.

Mailing lists that append a footer (“Unsubscribe from this list:…”) modify the body and break bh. This is the most common reason a DKIM signature fails on real, legitimate mail. Modern mailing-list software re-signs messages with the list’s own domain, which is why you sometimes see two DKIM-Signature headers on list mail.

b — the signature itself

b=KQjW6Yp8H0pNiOoFvdEKvCs2A1qf7uK3JZcLn3xQNb8H+r4d9rTfH1y9...

The actual cryptographic signature, base64-encoded. Long string. Usually wrapped across multiple lines in the raw header.

The receiver decodes this, uses the public key from DNS to verify it against the re-computed hash of (selected headers + body hash), and gets a pass or fail.

Less common fields

The eight above are the ones you see on every signed message. Three more appear occasionally:

  • t — signature timestamp. Unix epoch seconds. When the message was signed.
  • x — signature expiration. Unix epoch seconds. After this time, receivers may treat the signature as invalid.
  • i — identity. A more specific sender identifier, usually i=@isidoregroup.com. Rarely used in M365 or Google Workspace.

You can mostly ignore these. If a client’s mail is being rejected for “DKIM signature expired,” it’s the x= field.

How to find the header in a real message

In Outlook desktop:

  1. Open the message.
  2. File → Properties.
  3. Scroll the “Internet headers” box. Search for DKIM-Signature.

In Outlook web:

  1. Open the message.
  2. Three-dot menu → View → View message source.
  3. Search the source for DKIM-Signature.

In Gmail:

  1. Open the message.
  2. Three-dot menu → Show original.
  3. The header section is at the top of the page.

If you see no DKIM-Signature: header at all on inbound mail from a domain that should sign it, that is your first DKIM finding before Cathedra even runs.

What you should remember

  • Eight fields you must recognize: v, a, c, d, s, h, bh, b.
  • d= is the signing domain. s= is the selector. Together they tell the receiver where to fetch the public key.
  • d= is what DMARC alignment hinges on. Mismatch with From: = DMARC fails on DKIM.
  • bh= is the body hash. Footer injection on a mailing list breaks it.
  • Modern senders use a=rsa-sha256 with c=relaxed/relaxed. SHA-1 is legacy.

Next: which selectors Cathedra probes, and why a “no DKIM” finding might still be a working DKIM setup.


Cathedra alignment: DkimRecordCheck.php — header field semantics inform what selector Cathedra looks for