Hey Wei, I remember a discussion were someone also wanted to assert ADMD boundaries and after reading your proposal and also re-reading Richards, I would like to propose a third way of solving the issue at hand (i.e. enablement of multi-hop in same ADMD signing for forwarders and single-hop multi-signing for differentiation between brands and sender infrastructures) and also provide a way to cryptographically assert ADMD boundaries itself.
A DKIM2 signature i=n could explicitly assert the signing domain expected to produce DKIM2 signature i=n+1. Alternatively, a DKIM2 signature i=n could explicitly assert the signing domain of DKIM2 signature i=n-1 as the domain it continues from. In both cases, the assertion MUST be covered by the DKIM2 signature instance that makes it and therefore protected against modification. * If DKIM2 signature i=n asserts the signing domain of DKIM2 signature i=n+1, DKIM2 signature i=n+1 may omit the mf and rt fields and inherit their effective values from DKIM2 signature i=n. * If DKIM2 signature i=n asserts the signing domain of DKIM2 signature i=n-1, DKIM2 signature i=n-1 may omit the mf and rt fields and inherit their effective values from DKIM2 signature i=n. A relationship between two DKIM2 signature instances MUST be asserted in exactly one direction. If both signature instances assert the same relationship, the relationship is invalid. This keeps the chain of custody unambiguous and reduces replay opportunities by ensuring that each link has exactly one authoritative assertion. This can be repeated across multiple DKIM2 signature instances, creating a chain of signed relationships between consecutive signing domains. If either mf or rt changes between DKIM2 signature instances, the DKIM2 signature instance reflecting the change MUST explicitly assert the new value. Omission is only valid when the effective values remain unchanged. A receiver remains free to apply local policy when evaluating a relationship assertion that directly references the receiver's DKIM2 signature instance, or when inheriting omitted mf or rt values from the immediately related DKIM2 signature instance. If the receiver does not accept such a relationship or inheritance, the DKIM2 chain MUST be treated as invalid. The examples are always from the perspective of the next entity that would add a new instance of the signature header. Bulk Sender Example (simple) Simple if I'm the hop after i=2 it's easy to understand that i=2 was authorized by i=1 to send this and a possible rejection later in this chain would go back to [email protected] DKIM2-signature: i=2 d=esp.example DKIM2-signature: i=1 d=brand.example [email protected] [email protected] nd=esp.example From: [email protected] To: [email protected] Bulk Sender Example (extended) Also simple same result as before. I=1 and i=2 asserted the next hops and I'm as theoretic i=4 am mbp.example and ca deliver that message fine DKIM2-signature: i=3 d=esp.example DKIM2-signature: i=2 d=agency.example nd=esp.example DKIM2-signature: i=1 d=brand.example [email protected] [email protected] nd=agency.example From: [email protected] To: [email protected] Enterprise example from a Bulk Mailer with Forwarding and an SEG The enterpise example also works fine, i=4 can easily validate the chain and gets the mail from [email protected] and i=5 then allows the un-aligned domain change afterwards by asserting the last hop. If I'm now somewhere later in the chain this works out, DKIM2-signature: i=5 d=enterprise.example [email protected] [email protected] ld=security.example DKIM2-signature: i=4 d=security.example [email protected] [email protected] DKIM2-signature: i=3 d=esp.example DKIM2-signature: i=2 d=agency.example nd=esp.example DKIM2-signature: i=1 d=brand.example [email protected] [email protected] nd=agency.example From: [email protected] To: [email protected] This approach effectively reduces header clutter while remaining simple to understand and implement. The relationship between signature instances is explicit and easy for both humans and machines to parse. Expressing multiple signing domains within the same construct introduces additional complexity, as a signature is no longer associated with a single signing domain and additional semantics are required to describe the relationship between domains. The proposed approach keeps that relationship explicit. My late reply to this comes from the time I tried to find a way to abuse this explicitly, I'm aware that any attacker could add hops with assertions, but this is the whole idea, if an attackers asserts the previous hop, he takes ownership and will be punished for spam, and if an attacker asserts the next hop a receiver can easily decide to not accept the message if he is not aware of such a relationship. -- Best regards, Tobias Herkula ________________________________ From: Wei Chuang <[email protected]> Sent: 26 May 2026 21:39 To: [email protected] <[email protected]> Subject: [Ietf-dkim] DKIM2 Multiple Domain Signatures Proposal One problem we've observed in the current DKIM2 proposal is that the synthetic headers described in Section 11.1<https://www.ietf.org/archive/id/draft-clayton-dkim2-spec-08.html#name-add-any-necessary-message-i> imply SMTP boundaries where non-existed. These are needed for enterprise or bulk sender flows to maintain the chain of custody with the added synthetic headers used to link together the mf= and rt= tag with the headers representing actual ADMD boundaries. While they are easily generated and verified, other systems interpreting them may be confused such as NDR bounce handling, and seem to be an unnecessary artifact of the protocol. Can we find an approach that does not require these synthetic headers? First what are those synthetic headers: Enterprise Forwarding Problem Broken forwarding because the chain of custody is not maintained through the mf= and rt=: From: orig@orig DKIM2-signature: i=1; d=orig; mf=orig@orig; rt=recv@recv DKIM2-signature: i=2; d=forw; mf=forw@forw; rt=dest@dest "Fixed" by adding a i=2 synthetic DKIM2 signatures as described in Section 11.1<https://www.ietf.org/archive/id/draft-clayton-dkim2-spec-08.html#name-add-any-necessary-message-i> to link mf= and rt=. From: orig@orig DKIM2-signature: i=1; d=orig; mf=orig@orig; rt=recv@recv DKIM2-signature: i=2; d=recv; mf=recv@recv; rt=forw@forw DKIM2-signature: i=3; d=forw; mf=forw@forw; rt=dest@dest Further the bulk sender pattern implies a synthetic email address where non-existed before. Proposed Multiple Domain Signatures Instead let's collapse the synthetic header into the header generated at the ADMD boundary. We can do this by moving the domain d= into the signature s= and skip generating the synthetic header. If we do this, it implies a set of changes in the DKIM2 signature and chain of custody algorithm. * Move d= domain into the s= signature and drop d= * Each of these signatures signs for the same hash but varies by signing algorithms or private keys * "d=domain; s=selector:rsa-sha256:sigdata" => "s=domain:selector:rsa-sha256:sigdata" * For a given DKIM2 signature header, defines a set of valid domains D across all signature selectors and algorithms Modified chain of custody algorithm * For the i= instance number of DKIM2 signature header, there is an origination i=1 and the highest numbered i=n. These instance numbers of DKIM2 signatures form a continuous sequence of 1..n without skips. * For each DKIM2 signature header i=m in 1..n * mf= domain is DMARC aligned with a domain in the set of DKIM2 signatures D * For each DKIM2 signature header i=m in 1..n-1 * rt= domain is DMARC aligned with a domain in the set of member of DKIM2 signatures D at i=m+1 * For the DKIM2 signature header at i=n, the receiver checks * rt= address must be an exact match to the address of RCPT TO * mf= address must be an exact match to the address of MAIL FROM * Receiver accepts delivery for RCPT TO address (effectively i=n+1) * For a given DKIM2 signature header, if there is more than one signature provided then they MUST all be checked if the verifier is able to do so. * If any signature fails then an error SHOULD be reported * If more than two domains are present then an error SHOULD be reported * The verifier SHOULD check at least 6 signatures (or some TBD reasonable number) in a DKIM2 signature header. Six is supposed to support three algorithms with either the enterprise or bulk sender use case. This is to support some hypothesized new PQC algorithms that haven't been selected but likely to happen. This is in addition to rsa-sha256 and ed25519-sha256 algorithms already specified. * Each domain must have at least one passing signature, with non-passing results only permitted for unknown algorithms. Usage There are scenarios where we want multiple signatures to be associated with a given ADMD that can map to a single DKIM2 signature header. Three cases: * Different algorithms * Forwarder with different receiver and sending domains that occurs with enterprise flows * Bulk senders with multiple signatures to get feedback reports #1 Different Algorithms From: orig@orig DKIM2-signature: i=1; s=orig::rsa-sha256:; s=orig::ed25519-sha256:; mf=orig@orig; rt=recv@recv #2 Enterprise forwarding From: orig@orig DKIM2-signature: i=1; s=orig:::; mf=orig@orig; rt=recv@recv DKIM2-signature: i=2; s=forw:::; s=recv:::; mf=forw@forw; rt=dest@dest #3 Bulk sender multiple signers From: brand@brand DKIM2-signature: i=1; s=brand::; s=platform:::; mf=platform@platform; rt=recv@recv In this bulk sender case, the platform i.e. bulk sender may wish to handle bounces on behalf of the brand. Security Discussion This approach still demonstrates to receivers that the forwarder actually handled the message by signing the message. A subsequent receiver can validate the signatures, and checks for domain alignment using the above process. Alternative Approach Richard Clayton proposes a different approach to identify synthetic headers and addresses without the large changes above. This would keep the synthetic headers generated in Section 11.1<https://www.ietf.org/archive/id/draft-clayton-dkim2-spec-08.html#name-add-any-necessary-message-i>. To paraphrase him, hopefully correctly, he proposes that the synthetic forwarder addresses in the synthetic headers not specify a local-part. The chain of custody tag matching of mf= and rt= would check for domain alignment only. The examples below illustrate how they might look. Note the synthetic headers with missing the local-parts are designated as @domain. #1 Different Algorithms From: orig@orig DKIM2-signature: i=1; d=orig; s=::rsa-sha256:; s=::ed25519-sha256:; mf=orig@orig; rt=recv@recv #2 Enterprise forwarding From: orig@orig DKIM2-signature: i=1; d=orig; mf=orig@orig; rt=recv@recv DKIM2-signature: i=2; d=recv; mf=recv@recv; rt=@forw DKIM2-signature: i=3; d=forw; mf=forw@forw; rt=dest@dest #3 Bulk sender multiple signers From: brand@brand DKIM2-signature: i=1; d=brand; mf=brand@brand; rt=@platform DKIM2-signature: i=2; d=platform; mf=platform@platform; rt=recv@recv Thanks, -Wei
_______________________________________________ Ietf-dkim mailing list -- [email protected] To unsubscribe send an email to [email protected]
