> 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]

Reply via email to