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]

Reply via email to