Hi Steve (and all), I was thinking that we could move the interoperability test suite currently at https://github.com/stalwartlabs/mail-auth/blob/main/src/dkim2/interop_test.rs to https://github.com/dkim2wg, so other implementers can contribute their code directly rather than going through the mail-auth repo. The suite uses testcontainers to build a Docker image covering all four implementations I'm aware of (Rust, Go, Python, and PhoenixDKIM in C).
I'm also happy to leave the interop code in mail-auth and continue adding new implementations there as they come up. Best, Mauro > On 7 Jul 2026, at 12:16, Steve Atkins <[email protected]> wrote: > > > >> On 4 Jul 2026, at 08:25, Mauro De Gennaro <[email protected]> >> wrote: >> >> Hi all, >> >> I wanted to share some news from implementing DKIM2, along with a few >> findings that came out of interop testing. Incidentally, this message is >> itself DKIM2 signed, so if your tooling supports it, feel free to use it as >> a small real-world sample. >> >> I have added DKIM2 support (draft-ietf-dkim-dkim2-spec-03) to mail-auth, the >> Rust library for email authentication, which lives at >> https://github.com/stalwartlabs/mail-auth. One thing worth mentioning is >> that mail-auth also compiles to WebAssembly, so it can be used from >> JavaScript applications and other WASM environments. To make it easy to try, >> I put together a playground at https://mail-auth.stalw.art/ that signs and >> validates DKIM2, as well as DMARC, entirely from the browser, resolving the >> records using DNS-over-HTTP. >> >> DKIM2 is now also supported in Stalwart mail server >> (https://github.com/stalwartlabs/stalwart/), which uses mail-auth >> internally. Beyond signing and verification, I have implemented inbound DSN >> validation for DKIM2 as described in the draft, so that delivery status >> notifications coming back along the chain can themselves be authenticated. >> >> On interoperability, I tested mail-auth against Bron's Python implementation >> (https://github.com/dkim2wg/interop.git) and Steve's Go implementation >> (https://forge.turscar.ie/turscar/dkim2.git). The integration tests are at >> https://github.com/stalwartlabs/mail-auth/blob/main/src/dkim2/interop_test.rs >> and they exercise signing, verification and recipe generation across all >> three implementations, in both directions, including multi-hop chains. The >> good news is that with header folding disabled, every combination passes: >> signing, verifying and recipe based reconstruction all agree across the >> three implementations. > > Nice work! > >> >> I did hit one issue, when mail-auth folds the DKIM2-Signature and >> Message-Instance header fields, which is expected behaviour for long fields >> such as the base64 signature, both the Python and the Go implementations >> fail to parse them. The draft describes in section 2.12 that folding >> whitespace is allowed inside base64 strings and must be ignored when the >> value is used, so I believe mail-auth's output is conformant here, and it >> round-trips cleanly through my own parser. In Steve's Go library the mf= and >> rt= values are base64 decoded in strict mode without first removing the >> folding whitespace, which trips on the embedded space or tab. In Bron's >> Python library the s= value is split on the colon without unfolding first, >> so the algorithm token ends up carrying the leading CRLF and tab, and the >> algorithm comparison then fails. Neither looks hard to fix, and as noted, >> disabling folding on my side makes all tests pass. > > We should add some test vectors to check folding and otehr FWS in all the > places things can be folded, I guess. > >> Finally, a couple of small notes on the spec itself. Overall I found it >> clear, but a few of the sections that describe algorithms in prose would >> benefit from some accompanying pseudocode, in particular the parts covering >> recipe application and the chain walk during verification. It would remove a >> little ambiguity for implementers. The other point concerns header field >> names in recipes. It is not entirely clear from the text whether the JSON >> keys must be lowercased or may retain their original case. Steve's >> implementation expects lowercase and rejects mixed case, whereas I initially >> generated recipes preserving the original header case, which the current >> wording about matching without regard to case seemed to permit. A sentence >> stating the expected behaviour would avoid this divergence. > > The current spec says they’re case-sensitive. There was discussion about > requiring lower case around the time I implemented that bit, and I apparently > got ahead of the spec. > > Cheers, > Steve > _______________________________________________ > Ietf-dkim mailing list -- [email protected] > To unsubscribe send an email to [email protected] _______________________________________________ Ietf-dkim mailing list -- [email protected] To unsubscribe send an email to [email protected]
