Sorry for the delay in replying. Response inline below. On Fri, May 29, 2026 at 7:23 AM Tobias Herkula <tobias.herkula= [email protected]> wrote:
> 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 risk is an adversary trying to hide from the RCPT TO and MAIL FROM check. To prevent, I think i=n-1 approach is probably better. It also means less walking for the verifier. I see you are using "nd=" to define the relationship within an ADMD in a forwarding i.e. i=n to i=n+1 direction. I think this is doable. The risk is an adversary claiming a relationship with a prior ADMD, which I think this covers, though others should opine if there is any risk here. This is similar to Richard's proposal except it uses an explicit new tag "nd=" for the within the ADMD relation. 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 > > PS: a correction in my example. My Section 11.1 cited below is accidentally from the -08 draft. It should really be the latest -02 draft which is Section 8.1 <https://datatracker.ietf.org/doc/html/draft-ietf-dkim-dkim2-spec-02#name-add-any-necessary-message-i> . -Wei > ------------------------------ > *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]
