Newsroom
Method7 min read

The signature already sitting in your inbox

By Dylan Wolpe

The short version

  • Practically every institutional email you receive is cryptographically signed by the sending domain, and that signature covers the attachments as well as the body.
  • This makes an ordinary inbox a widely deployed trust anchor that almost no product uses, the coverage problem in verifiable credentials is partly a matter of nobody consuming what already exists.
  • Building a verifier is where it gets unforgiving: we had a bug where valid Ed25519 signatures were rejected, because RFC 8463 signs the SHA-256 digest of the canonicalised headers rather than the headers themselves.
  • Code review did not catch it. A differential harness comparing our output against an established implementation across a matrix of signature variants caught it immediately.

There is a functioning, globally deployed cryptographic attestation system that almost nobody builds on. It has been running for twenty years, your bank uses it, and its output is sitting unexamined in your inbox right now.

What is already there

When an institution sends you mail, its server signs the message with a private key and publishes the matching public key in DNS. Your mail provider checks it silently and shows you nothing, because a passing check is unremarkable.

That check establishes something quite strong:

  • The message was signed by whoever controls DNS for the sending domain.
  • The signed headers have not been altered since.
  • The body has not been altered, including any attachment.

That last point is the interesting one. A PDF statement attached to a signed email inherits a cryptographic link back to the institution. Not a claim that it came from your bank, a checkable fact, using a key your bank published, requiring no cooperation from them and no integration with anyone.

The verifiable-credentials problem is usually framed as institutions needing to start signing things. A large number of them already do, and almost nothing reads it.

Then you try to verify one

The specification is where the enthusiasm meets reality. To check a signature you must reconstruct the exact byte sequence that was signed, and the standard offers multiple ways to do it.

Canonicalisation comes in simple and relaxedvariants, chosen independently for headers and body, so four combinations, each producing different bytes for the same message. Relaxed folds whitespace and lowercases header names; simple demands the message survive transit unmodified, which it frequently does not.

Multiple signatures may be present, and the rule is that any one valid signature is a pass. A verifier that checks only the first is wrong in a way that fails closed and looks fine in testing.

Alignment is a separate concern entirely. DKIM proves some domain signed the message. It does not check that the domain matches the From:address a human reads. Without the DMARC alignment check, a valid signature from an attacker’s own domain is a pass, technically correct and completely useless.

The bug

Our implementation rejected valid Ed25519 signatures. RSA worked. Everything looked right, the code read correctly, and the failure was consistent.

RFC 8463 added Ed25519 to DKIM, and the detail that matters is what gets fed to the verifier:

  RSA path      verify( pubkey, canonicalised_headers,        signature )
  Ed25519 path  verify( pubkey, SHA256(canonicalised_headers), signature )
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ed25519 in DKIM signs the SHA-256 digest of the canonicalised headers, not the headers themselves. RSA's PKCS#1 v1.5 verification hashes internally, so the same code path is correct for one and wrong for the other.

We were passing the raw canonicalised headers to both. For RSA that is correct, because the verification routine hashes internally. For Ed25519 it is not, because Ed25519 signs whatever you hand it, and in this profile the standard specifies that you hand it a digest.

The consequence was a verifier that silently rejected genuine mail from every sender using the more modern algorithm. It fails closed, so nothing looked broken; it simply quietly declined to verify a growing share of legitimate messages.

What actually caught it

Not code review. The code looked correct because it was correct for the case anyone reading it had in mind.

What caught it was a differential harness: a matrix of synthetic messages covering both algorithms, all four canonicalisation combinations, single and multiple signatures, and assorted malformed cases, each verified with both our implementation and an established third-party one, asserting the verdicts match. The Ed25519 rows disagreed immediately.

The harness runs in CI, and the reasoning generalises past email:

  1. Test against an oracle, not against your own expectations. Your tests encode the same understanding your implementation does, so they agree with each other while both misread the specification.
  2. Enumerate the option matrix. Bugs live in the combinations nobody chose deliberately.
  3. Distrust code paths shared across algorithms. The shared path was exactly the bug: one function, correct for one algorithm, wrong for the other.

Why bother

Because it exists now, at scale, with no adoption curve to wait out. Open banking is better where it has been mandated and thin where it has not. Attested sessions are promising and immature. Signed email is deployed today by almost every institution you would want to prove something about, and the only thing missing is software that reads it correctly.

Which brings it back to the anchor problem: the cryptography for proving things without revealing them has been ready for years, and the constraint is having a source a verifier will believe. One of those sources has been sitting in everyone’s inbox the whole time.

Questions people ask about this

What does a DKIM signature actually prove?

That the message was signed by a key published in the sending domain's DNS, and that the signed headers and body have not been modified since. It authenticates the domain, not the human, and it says nothing about whether the content is true, only that the domain vouched for these exact bytes.

Does DKIM cover email attachments?

Yes, when the body hash covers the whole message, which is the normal configuration. That is what makes it interesting as a trust anchor: a PDF statement attached to a signed email inherits a cryptographic link back to the institution that sent it.

Why do DKIM signatures stop verifying over time?

Two reasons. Signing keys are published in DNS and rotate, and once an old key is withdrawn a perfectly genuine old message can no longer be verified. And some mail systems modify messages in transit, rewriting headers, altering encoding, which invalidates the signature even though nothing malicious happened.

Is DKIM enough to trust an email?

On its own, no. It proves some domain signed the message; it does not check that the signing domain matches the visible From address. That alignment check is DMARC's job, and without it a valid signature from an attacker-controlled domain looks like a pass.

Related

More from the newsroom