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


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

]>


<rfc ipr="trust200902" docName="draft-gondwana-dkim2-modification-alegbra-03" 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="2025" month="October" day="01"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


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


<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'>Tag</ttcol>
      <ttcol align='left'>Value</ttcol>
      <c>i</c>
      <c>DKIM2 matching header number</c>
      <c>a.header.n</c>
      <c>prepend named header with base64 octet value</c>
      <c>b.header.n</c>
      <c>replace named header with base64 octet value (remove and prepend)</c>
      <c>d.header.n</c>
      <c>remove first instance of named header (value: 't')</c>
      <c>r.header.n</c>
      <c>replace named header with raw text characters value (remove and prepend)</c>
      <c>t.header.n</c>
      <c>prepend named header 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;
 r.Subject.0=A replacement for DKIM;
 b.From.0=YnJvbmdAZmFzdG1haWx0ZWFtLmNvbQo=;
 d.Reply-To.0=t
]]></artwork></figure>

<t>Notice that each of these is .0.  If there is more than one edit of the same header name
then they will be .1, .2, etc.</t>

<t>While key names are case insensitive, implementations SHOULD create the header with the same
case as the key.</t>

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

<t>This difference format for the body was originally going to be
an octet-based change format, however this is incompatible with
"relaxed" signature checks as line ending normalisation could
change the octet lengths, so this format was changed to be line
based.</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'>Tag</ttcol>
      <ttcol align='left'>Value</ttcol>
      <c>i</c>
      <c>DKIM2 matching header number</c>
      <c>d.n</c>
      <c>Insert lines by the formula in the value into the output</c>
      <c>z</c>
      <c>If present (value 't') then the program in d.0-N is declared to not recreate a passing hash (e.g. if an attachment has been deleted)</c>
</texttable>

<t>Formulas:</t>

<texttable>
      <ttcol align='left'>Command</ttcol>
      <ttcol align='left'>Input</ttcol>
      <c>b.b64val</c>
      <c>decode the value as base64 an insert the resulting octets as a line</c>
      <c>c.a-b</c>
      <c>insert the numbered lines from a to b inclusive (starting at 1)</c>
      <c>t.value</c>
      <c>insert the text of the value as a line</c>
</texttable>

<t>Example:</t>

<figure><artwork><![CDATA[
DKIM2-Delta-Body: i=2; d.0=c.1-500; d.1=c.520-520
]]></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;
 d.0=c.1-500;
 d.1=b.PGEgaHJlZj0iaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20iPkV4YW1wbGU8L2E+Cg==;
 d.2=c.501-702
]]></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 lines 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>

</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'>



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


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

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

<t><list style="symbols">
  <t>change the header format to have unique keys, making it fit the ABNF for these types
of headers.</t>
  <t>allow easier editing of multi-value headers by always popping the first header and
always prepending newly added headers.</t>
  <t>change body to use d.0, d.1, etc with the program in the value, so that the program
ordering is reliable regardless of the parser used to read the header.</t>
</list></t>

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

<t><list style="symbols">
  <t>change to using line numbers rather than octet offsets</t>
  <t>remove d= base64 decoding capability</t>
  <t>for multiple lines; require a separate b= or t= for each line</t>
</list></t>

</section>
<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>

