Expand description
§mailrs-dkim
RFC 6376 DKIM signature verifier. Pairs with
mailrs-spf and
mailrs-rfc5322 to give
mailrs full ownership of the inbound email-auth stack — together
they replace the mail-auth umbrella crate with shape we control.
§Quickstart
use mailrs_dkim::{verify, HickoryDkimResolver};
use hickory_resolver::TokioResolver;
let inner = TokioResolver::builder_tokio()?.build();
let resolver = HickoryDkimResolver::new(inner);
let result = verify(&resolver, raw_message).await;
// Returns mailrs_dkim::DkimResult: Pass / Fail / Neutral / TempError /
// PermError / None / Policy.§What this crate does (1.0)
- Parse
DKIM-Signature:headers (all tags: v, a, b, bh, c, d, h, l, q, s, t, x, i, z). - Canonicalization: simple/simple, simple/relaxed, relaxed/simple, relaxed/relaxed — all four combinations per RFC 6376 §3.4.
- Body hash computation (SHA-256) with optional length limit (
l=). - Header hash computation over the signed-header list in order,
with the DKIM-Signature value itself appended with the
b=tag cleared (RFC 6376 §3.7). - Public-key fetch: TXT at
<selector>._domainkey.<domain>. - Signature verification:
a=rsa-sha256(covers ~99% of real-world DKIM in 2026). - Returns the seven RFC 8601 vocabulary values:
none / pass / fail / neutral / temperror / permerror / policy. - Pluggable
DkimResolverasync trait — bring your own DNS or use the bundled hickory-backed adapter.
§What this crate does not (yet)
a=ed25519-sha256(RFC 8463) — modern but rare. Deferred to 1.1. The header parser rejects withUnsupportedAlgorithm; treat this asPermError.- Multiple signatures:
verifyfinds the first DKIM-Signature header. Most legitimate mail signs once; some ARC-bridged mail signs multiple times. The trait shape allows a futureverify_allwithout breaking changes. - DSN bounce signature verification — same protocol shape, but the DKIM-Signature is on a different header anchor; future addition.
- Author Domain Signing Practices — historical (RFC 5617), deprecated.
§Why a new crate?
mail-auth includes DKIM but bundles it with SPF + DMARC + ARC. By
the project’s DEPS_AUDIT we want each in a focused stone so:
- the perf of each step is measurable independently
- the API shape is tunable per-RFC
- the crate’s transitive deps stay tight per use case
mailrs-spf shipped first (DEPS_AUDIT #1). This is its sibling.
§Performance
Measured (criterion, M-series Mac, release):
| Operation | Median |
|---|---|
DkimHeader::parse (minimal header) | 147 ns |
DkimHeader::parse (realistic 11-tag header) | 405 ns |
canonicalize_body (simple) | 70 ns |
canonicalize_body (relaxed) | 140 ns |
canonicalize_header (relaxed, one header) | 85 ns |
§Vs. mail-auth 0.9 (the de-facto Rust competitor)
| Input | mailrs-dkim 1.1.3 | mail-auth 0.9 | Winner |
|---|---|---|---|
| minimal (7 tags) | 147 ns | 167 ns | mailrs +12% ✅ |
| realistic (folded, 11 tags) | 405 ns | 423 ns | mailrs +4% ✅ |
We beat mail-auth on both inputs. The 4.6× / 3.5× cumulative speedup
since 1.1.1 came from: (1) single-pass byte scanner replaces HashMap +
unfold pre-pass; (2) byte-level tag dispatch via match name.as_bytes()
(lowercase fast path + case-insensitive fallback); (3) h= signed-
headers parsed via byte-iter with from_utf8_unchecked (safe because
only ASCII-lowercased bytes are pushed). Reproduce via
cargo bench -p mailrs-dkim --bench compare_mail_auth.
Production verify is dominated by:
- DNS lookup for the selector key (5-50 ms)
- RSA-SHA256 signature verification (~1-2 ms for 2048-bit keys)
The bench numbers above are the pure CPU pieces. Reproduce:
cargo bench -p mailrs-dkim --bench dkim.
§License
Apache-2.0 OR MIT. Module layout:
header— DKIM-Signature header parsercanon— header + body canonicalization (simple / relaxed)headers— low-level byte-region helpers (body offset, fold-aware find, b= clear)crypto— standalone RSA-SHA256 / Ed25519-SHA256 signature verify + DNS pubkey parseresolver—DkimResolvertrait + (optional) hickory implverifier— full verify() entry pointerror— error / temp-fail / perm-fail types
Re-exports§
pub use error::DkimError;pub use error::DkimResult;pub use header::Algorithm;pub use header::Canon;pub use header::DkimHeader;pub use resolver::DkimResolver;pub use sign::DkimSigningKey;pub use sign::SignOpts;pub use sign::sign;pub use verifier::SignatureOutput;pub use verifier::verify;pub use verifier::verify_all;pub use resolver::hickory::HickoryDkimResolver;
Modules§
- canon
- Canonicalization (RFC 6376 §3.4).
- crypto
- Standalone signature verification primitives — extracted from
crate::verifierso other crates in the email-auth family (notablymailrs-arc’s AMS / AS verify) can reuse the same RSA-SHA256 + Ed25519-SHA256 verifier without depending on the DKIM-Signature header layout. - error
- Error + result types per RFC 6376 §3.9 / RFC 8601 §2.7.1.
- header
- DKIM-Signature header parsing (RFC 6376 §3.5).
- headers
- Low-level byte-region helpers for navigating an RFC 5322 message buffer without parsing it into owned structures.
- resolver
- DNS resolver trait for DKIM public-key TXT lookups.
- sign
- DKIM signer (RFC 6376 §3.7).
- verifier
- End-to-end DKIM verifier: parse DKIM-Signature → fetch public key → canonicalize → hash → verify signature.