<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.19 (Ruby 3.0.2) -->


<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

]>


<rfc ipr="trust200902" docName="draft-gondwana-dkim2-modification-alegbra-01" category="std" consensus="true" submissionType="IETF" obsoletes="4686" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="Email Modification Algebra">A method for describing changes made to an email</title>

    <author initials="B." surname="Gondwana" fullname="Bron Gondwana">
      <organization>Fastmail Pty Ltd</organization>
      <address>
        <postal>
          <street>Level 2, 114 William Street</street>
          <code>3000</code>
          <country>Australia</country>
        </postal>
        <phone>+61 457 416 436</phone>
        <email>brong@fastmailteam.com</email>
      </address>
    </author>

    <date year="2024" month="November" day="20"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 31?>

<t>This memo describes a method for describing the changes made to an email
during common email modifications, for example those caused by mailing lists
and forwarders.</t>

<t>While this is general enough to be used for any changes, it is anticipated that
this method will normally be used for removing added data rather than large
complex changes.</t>



    </abstract>



  </front>

  <middle>


<?line 41?>

<section anchor="background-and-motivations"><name>Background and motivations</name>

<t>Currently, when an email is sent with a DKIM signature, the message can go
through multiple forwarders and still be authenticated, however if a single
change is made to a header which is covered by the signature, or to the body,
then the signature no longer validates - and it's impossible for the receiver
to know what was changed, or even if the entire message was replaced.</t>

<t>By producing a way to describe changes, the recipient can examine the sections
which were changed and determine whether the change was malicious.  Because
each step signs its own changes in DKIM2, this also allows the recipient to
identify exactly which intermediary introduced each change, and adjust their
reputation accordingly.</t>

</section>
<section anchor="delta-format-headers"><name>Delta format - headers</name>

<t>For headers, the format is to completely replace all headers with
a particular name.  For example if you replace the subject and
from address in an email, then you need to include the complete
old headers for each of those:</t>

<t>Header: "DKIM2-Delta-Header:"</t>

<texttable>
      <ttcol align='left'>Command</ttcol>
      <ttcol align='left'>Input</ttcol>
      <c>i</c>
      <c>DKIM2 matching header number</c>
      <c>b</c>
      <c>replace headers with base64 octet value</c>
      <c>t</c>
      <c>replace headers with raw text characters value</c>
</texttable>

<t>Example for a message which has had Subject and From replaced,
and Reply-To added.</t>

<figure><artwork><![CDATA[
From: brong@fastmailteam.com.dmarc.fail
To: dkim2@lists.ietf.org
Reply-To: dkim2@lists.ietf.org
DKIM2-Delta-Header: i=3;
 t=Subject:A replacement for DKIM;
 b=From:YnJvbmdAZmFzdG1haWx0ZWFtLmNvbQo=;
 t=Reply-To
]]></artwork></figure>

<t>Notice that "Reply-To" has no colon, and hence is an instruction to
remove any "Reply-To" headers.  All headers are case insignificant
for removal, and SHOULD be inserted with the case given in the header
when being added back.</t>

</section>
<section anchor="delta-format-body"><name>Delta format - body</name>

<t>This difference format for the body is inspired by <xref target="RFC3284"/>
(The VCDIFF Generic Differencing and Compression Data Format).</t>

<t>Since the transport for the delta is a 7-bit mime header,
this format has been made simple and human readable.  It is a
simple program describing ranges of data to copy from the output
to recreate the input.</t>

<t>Header: "DKIM2-Delta-Body:"</t>

<texttable>
      <ttcol align='left'>Command</ttcol>
      <ttcol align='left'>Input</ttcol>
      <c>i</c>
      <c>DKIM2 matching header number</c>
      <c>b</c>
      <c>insert octets from base64 encoded value</c>
      <c>c</c>
      <c>copy raw octets from range offset-length in new-message body</c>
      <c>d</c>
      <c>copy base64 encoded octets from range offset-length in new-message body</c>
      <c>t</c>
      <c>insert raw octets from value (only usable for some text characters)</c>
      <c>z</c>
      <c>y (if set, MUST be only source) - unspecified change made</c>
</texttable>

<t>Example:</t>

<figure><artwork><![CDATA[
DKIM2-Delta-Body: i=2; c=0-19452; c=20312-150
]]></artwork></figure>

<t>Example - appended to some base64 content; so we need to add back the
last few characters (and the mime trailer)</t>

<figure><artwork><![CDATA[
DKIM2-Delta-Body: i=2; c=0-19452; t=aX==; c=20312-150
]]></artwork></figure>

<t>Example - a URL was substituted in the content of the body (complex, but still
easily doable!)</t>

<figure><artwork><![CDATA[
DKIM2-Delta-Body: i=3;
 c=0-3542;
 b=PGEgaHJlZj0iaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20iPkV4YW1wbGU8L2E+Cg==;
 c=3623-84743
]]></artwork></figure>

<t>The decision whether to use 'b' or 't' is up to the system creating the diff, however
't' has a limited set of characters that are safe to use in headers.</t>

<t>Likewise, it is expected that 'c' will normally be used to copy octets directly from
the new message, however in cases where a message needs to transit 7 bits systems
cleanly, the email modifier may need to re-encode the octets of the original message,
and this allows for doing so.</t>

<t>In the most extreme case, it is possible to place content in the <xref target="RFC2046"/>
preamble or epilogue, either as base64-encoded or raw MIME structures, which
represents the original message.</t>

<t>For example an email which removes an attachment could have:</t>

<figure><artwork><![CDATA[
Content-Type: multipart/mixed; boundary="oldboundary"

This is a multipart message in MIME format.

--oldboundary
Content-Type: text/plain

The message
--oldboundary
Content-Type: application/pdf

A big attachment in base64...
--oldboundary--
]]></artwork></figure>

<t>And the new message:</t>

<figure><artwork><![CDATA[
DKIM2: i=1; ...
DKIM2-Delta-Body: i=1; c=0-45; c=337-13; c=58-39; c=337-13; c=275-78
DKIM2-Delta-Header: i=1;
 b=Content-Type,bXVsdGlwYXJ0L21peGVkOyBib3VuZGFyeT0ib2xkYm91bmRhcnki
Content-Type: multipart/mixed; boundary="newboundary"

This is a multipart message in MIME format.

--newboundary
Content-Type: text/plain

The message
--newboundary--

The following is content which was removed by example.com
forwarding service and is present to allow reconstructing
the original message for DKIM2 verification.

Content-Type: application/pdf

A big attachment in base64...
--oldboundary--
]]></artwork></figure>

<t>In this case, the delta format is using the old boundary string at the very
end as the source three times to recreate each of the old MIME boundaries.
A much simpler though slightly more space hungry version of the same thing
can be done like this:</t>

<figure><artwork><![CDATA[
DKIM2: i=1; n=hi
DKIM2-Delta-Body: i=1; c=0-45; c=276-144
DKIM2-Delta-Header: i=1;
 b=Content-Type,bXVsdGlwYXJ0L21peGVkOyBib3VuZGFyeT0ib2xkYm91bmRhcnki
Content-Type: multipart/mixed; boundary="newboundary"

This is a multipart message in MIME format.

--newboundary
Content-Type: text/plain

The message
--newboundary--

The following is content which was removed by example.com
forwarding service and is present to allow reconstructing
the original message for DKIM2 verification.

--oldboundary
Content-Type: text/plain

The message
--oldboundary
Content-Type: application/pdf

A big attachment in base64...
--oldboundary--
]]></artwork></figure>

<t>Or you can reuse the boundaries from the original message:</t>

<figure><artwork><![CDATA[
DKIM2: i=1; ...
DKIM2-Delta-Body: i=1; c=0-110; c=269-62; c=97-16
Content-Type: multipart/mixed; boundary="oldboundary"

This is a multipart message in MIME format.

--oldboundary
Content-Type: text/plain

The message
--oldboundary--

The following attachment was removed by example.com
forwarding service and is present to allow reconstructing
the original message for DKIM2 verification.

Content-Type: application/pdf

A big attachment in base64...
]]></artwork></figure>

<t>This also reverses back to the original message.</t>

</section>
<section anchor="signature-coverage"><name>Signature coverage.</name>

<t>Each DKIM2 signature implicitly covers all DKIM2-Delta-Body and DKIM2-Delta-Header headers
with an <spanx style="verb">i=N</spanx> value for the same and lower N values as the <spanx style="verb">i=</spanx> on the DKIM2 header.</t>

</section>
<section anchor="iterative-application"><name>Iterative application</name>

<t>To get back to the original message and confirm that it was unchanged, it is necessary
to apply this algorith iteratively.</t>

<t>For example if you receive a message at <spanx style="verb">i=7</spanx> for which there is a modification to the
headers at <spanx style="verb">i=5</spanx> and a modification to both headers and body at <spanx style="verb">i=3</spanx>, to recreate the
original message you would first apply the header changes from <spanx style="verb">i=5</spanx>, then apply the
header and body changes for <spanx style="verb">i=3</spanx>.  If this doesn't create a message which validates
with the initial i=1 signature, then some hop has corrupted the message, and you can
check every single DKIM signature in reverse to find the first one where the message
no longer validates.</t>

</section>
<section anchor="security"><name>Security</name>

<t>TBA</t>

</section>
<section anchor="iana-considerations"><name>IANA Considerations</name>

<t>TBA</t>

</section>


  </middle>

  <back>




    <references title='Informative References' anchor="sec-informative-references">



<reference anchor="RFC3284">
  <front>
    <title>The VCDIFF Generic Differencing and Compression Data Format</title>
    <author fullname="D. Korn" initials="D." surname="Korn"/>
    <author fullname="J. MacDonald" initials="J." surname="MacDonald"/>
    <author fullname="J. Mogul" initials="J." surname="Mogul"/>
    <author fullname="K. Vo" initials="K." surname="Vo"/>
    <date month="June" year="2002"/>
    <abstract>
      <t>This memo describes VCDIFF, a general, efficient and portable data format suitable for encoding compressed and/or differencing data so that they can be easily transported among computers. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="3284"/>
  <seriesInfo name="DOI" value="10.17487/RFC3284"/>
</reference>

<reference anchor="RFC2046">
  <front>
    <title>Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types</title>
    <author fullname="N. Freed" initials="N." surname="Freed"/>
    <author fullname="N. Borenstein" initials="N." surname="Borenstein"/>
    <date month="November" year="1996"/>
    <abstract>
      <t>This second document defines the general structure of the MIME media typing system and defines an initial set of media types. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="2046"/>
  <seriesInfo name="DOI" value="10.17487/RFC2046"/>
</reference>




    </references>



<?line 278?>

<section anchor="changes-from-earlier-versions"><name>Changes from Earlier Versions</name>

<section anchor="draft-gondwana-dkim2-modification-algebra-01"><name>draft-gondwana-dkim2-modification-algebra-01</name>

<t><list style="symbols">
  <t>rename 'DKIM2-Diff' headers to 'DKIM2-Delta'</t>
  <t>add 'z=y' option to DKIM2-Delta-Body for "complete replacement"</t>
  <t>add d= base64 decoding option to DKIM2-Delta-Body</t>
</list></t>

</section>
<section anchor="draft-gondwana-dkim2-modification-algebra-00"><name>draft-gondwana-dkim2-modification-algebra-00</name>

<t><list style="symbols">
  <t>original version</t>
</list></t>

<t>[[This section to be removed by RFC Editor]]</t>

</section>
</section>


  </back>

<!-- ##markdown-source:
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

-->

</rfc>

