<?xml version="1.0" encoding="utf-8"?>
<?xml-model href="rfc7991bis.rnc"?>  <!-- Required for schema validation and schema-aware editing -->
<!-- <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?> -->
<!-- This third-party XSLT can be enabled for direct transformations in XML processors, including most browsers -->
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<!-- If further character entities are required then they should be added to the DOCTYPE above.
     Use of an external entity file is not recommended. -->
<rfc
  xmlns:xi="http://www.w3.org/2001/XInclude"
  category="info"
  docName="draft-nurpmeso-dkim-access-control-diff-changes-11"
  ipr="trust200902"
  obsoletes=""

  updates="6376"

  submissionType="IETF"
  xml:lang="en"
  version="3">
<!--
     [CHECK]
       * category should be one of std, bcp, info, exp, historic
       * ipr should be one of trust200902, noModificationTrust200902,
         noDerivativesTrust200902, pre5378Trust200902
       * updates can be an RFC number as NNNN
       * obsoletes can be an RFC number as NNNN
-->
  <front>

   <title>DKIM Access Control and Differential Changes</title>

   <seriesInfo name="Internet-Draft" value="draft-nurpmeso-dkim-access-control-diff-changes-11"/>

    <author fullname="Steffen Nurpmeso" initials="S" role="editor" surname="Nurpmeso">
      <address><email>steffen@sdaoden.eu</email></address>
    </author>

    <date year="2026" month="06" day="16"/>

    <area>General</area>

    <keyword>DKIM</keyword>

    <abstract><t>
      This document specifies a
      DKIM (RFC 6376)
      iteration that allows cryptographical verification of
      SMTP (RFC 5321)
      envelope data,
      and of any signature along the message path,
      even beyond IMF (RFC 5322) message content changes.
      It addresses existing security glitches,
      and introduces active mitigations to embrace collateral damage effects
      of email solutions of the younger past by a standardized solution,
      also by moving complexity away from lower network protocol layers,
      where problems cannot be solved.
      It updates DKIM in certain aspects that reality has proven to be
      superfluous, incomplete, or obsoleted.
    </t></abstract>

  </front>
  <middle>

    <section>
      <name>Introduction</name>
      <t>
        DKIM<xref target="RFC6376"/>
        was not designed to cover
        SMTP<xref target="RFC5321"/>
        envelope data, allowing replay of valid, verifiable messages
        to an infinite set of recipients by malicious third parties,
        undetectable by sender and recipients.

        (Rationale: to aid SMTP delivery to recipients in various conditions
        even the existing but optional "x=" expiration tag timestamp must be
        chosen so far in the future that malicious players have plenty of time
        to misuse messages.)
      </t><t>
        Whereas
        DKIM<xref target="RFC6376"/>
        standardized rudimentary, incomplete approaches to inspect at least
        header field modifications of
        IMF<xref target="RFC5322"/>
        message content that happen along the message path
        (the "z=" tag content; also to point to the "l=" tag),
        the overall design was agreed in not to survive them
        (compare, for example,
        <xref target="RFC6377"/>).
      </t><blockquote>
        The resulting paradigm is
        "as long as one signature can be successfully verified,
        DKIM verification will succeed".
        It is a context-free "take it and accept it" approach.
      </blockquote><t>
        This is problematic as message content changes may be falsely
        attributed to (the) address(es) in the IMF originator field(s).

        Later policy-enforcing standards effectively complicated the
        situation, in that false attribution may now technically be
        avoidable, but mitigations of practice like "user A via B" will
        still be attributed to "A" by a human for one, and, in short,
        anything is valid, if just one signature is.
        (<xref target="RFC9057"/> elaborates more context.)
      </t><t>
        Potentially many signatures may exist in a message.
        DKIM<xref target="RFC6376"/>
        gives hints on how verification can be performed,
        but in practice mitigations are applied in order to reduce
        excessive and useless verifications on hops down the message
        path: elder, especially broken signatures are removed, or renamed,
        as changes are performed on message content.
        Especially mailing-lists, or, in general, hops that cross the
        <xref target="RFC3461"/>
        definition of a <em>"final delivery for the message"</em> act like this.

        A standardized approach to avoid excessive network traffic,
        and, in parts, CPU work during message verification will mitigate
        careless configurations.
      </t>

      <section>
        <name>Conventions and Terminology</name>
        <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL",
          "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT
          RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be
          interpreted as described in BCP 14 <xref target="RFC2119"/>
          <xref target="RFC8174"/> when, and only when, they appear in
          all capitals, as shown here.</t>
        <t>
          The term "FOSS" refers to Free and Open Source Software.
        </t><t>
          The term "privately encrypt" is used to denote that the software
          should take appropriate steps to ensure data encryption and
          key security.
        </t>
      </section>
    </section>

    <section>
      <name>DKIM Vivid Adjustments</name>
      <t>
        This document obsoletes certain unused / incomplete aspects of
        DKIM<xref target="RFC6376"/>,
        and adjusts certain vivid parts as follows.
        The full context of the changes will become clear as the remains
        of this document unfold.
      </t><blockquote>
        <em>Informative remark:</em>
        The protocol changes apply only to signatures signalling compliance
        with the iterated variant presented in this document.
      </blockquote><ul><li><t>
        Temporary errors encountered during DNS record lookups
        <bcp14>MUST</bcp14> be passed through to the
        SMTP<xref target="RFC5321"/>
        layer as such via a 451 or 455 reply code; with
        enhanced SMTP status codes<xref target="RFC3463"/>
        4.4.3 ("routing server failure") or 4.7.5 ("cryptographic failure")
        <bcp14>MUST</bcp14> be used.
      </t><blockquote>
        <em>Informative remark:</em>
        Verification and creation of cryptographic signatures becomes crucial,
        therefore DNS failures can no longer be subject of local policy.
        Among others the DKIM sections
        4.2 "Interpretation",
        6.3. "Interpret Results/Apply Local Policy"
        and
        8.15. "Attacks Involving Extra Header Fields"
        are declared "changed" in meaning to stand back behind this paradigm.
      </blockquote></li><li><t>
        It is herewith clarified that during "relaxed" canonicalization of
        header fields any encountered carriage-return <tt>CR</tt> or line
        feed <tt>LF</tt> <bcp14>MUST</bcp14> be ignored.
        This to make official the approach taken by existing implementations
        to deal with compatibility issues required by IMF (RFC 5322).
        Likewise care has to be taken to ensure that only the sequence
        <tt>CRLF</tt> is interpreted as a line terminator in body processing.
      </t><blockquote>
        <em>Informative remark:</em>
        The milter protocol in widespread use for implementing SMTP extensions
        or support, like DKIM,
        does not pass <tt>CRLF</tt> during header processing,
        but uses <tt>LF</tt>.
        Also because DKIM processing is byte-based,
        and does not know about "quoted-pair" at all,
        the specification could never be complied to in full in reality.
      </blockquote></li><li><t>
        The signature expiration tag "x=" is no longer optional.
        It <bcp14>MUST</bcp14> be used to place a lifetime constraint.
        The maximum "t=" to "x=" delta <bcp14>MUST NOT</bcp14> be
        greater than 864000 seconds
        (ten days: to reach into the next working week).
      </t><t>
        Example delta values for tag auto-generation may be the bounce
        defaults 432000 seconds (five days: used for example by the
        Mailman2 and mlmmj mailing-list managers, and the postfix MTA),
        345600 seconds (four days: OpenSMTPD MTA),
        or 172800 seconds (two days: Exim MTA).
      </t><blockquote>
        <em>Informative remark:</em>
        The DKIM section 5.2 defined "reasonable validation interval
        before [keys are] being removed from the key server" is being
        pointed to in that respect.
      </blockquote><blockquote>
        <em>Informative remark:</em>
        For "ingress" signatures with the DKIM/ACDC "I" flag, as below,
        this limit does not apply:
        it <bcp14>MAY</bcp14> be as high as local policies desire,
        in order to support delayed verification of validation results.
      </blockquote></li><li><t>
        The AUID (DKIM, section 3.5, "i=" tag description)
        <bcp14>SHOULD</bcp14> be used,
        and the value should enable the signer to identify the originator
        for whom it creates the signature.
        The value <bcp14>SHOULD NOT</bcp14> hinder obfuscation,
        for example hiding real (sender etc.) address(es) for the purpose of
        cryptographically protecting email<xref target="RFC9788"/>
        in an end-to-end security scenario<xref target="RFC9787"/>.
      </t></li><li><t>
        Configuration directives to verify that for locally created messages
        SMTP<xref target="RFC5321"/>
        envelope <tt>MAIL FROM</tt> matches the first address of the
        IMF<xref target="RFC5322"/>
        From: header field <bcp14>SHOULD</bcp14> be offered,
        and may be enabled by default.
      </t><blockquote>
        <em>Informative remark:</em>
        Offering an easily accessible constraint to ensure matching identities
        of envelope and message data for messages newly injected into the
        email system prevents an entire type of attack,
        which is not easy to counteract otherwise.
        Since parsing of "RFC5322.From" is a common DKIM operation (compare
        DMARC), bolstering a domains' operational stringency is in good hands.
      </blockquote><blockquote>
        <em>Informative remark:</em>
        Not only for more context on operational email status reading
        <xref target="RFC9057"/>,
        and using the Author: header field described there is recommendet.
      </blockquote></li><li><t>
        DKIM section 3.7 defines how "Computing the Message Hashes" has
        to be performed.
        Different to the RSA algorithm (RFC 8017) solely defined for DKIM
        at the time section 3.7 was written,
        modern algorithms include checksumming themselves.
        Section 3.7 is hereby modified in that the input to "sig-alg",
        the "data-hash",
        can adapt to standardized algorithms as appropriate.
      </t><t>
        If an algorithm chooses adaption,
        "hash-alg" is only used to produce the "body-hash",
        whereas the input formerly used to create the "data-hash"
        is fed in full into "sig-alg", instead of to "hash-alg".
        More formally,
        the new pseudo-code for the signature algorithm is:
      </t><sourcecode><![CDATA[
body-hash = hash-alg (canon-body, l-param)
data-hash = hash-alg (h-headers, D-SIG, body-hash)
signature = sig-alg (d-domain, selector,
                     data-hash / (h-headers, D-SIG, body-hash))
      ]]></sourcecode><blockquote>
        <em>Informative remark:</em>
        An algorithm that exists in "adopted" and "non-adopted" variants
        <bcp14>MUST</bcp14> be treated as a single algorithm.
        For example, a constraint like "one X per algorithm" would not
        allow both variants to be used.
      </blockquote><blockquote>
        <em>Informative remark:</em>
        Different to plain DKIM DKIM/ACDC, as below, requires to keep
        the normalized content of header fields around for consumption
        by the differential changes algorithm.

        The immediate consumption of all input by "hash-alg",
        as was and is implemented by certain (not all) DKIM software,
        can therefore no longer be a primary design goal.

        Whether the larger amount of data ("data-hash" vs all of
        "h-headers", "D-SIG", "body-hash"), when fed into "sig-alg",
        is of negative impact, is to a large extend a digital signature
        quality of implementation, and hardware performance issue.
      </blockquote></li><li><t>
        A new "Key Type" (DKIM section 7.6) is added: "EDA-SHA256".
        It is identical to
        ED25519<xref target="RFC8463"/>
        except for using the above adaption.
        DKIM/ACDC compatible software <bcp14>MUST</bcp14> support
        <xref target="RFC8463"/>
        as well as "eda-sha256".
        The type "eda" <bcp14>MUST NOT</bcp14> be used for the backward
        compatible DKIM-Signature: header fields,
        but only for the "DKIX-" DKIM/ACDC-only variants, as below.
      </t></li></ul>
    </section>

    <section>
      <name>DKIM/ACDC</name>
      <t>
        The
        DKIM<xref target="RFC6376"/>
        iteration Access Control and Differential Changes:
      </t><ul>
        <li><t>
          Changes paradigm: there is absolute trust in public key cryptography.
        </t><blockquote>
          <em>Informative remark:</em>
          A correct cryptographic signature is the only known way to safely
          ensure message validity.
          A failing integrity check is described by
          <xref target="RFC3463"/>
          from 2003 as "<em>the message was corrupted or altered</em>",
          meaning the system is "<em>unable to validate the message</em>".
          Furtherly processing and delegating such a message is misguided,
          not only in a world in which not even communication handshakes
          succeed in an identical situation.
        </blockquote></li><li><t>
          Introduces a flag second:
          base DKIM, and any base DKIM compatibility items introduced below,
          become obsolete after "t=" 2054847098 (0x7A7A7A7A hexadecimal),
          which corresponds to ISO 8601 2035-02-11T22:51:38Z.
          DKIM/ACDC aware software <bcp14>MUST NOT</bcp14> generate nor
          interpret compatibility items when the "t=" tag of signatures
          denotes a larger timestamp.
          It <bcp14>MAY</bcp14> have configuration options to do so much
          earlier, in general or for certain network communication partners.
        </t><blockquote>
          <em>Informative remark:</em>
          A "t=" older than the allowed maximum "t=" to "x=" delta (as above),
          or more than 84421 seconds in the future,
          <bcp14>MUST</bcp14> cause the signature to be ignored,
          or the message to be rejected in case the signature "is vivid";
          in the latter case the reply code 550 is to be used; with
          enhanced SMTP status codes<xref target="RFC3463"/>
          5.4.7 ("delivery time expired")
          <bcp14>MUST</bcp14> be used.
          (A DKIM/ACDC DKIX-Sig: with the highest "sequence" is "vivid".)
        </blockquote></li><li><t>
          Introduces new header fields:
          DKIX-Sig: is the signature,
          DKIX-DC: covers differential changes, as necessary, and
          DKIX-AC: constitutes a access-control signature.
          There is also a "temporary" DKIX-Store: header field.
          They should be treated like trace headers, just like DKIM-Signature:.
        </t><blockquote>
          <em>Informative remark:</em>
          DKIM/ACDC treats the DKIM-Signature: header field as actively
          maintained legacy that is left alone,
          except that any such field generated by DKIM/ACDC aware software
          links to its corresponding DKIX-Sig: successor via the new "w=" tag,
          and may (will) be removed by later DKIM/ACDC aware hops as part of
          active mitigations <xref target="MITIGATIONS"/>:
          the DKIM section 4.2 "Interpretation"
          is cleared away in this respect.
          (Past the flag second any such field <bcp14>MUST</bcp14> be removed.)
        </blockquote><t>
          DKIX signatures <bcp14>MUST NOT</bcp14> be generated with the RSA
          algorithm ("rsa-sha256").
          If a legacy DKIM-Signature: header field is generated,
          it may, or, for maximum compatibility, should be generated with it.
        </t><t>
          Any DKIX header field <bcp14>MUST NOT</bcp14> have <tt>FWS</tt>
          in surrounding the "=" separator in key/value lists.
          More formally, this specification obsoletes the use of <tt>FWS</tt>
          in "ag-spec".
          (DKIM/ACDC thus "reverts" back to "original policies" as used for
          example by
          MIME<xref target="RFC2045"/>.)
        </t></li><li><t>
          Places signatures in an ordered, numbered, random-accessible
          sequence which' state correlate.
          (Signatures generated at the same hop share a sequence number.)
        </t><blockquote>
          <em>Informative remark:</em>
          With DKIM/ACDC it can be, and usually is, sufficient to verify
          only the cheaply detectable highest numbered signature.
        </blockquote></li><li><t>
          Adds reversible data difference tracking,
          and as such supports cryptographical content verification
          of any (DKIM/ACDC aware) intermediate message state,
          up to the initial variant as sent by the author.
        </t></li><li><t>
          Cryptographically protects the
          SMTP<xref target="RFC5321"/>
          envelope, that is,
          <tt>RCPT TO</tt> addresses
          as well as the
          <tt>MAIL FROM</tt>
          address.
        </t><blockquote>
          <em>Informative remark:</em>
          Replay of valid messages to initially not addressed recipients,
          as well as backscatter bounces to random addresses instead of
          the originator, becomes detectable.
        </blockquote></li><li><t>
          The advices of DKIM section 5.4 and 5.4.1,
          "Determine the Header Fields to Sign"
          and
          "Recommended signature content",
          respectively, are replaced with a dedicated
          header field database <xref target="HFDB"/>,
          the members of which <bcp14>MUST</bcp14> be signed.
        </t><t>
          Database members are not announced via the "h=" tag.
          Instead DKIX-Sig: uses a "visualized" bitset that is stored
          in the "hfdb-bits" subtag of the "acdc=" tag.
        </t><blockquote>
          <em>Informative remark:</em>
          For DKIX-Sig: "h=" becomes an optional tag that is only used
          to denote those fields which are not covered by the database.
        </blockquote><blockquote>
          <em>Informative remark:</em>
          The concept of "sealing" or "oversigning", that is,
          the DKIM saying of section 3.5, "h=" tag description, to
          "<em>sign fields not present at the time of signing</em>"
          does not apply.
          Each hop signs the message state it sees,
          and content changes are recorded via DKIX-DC: differential changes.
        </blockquote><blockquote>
          <em>Side note:</em>
          It is not up to DKIM(/ACDC) to decide upon the validity of changes.
          With DKIM/ACDC it is just like today, but in a standardized fashion:
          each hop "mitigates away" elder message instances to create a valid
          signature environment for hops further down the message path.
          Different to today, however, these hops can cryptographically verify
          and inspect elder instances up the path, back to the message author.
          Since DKIM/ACDC
          mitigations <xref target="MITIGATIONS"/>
          require message content changes to "take message ownership",
          this is always visible to and verifiable by end users.
          Oversigning has no meaning:
          without content changes nothing is mitigated,
          with changes mitigations can be unrolled.
        </blockquote></li><li><t>
          Only makes use of the "relaxed" canonicalization type.
          The "simple" variant <bcp14>MUST NOT</bcp14> be used.
          (A rational for choosing "relaxed" is given in the section
          "Further DKIM Updates".)
        </t></li><li><t>
          Allows recognition of certain flagged conditions (along the
          message path) only by looking at the highest numbered signature.
        </t></li><li><t>
          Allows cryptographically verifiable collection of statistics of
          organizational trust (<xref target="RFC5863"/>, section 2.5)
          along the entire message path.
        </t></li>
      </ul><t>
        The
        DKIM<xref target="RFC6376"/>
        iteration Access Control and Differential Changes
        creates DKIX-Sig: signature header fields,
        which are identical to DKIM-Signature: header fields except for the
        new "acdc=" and "dch=" tags,
        the missing "v=" tag,
        and the changed semantics of the now optional "h=" tag.
      </t><t>
        The "dch=" tag holds the checksum of the canonicalized data of all
        existing DKIX-DC: header fields,
        each header field concluded with a <tt>CRLF</tt>,
        sorted in reverse header stack order as defined by
        DKIM<xref target="RFC6376"/>
        section 5.4.2,
        "Signatures Involving Multiple Instances of a Field"
        (which should be equal the reverse "sequence" order),
        with the DKIX-DC: header created for this signature, if any,
        last (at the top of the stack).
      </t><t>
        The "acdc=" tag consists of multiple subtags separated with
        colon (U+003A, :).
        For efficiency reasons it <bcp14>SHOULD</bcp14> be placed
        early, before tags like the new "dch=", but also "bh=", "b=",
        and "h=", or example.
      </t><ul><li><t>
        The tag starts with the "sequence" subtag,
        a decimal number starting at 1,
        or incremented by 1 from the highest DKIM/ACDC "sequence"
        encountered in the message;
        the maximum value is 999:
        if incrementing would result in overflow,
        the message <bcp14>MUST</bcp14> be rejected;
        detected sequence holes <bcp14>MUST</bcp14> also cause
        rejection (but see below);

        in both cases
        SMTP<xref target="RFC5321"/>
        reply code 550 is to be used; with
        enhanced SMTP status codes<xref target="RFC3463"/>
        5.5.4 <bcp14>MUST</bcp14> be used.
      </t><blockquote>
        <em>Informative remark:</em>
        The chosen limit seems sufficiently high to never cause problems
        in practice; compare for example SMTP section 6.3 "Loop Detection".
      </blockquote><t>
        Multiple signature header fields with the same "sequence"
        <bcp14>MAY</bcp14> be generated by a domain, in which case each field
        <bcp14>MUST</bcp14> use a different "s=" selector,
        and maximally one selector per algorithm <bcp14>MUST</bcp14> be used.
      </t></li><li><t>
        The second subtag after "sequence" is "hfdb-bits",
        a "visualized" (base 36) bitset that stores 5 bits per byte
        (examplary C code exists <xref target="HFDB_CODE"/>),
        and records presence of header fields which are part of the
        header field database <xref target="HFDB"/>.
        (Standard conforming messages always have multiple header fields
        announced by "hfdb-bits", but "hfdb-bits" <bcp14>MUST</bcp14> be at
        least presented by "0".)
      </t><blockquote>
        <em>Informative remark:</em>
        The optional "h=" tag is only used for header fields which are not
        included in the database.
        An empty "h=" tag <bcp14>MUST NOT</bcp14> be generated.
      </blockquote></li><li><t>
        The third subtag contains a list of flags that announce state and
        conditions of the message at its current point in the message path.
        If a flag is said to be necessary, all flags that it implies must also
        be set, even if not explicitly mentioned.
        Flag description is normative.
        (Again: note the missing <tt>FWS</tt> separators around "="!)
        ABNF<xref target="RFC5234"/>:
      </t><sourcecode><![CDATA[
# DKIX-Sig:
acdc-tag = %x61 %x63 %x64 %x63 "="
             sequence ":" hfdb-bits ":" 1*flag [ ":" id ]

sequence = 1*3DIGIT; DIGIT from RFC 5234
hfdb-bits = 1*9(%x30-39 / %x41-56 / %x61-76)
flag = "A" / "C" / "D" / "E" / "I" / "L" / "N" / "O" /
       "P" / "R" / "S" / "s" / "T" / "t" / "V" / "v" /
       "X" / "x" / "Y" / "y" / "Z" / "z"
id = *42base64string; optional (bounce) identifier; from RFC 6376

dch-tag = %x64 %x63 %x68 "=" base64string; from RFC 6376 

# DKIX-DC:, DKIX-AC:, [DKIM-Signature:]
link-tag = %x77 "=" sequence
      ]]></sourcecode><dl>
        <dt>A</dt><dd><t>
          Alongside the "V" flag (see there) only:
          all existing signatures were verified.
        </t></dd><dt>D</dt><dd><t>
          The message content was modified at this hop,
          differential changes were generated,
          and are stored in a DKIX-DC: header field.
        </t><t>
          The "Y" flag has to be set.
        </t></dd><dt>C</dt><dd><t>
          The hop signals interest in collection and (periodical) report of
          statistical informations regarding (this) message(s).
          The exact semantics are out of scope for this document.
          As an example of what this could be
          DMARC aggregate reporting (RFC 9990)
          may be mentioned.
        </t></dd><dt>E</dt><dd><t>
          The
          SMTP<xref target="RFC5321"/>
          envelope (<tt>MAIL FROM</tt> and/or <tt>RCPT TO</tt>)
          was modified.
        </t><t>
          The "O" or "N" flag has to be set if the <tt>MAIL FROM</tt> changed.
          The "y" flag has to be set.
        </t><t>
          But for "I"ngress signatures a new
          "Access Control"<xref target="AC"/>
          evaluation has been performed.
          Existing DKIX-AC: header fields <bcp14>MUST</bcp14> be removed.
        </t></dd><dt>I</dt><dd><t>
          This signature header field was generated at ingress.
          Special rules apply to these signatures,
          for example unlimited "x=" tag expiration.
        </t><blockquote>
          <em>Informative remark:</em>
          Such fields offer a cryptographically verifiable message state
          authentication contract: for as long as the ("local") "s="
          selector announced key is available,
          the message state at the time it entered the "local" email
          processing system is assurable by for example user interfaces.
        </blockquote><t>
          All signature instances with this flag set <bcp14>MUST</bcp14>
          be removed when messages enter and leave the email system.
          This is meant as simple: if the flag is set, remove the field.
        </t><blockquote>
          <em>Informative remark:</em>
          If a local "I" message is removed on egress, the newly generated
          DKIX-Sig: overtakes its logical flag subset.
        </blockquote></dd><dt>L</dt><dd><t>
          This hop announces that it supports the
          SMTP<xref target="RFC5321"/>
          extension
          STARTTLS<xref target="RFC3207"/>.
          The flag <bcp14>MUST</bcp14> only be set if any incoming SMTP
          connection will reach a TLS-enabled endpoint.
          <em>Author remark: "Dies mein Abendgruss folgend dem SRV DNSSEC Blues"
          ("here my evening greeting following the SRV dnssec cheatin'").</em>
        </t></dd><dt>N</dt><dd><t>
          The hop detected an unprotected or "irregulary changed" SMTP envelope
          (compare the mutual exclusive "O" flag),
          but the message will be accepted,
          necessarily alongside the "Z" flag.
        </t><t>
          Some non DKIM/ACDC aware hop changed the SMTP envelope.
          If there is a DKIX-AC: header field, the
          access control<xref target="AC"/>
          check <bcp14>MUST</bcp14> instead fail
          if (at least the domain of) the <tt>MAIL FROM</tt> is unchanged.
        </t><t>
          The "E" flag has to be set.
        </t><blockquote>
          <em>Informative remark:</em>
          Except for messages with "sequence" 1 the "N" state is usually
          mitigated <xref target="MITIGATE"/>,
          causing the "O" flag condition.
        </blockquote></dd><dt>O</dt><dd><t>
          This hop claims the message origin.
        </t><t>
          This either means that the message originated at this hop,
          in which case the signature (usually, DKIM-typical) refers to
          the first address of the From: header field,
          and the "sequence" is 1.
        </t><t>
          Or it means the current hop was the, quoting
          <xref target="RFC3461"/>,
          <em>"final delivery for the [original] message"</em>,
          that the message got a <em>"new envelope return address"</em>,
          that is, the <tt>MAIL FROM</tt> of the SMTP envelope was changed.

          In this case the "E" flag has to be set.
        </t></dd><dt>P</dt><dd><t>
          Postmaster mode.
          With this flag set the behavior of DKIM/ACDC borders test
          mode in that rejections must not occur (due to DKIM/ACDC).
          This is to allow for a communication possibility window in
          a situation where messages would always be rejected, due to
          misconfigurations et cetera, and as such reflects
          SMTP<xref target="RFC5321"/>
          section 4.5.1 Minimum Implementation.
        </t><t>
          If the "sequence" is 1,
          message recipients have to be inspected.
          If the
          IMF<xref target="RFC5322"/>
          header fields To: and Cc: only contain a single addressee with
          the local-part
          postmaster<xref target="RFC1123"/>,
          and if the same "postmaster" is addressed as the only
          SMTP<xref target="RFC5321"/>
          <tt>RCPT TO</tt> recipient,
          then the "P" flag has to be set.
        </t><t>
          Once set, all future DKIM/ACDC signatures must copy it.
          It <bcp14>MUST</bcp14>, however, be removed when in conjunction
          with the "E" flag the according SMTP envelope conditions are no
          longer satisfied.
        </t></dd><dt>R</dt><dd><t>
          Reputation check to collect
          organizational trust (<xref target="RFC5863"/>, section 2.5)
          along the signature chain was performed.
        </t><t>
          On top of the "V" (and possibly "A") flag(s) this means that
          all differential changes have been applied,
          and all signatures (at least one per "sequence") along the
          chain have been verified,
          and the entire chain validated correctly.
        </t><t>
          Only in signatures with a "sequence" greater than 1,
          and without the "z" flag.
        </t><blockquote>
          <em>Informative remark:</em>
          The presence of "R" reveals local state publically;
          however, in a chain of trust this seems desirable even.

          The use of organizational trust may for example mean to
          perform full reputation checks more and more sparingly,
          the higher the trust, falling back to only random checks.
          (For a more complete example, see
          <xref target="RFC5863"/>, section 2.5.)
        </blockquote></dd><dt>S and s</dt><dd><t>
          Only in conjunction with the "I" flag: upon ingress the
          SPF<xref target="RFC7208"/>
          state was, or was not, respectively, successfully verified.
        </t><blockquote>
          <em>Informative remark:</em>
          From DKIM/ACDC's point of view SPF is legacy, and it actively
          mitigates <xref target="MITIGATE"/>
          it to transpose trust to DKIX-AC: (also see the "N" flag).
          With DKIM/ACDC SPF users can announce the strict <tt>-all</tt>
          mode that allows SPF verifiers to apply policy.
        </blockquote></dd><dt>T</dt><dd><t>
          This hop requires complete trust to be put into its signature.
          In general all DKIX-DC: header fields were removed,
          applying changes for verification of elder signatures is
          therefore impossible.
          Corresponding additional flags have to be set, like "Z".
          Please read about the "t" flag.
        </t></dd><dt>t</dt><dd><t>
          This is like "T",
          except that DKIX-DC: header fields are not (yet) removed,
          so that elder signatures (to the extend as indicated by the
          usual DKIM/ACDC flag machinery) can be verified.
        </t><blockquote>
          <em>Informative remark:</em>
          the "T" and "t" flags are meant to adapt to operational reality.
          There "trusted proof points" are hired to handle email, to apply
          all the necessary checks for, and removal of spam, malicious,
          dangerous, or otherwise undesired message (MIME part) content,
          before passing the results further to their real recipients.

          As of today only the "equivalent of T" is a known mode of operation;
          DKIM/ACDC, however, allows for a new business model via "t":
          the "trusted proof point" readily prepares messages just like today,
          but also creates and includes a DKIX-DC: header field to undo these
          modifications, as well as keeping all elder DKIX-DC: header fields
          intact.
          (Read: simply through the normal DKIM/ACDC mode of operation,
          except for setting the "t" flag in addition.)

          Turning a "t" message into a "T" message practically means nothing
          but removing the DKIX-DC: header fields:
          an operation that can fastly and safely be performed by simplemost
          command line utilities or scripting languages,
          thanks to the plain-text nature of
          SMTP<xref target="RFC5321"/>,
          of
          IMF<xref target="RFC5322"/>
          messages.

          DKIM/ACDC aware software <bcp14>MAY</bcp14> also offer a mode which
          removes DKIX-DC: header fields after the signature verification step
          (and creation of an "I" signature) for messages tagged "t" coming
          from a configurable "trusted proof point".
        </blockquote><blockquote>
          <em>Informative remark:</em>
          because DKIX-DC: header fields are covered by the "dch=" hash,
          removing them still allows for successful signature verification,
          simply by trusting the original "dch=" checksum.

          DKIM/ACDC's "t" flag allows customers to perform a complete "R"
          reputation check on data delivered by "trusted proof points".
          (To be written or extended message access software could also be
          allowed to access more portions via DKIX-DC:.)
          It is only their users verifying "I" ingress signatures who have
          no option but putting trust into "dch=" hashes.
        </blockquote></dd><dt>V</dt><dd><t>
          DKIM/ACDC signature verified successfully.
        </t><t>
          The signature with the highest "sequence" has been verified
          correctly,
          the (otherwise untested) DKIM/ACDC signature chain is complete,
          and their flags make sense (in the sequence).
          In conjunction with the flag "R" even deeper inspection was
          performed.
        </t><t>
          If multiple signatures with the same highest "sequence" exist,
          the verifier behavior is unspecified in that "V" signals
          success: at least one signature was checked, and all tested
          signatures verified successfully.
          If however all signatures were verified,
          the "A" flag <bcp14>SHOULD</bcp14> be set;
          in single-signature cases the "A" flag <bcp14>MAY</bcp14> be
          omitted.
        </t><t>
          Only in signatures with a "sequence" greater than 1.
        </t></dd><dt>v</dt><dd><t>
          DKIM signature verified successfully.
        </t><t>
          In signatures with "sequence" 1,
          then missing the "O", but with the "N" flag,
          it means the message originated at a non DKIM/ACDC aware hop,
          and normal DKIM processing was performed and succeeded.
          If the signature covering "RFC5322.From" verified
          the "Z" flag must be set, otherwise "z".
        </t><t>
          In messages with a higher "sequence" it comes alongside
          the "X" flag: necessarily the DKIM/ACDC chain was broken, and the
          message changed, by an intermediate non DKIM/ACDC aware hop.
          The "z" flag must be set.
        </t></dd><dt>X</dt><dd><t>
          DKIM/ACDC verification failed.
          Also see "v" and "x" flags.
        </t><t>
          The "z" flag must be set.
        </t></dd><dt>x</dt><dd><t>
          "Plain old DKIM verification" failed,
          or there was no (more) signature to verify.
        </t><t>
          In signatures with "sequence" 1,
          then missing the "O", but with the "N" flag,
          it means the message originated at a non DKIM/ACDC aware hop,
          and normal DKIM processing was performed and failed.
          The "z" flag must be set.
        </t><t>
          Otherwise, with an existing DKIM/ACDC chain,
          it comes alongside the "X" flag: necessarily the chain was broken,
          and the message changed, by an intermediate non DKIM/ACDC aware hop.
          The "z" flag must be set.
        </t></dd><dt>Y</dt><dd><t>
          The message has seen
          IMF<xref target="RFC5322"/>
          modifications:
          somewhere along the chain the message data was modified.
          Once set, all future DKIM/ACDC signatures must copy it.
        </t></dd><dt>y</dt><dd><t>
          The message has seen
          SMTP<xref target="RFC5321"/>
          envelope modifications:
          somewhere along the chain the envelope was modified.
          Once set, all future DKIM/ACDC signatures must copy it.
        </t></dd><dt>Z</dt><dd><t>
          Announces the DKIM/ACDC chain is incomplete.
          The message was processed by DKIM/ACDC unaware hops.
          However, the message verifies correctly and seems to have
          never been modified non-reversibly.
          Once set, all future DKIM/ACDC signatures must copy it,
          unless later downgraded to the "z" flag.
        </t></dd><dt>z</dt><dd><t>
          The message has seen non-reversible modifications,
          and cannot be cryptographically verified back to its origin.
          Once set, all future DKIM/ACDC signatures must copy it.
        </t><t>
          When a message newly enters, or "reenters", the "z" state,
          all existing DKIX-DC: header fields <bcp14>MUST</bcp14> be removed.
        </t><blockquote>
          <em>Informative remark:</em>
          Often "z" signals a condition that <bcp14>MUST</bcp14> cause
          message rejection,
          for example in conjunction with the "x" flag.
          Local policy <bcp14>MAY</bcp14> behave differently for certain
          conditions, but <bcp14>SHOULD NOT</bcp14>, as the flag combination
          may reduce the hops
          organizational trust (<xref target="RFC5863"/>, section 2.5).
        </blockquote></dd><dt>"id"</dt><dd><t>
          The optional "message and bounce identifier" offers enough room for
          Universally Unique IDentifiers<xref target="RFC9562"/>.
        </t><blockquote>
          <em>Informative remark:</em>
          It <bcp14>MAY</bcp14> be generated to help sending domains to
          uniquely identify messages within the "t=" and "x=" time delta,
          as well as to ensure that successively sent identical messages
          are not detected as being the same.
          It <bcp14>MUST</bcp14> be generated if the signature does not cover
          a Message-ID: header field,
          and it <bcp14>SHOULD</bcp14> be used if the uniqueness of the
          "msg-id" is dubious.
        </blockquote><blockquote>
          <em>Informative remark:</em>
          Receiving domains <bcp14>SHOULD NOT</bcp14> use this identifier
          due to the denial of service attack surface,
          regardless of collected organizational trust.
        </blockquote></dd>
      </dl><t>
        Unknown flags <bcp14>MUST</bcp14> be ignored.
        Invalid flag combinations and flag misuse, as far as detectable,
        and false "hfdb-bits" specifications
        <bcp14>MUST</bcp14> result in rejection with SMTP reply code 550;
        if enhanced status codes<xref target="RFC3463"/>
        are used, 5.5.4 <bcp14>MUST</bcp14> be used.
      </t></li></ul>
    </section>

    <section>
      <name>The DKIX-Store header field</name>
      <t>
        The DKIX-Store: header field has no meaning in the email system.
        The sole purpose of mentioning it is to announce that it
        <bcp14>MUST</bcp14> be removed when messages enter
        and leave the email system.
      </t><t>
        It could for example be temporarily created and used by
        non-integrated mail solutions that consist of otherwise unrelated
        software, to pass informational data in between the "ingress" and
        the "egress" processing side.
        To address possible software bugs and configuration errors
        this specification enforces removal of all occurrences.
      </t><blockquote>
        <em>Informative remark:</em>
        In order to achieve locality it is suggested to "privately encrypt"
        data passed around in this temporary header field.
      </blockquote>
    </section>

    <section anchor="AC">
      <name>Access Control</name>
      <t>
        SMTP<xref target="RFC5321"/>
        delivers messages to individual domains.
        With DKIM/ACDC, whenever a SMTP envelope is created or changed,
        all distinct domain-names found within the list of intended
        SMTP envelope <tt>RCPT TO</tt> addressees are collected,
        because messages need to be actively forged on this individual domain
        base:
        DKIM/ACDC will create and include DKIX-AC: header fields covering SMTP
        envelopes as messages are sent to individual domains.
      </t><t>
        The domains' _dkimacdc DNS entries, as below, are queried.
        Dependent upon the detected state the DKIX-AC: header fields will either
        contain exact envelope info (DKIM/ACDC supported), or only domain names.
      </t><t>
        In any case the completely prepared message,
        including the readily prepared signatures, is forged,
        (a) DKIX-AC: header field(s) is/are generated which cover(s)
        the logical recipient subset,
        and the resulting message is then sent.
      </t><blockquote>
        <em>Informative remark:</em>
        MTA-integrated DKIM/ACDC implementations can create
        <em>perfect fit</em> DKIX-AC: header fields only for recipients truly
        accepted by the receiving MTA (not hindering even
        SMTP pipelining<xref target="RFC2920"/>),
        and use successive transmissions until all recipients have been worked.
      </blockquote><t>
        DKIM/ACDC aware recipient domains are expected to manage
        a DKIX-AC: identity cache to mitigate replay attacks.
        (Hint: a verified DKIX-AC: signature seems like a natural cache
        key source, see below.)
      </t><blockquote>
        <em>Informative remark:</em>
        The now mandatory and constrained "x=" tag allows for finite
        identity cache sizes.
      </blockquote><blockquote>
        <em>Informative remark:</em>
        <em>Perfect fit</em> DKIX-AC: header fields can create write-once
        cache entries.
      </blockquote><t>
        A DKIM/ACDC aware hop that receives a message that contains at least
        one DKIM/ACDC enabled signature, and that does not contain a DKIX-AC:
        header field <bcp14>MUST</bcp14> reject it with SMTP reply code 550; if
        enhanced status codes<xref target="RFC3463"/>
        are used, 5.5.4 <bcp14>MUST</bcp14> be used.
      </t><t>
        It <bcp14>MUST</bcp14> reject messages which fail the signature
        check of a DKIX-AC: or signature header field,
        or the condition and flag check verification,
        with SMTP reply code 550;
        the enhanced status code <bcp14>MUST</bcp14> be
        5.7.7 ("message integrity failure").
      </t><t>
        It <bcp14>MUST</bcp14> likewise fail if the DKIX-AC: header field
        does not correspond to the SMTP envelope data,
        with exceptions as documented for the "N" flag of the "acdc="
        tag of DKIX-Sig:natures.
      </t><t>
        It <bcp14>MUST</bcp14> test for a superset of recipients,
        and only fail if an envelope recipient is not included in the
        DKIX-AC: header field.
        DKIX-AC: header fields with an "ec=" are treated specially.
      </t><t>
        Senders <bcp14>MAY</bcp14> use
        Delivery Status Notifications<xref target="RFC3461"/>
        to fine-tune the resulting behavior.
      </t>

      <section>
        <name>The DKIX-AC header field</name>
        <t>
          The syntax of this header field is the usual semicolon
          separated list of DKIM-style tags of unspecified order;
          unknown tags <bcp14>MUST</bcp14> be ignored.
          It is used to cryptographically link the SMTP envelope to the sent
          IMF<xref target="RFC5322"/>
          mail message.
        </t><t>
          The "w=" tag is the linked DKIX-Sig: "sequence", best placed early.
          Multiple signatures with the same "sequence",
          but different algorithms, may exist,
          and so may DKIX-AC: header fields.
        </t><t>
          The selector of the linked signature is given by the "s=" tag,
          the used algorithm can be deduced from there.
        </t><t>
          The "o=" tag is the domain of the
          SMTP<xref target="RFC5321"/>
          <tt>MAIL FROM</tt>,
          the "f=" tag denotes the "local-part".
        </t><blockquote>
          <em>Informative remark:</em>
          In conjunction with the "acdc=" "N" flag these do not correspond
          to the "local email system".
        </blockquote><t>
          The "d=" tag value is the recipient domain,
          with one to multiple "t=" tag(s) for the "local-part"s
          of <tt>RCPT TO</tt>s.
        </t><blockquote>
          <em>Warning:</em>
          The "d=" tag may have an empty value alongside "P"ostmaster mode!
        </blockquote><blockquote>
          <em>Warning:</em>
          SMTP<xref target="RFC5321"/>
          address "local-part"s permit "quoted-string"s!
        </blockquote><t>
          In case the recipient domain for a particular message forge
          has not announced support for DKIM/ACDC,
          and to strengthen SMTP envelope anonymity in permanent
          IMF<xref target="RFC5322"/>
          message data,
          the tag "f=", as well as any "t=" tag <bcp14>MUST</bcp14> be
          omitted, and instead a "privately encrypted" "ec=" tag be placed:
          the content of this tag is
          BASE64<xref target="RFC4648"/>
          encoded,
          and <bcp14>MUST</bcp14> correlate to the hidden "f=" and "t=" tags.
        </t><blockquote>
          <em>Informative remark:</em>
          The SMTP envelope domains are cryptographically fixated
          even in the minimal non-DKIM/ACDC variant of DKIX-AC:,
          protecting users of DKIM/ACDC aware hops against replay.
          The security enhancement was considered worth the resulting
          unfortunate leakage of this minimal DKIX-AC: header field to
          permanent storage.
        </blockquote><t>
          Mirroring DKIM-Signature: the tag list is concluded with the
          "b=" tag that is the cryptographic signature data of the
          DKIX-AC: header field.
          To ensure proper linkage and uniqueness of the "b=" signature
          the reassembled (see
          DKIM<xref target="RFC6376"/>
          section 3.5) value of the linked DKIX-Sig: signature is "temporarily
          assigned" to "b=" before creating it;
          Thereafter the "b=" tag is assigned its own value.
        </t><t>
          All instances of DKIX-AC: header fields <bcp14>MUST</bcp14>
          be removed by DKIM/ACDC aware software as soon as possible:
          they <bcp14>MUST NOT</bcp14> be delivered by local delivery
          agents as part of the message.
          They <bcp14>MUST</bcp14>, however, exist in rejected messages.
        </t><t>
          However, if a domain is only an intermediate, which was
          neither directly addressed nor which originated the mail,
          and which does not modify the SMTP envelope either, then it
          <bcp14>MUST NOT</bcp14> remove the "current" DKIX-AC: header
          field(s), and it <bcp14>MUST NOT</bcp14> generate (a) new one(s).
        </t>
      </section>

      <section>
        <name>The _dkimacdc.DOMAIN DNS TXT RR</name>
        <t>
          The syntax of this DNS resource record is the usual semicolon
          separated list of DKIM-style tags of unspecified order;
          unknown tags <bcp14>MUST</bcp14> be ignored.
        </t><t>
          DNS CNAME chains <bcp14>MUST</bcp14> be followed when looking
          up this DNS RR.
        </t><t>
          The optional tag "c=" (<tt>%x64 "="</tt>)
          <bcp14>MUST</bcp14> have the value "n" (<tt>%x6E</tt>).
          It announces that the DKIM-Signature: legacy header field need not
          be generated for messages sent to this host.
          Senders <bcp14>MAY</bcp14> follow this advise if they can ensure
          that the message will not pass intermediate hops.
        </t><t>
          The optional tag "a=" (<tt>%x61 "="</tt>)
          represents a colon-separated list of supported algorithm names,
          interpreted case-insensitively.
          Unknown list entries <bcp14>MUST</bcp14> be ignored.
          The entries "ed25519-sha256" and "eda-sha256" are implied.
        </t>
      </section>
    </section>

    <section>
      <name>Differential Changes</name>
      <t>
        Whenever a DKIM/ACDC enabled domain detects during signature
        creation that the canonicalized representation of a message,
        whether header fields and/or body data, was modified,
        a new DKIX-DC: header field has to be created.
      </t>

      <section>
        <name>The DKIX-DC header field</name>
        <t>
          The syntax of this header field is the usual semicolon
          separated list of DKIM-style tags of unspecified order;
          unknown tags <bcp14>MUST</bcp14> be ignored.
        </t><t>
          The "w=" tag is the linked DKIX-Sig: ACDC "sequence",
          best placed early.
        </t><t>
          The "h=" tag is used to store differential data for header
          fields, "b=" that for body content.
          Both tags are optional,
          but at least one <bcp14>MUST</bcp14> exist in a valid DKIX-DC:
          header field, and a given one <bcp14>MUST NOT</bcp14> have an
          empty value.
        </t><t>
          The differential data is stored in the patch format as below,
          which is first compressed with
          ZLIB<xref target="RFC1950"/>,
          and then
          BASE64<xref target="RFC4648"/>
          encoded.
        </t>
      </section>

      <section>
        <name>Preparing patch creation</name>
        <t>
          The differential changes are created with canonicalized
          header fields and body data, respectively, as seen
          on egress, alongside the equally canonicalized data present
          before modifications took place, that is, on ingress.
        </t><t>
          All header fields covered by the
          header field database <xref target="HFDB"/>
          <bcp14>MUST</bcp14> be included.
          All header fields covered by former signatures of the DKIM/ACDC
          chain <bcp14>MUST</bcp14> be included.
          DKIM/ACDC enabled signatures, and any other "DKIX-" header field
          <bcp14>MUST NOT</bcp14> be included.
        </t><t>
          The header fields <bcp14>MUST</bcp14> be sorted byte-wise
          (by numeric ASCII byte value) by-name,
          the formed subgroups <bcp14>MUST</bcp14> remain in the (reverse)
          header stack order defined by
          DKIM<xref target="RFC6376"/>
          section 5.4.2,
          "Signatures Involving Multiple Instances of a Field".
        </t><t>
          Differential changes are then expressed with the patch content
          as below.
        </t>

        <section>
          <name>Patch content</name>
          <t>
            The patch format is an adopted variant of the
            BSDiff algorithm patch format, as below.
            Overall it consists of a header, followed by control data.
            Thereafter the two byte (8-bit octet) streams of
            differential data (in reverse order)
            and extra data conclude the patch.
            Erroneous patch data <bcp14>MUST</bcp14> cause rejection.
          </t><t>
            The header and the control data consist of 32-bit signed
            integers, stored in network byte order
            (MSF; most significant byte first).
          </t><t>
            The header consists of four values denoting
            the length of the control data tuple block in bytes,
            the length of the differential data block in bytes,
            the length of the extra data block in bytes,
            concluded by the length of the original "data target" in bytes;
            The sum of the first three values must be one less than the
            maximum positive 32-bit signed integer.
            The number of control data tuples
            <bcp14>MUST NOT</bcp14> excess the length of the original "data
            source" (in bytes) plus one.
          </t><t>
            The control data is a stream of tuples of three values each.
            The first denotes the length of differential data to join in
            in bytes, or 0.
            Differential data is joined in by adding "the current" differential
            byte to "the current" byte of the "data source",
            then storing the addition result byte in the "data target".
            The read positions within the differential data and the
            "data source" move forward accordingly.
            The write position in the "data target" moves forward accordingly.
          </t><t>
            The second value denotes the length of extra data to copy in bytes,
            or 0.
            The read position within extra data move forward accordingly.
            The write position in the "data target" moves forward accordingly.
          </t><t>
            All tuples are worked in order, and within each tuple first the
            differential data, if any, then the extra data, if any, is worked.
          </t><t>
            The last value of control data tuples denotes the number of bytes
            to seek relatively in the "data source" before the next tuple is
            worked.
            Of all the values, only this one may be negative.
            The overall offset within the "data source" <bcp14>MUST NOT</bcp14>
            become negative after the seek.
          </t><blockquote>
            <em>Informative remark:</em>
            Of all control data tuples only the first may only perform seek
            adjustments without also storing data in "data target".
            Even if it is otherwise ignored the seek value of the last
            control data tuple must result in a valid offset.
            (0 is always valid.)
            Other conditions <bcp14>MUST</bcp14> be treated as errors.
          </blockquote>
        </section>

        <section>
          <name>BSDiff patch content adaption</name>
          <ul>
            <li>
              32-bit integers are used for length and offset values.
              This almost halves memory usage,
              and produces smaller patch control data.
              It is deemed sufficient for email purposes.
            </li><li>
              Data is stored in big endian
              (network; MSF; most significant byte first)
              instead of little endian
              (LSF; least significant byte first)
              byte order.
            </li><li>
              In order to allow for memory usage reduction during patch
              generation the adaption uses a shared memory region for
              differential and extra data:
              the former is therefore stored in reversed order, top down.
              (Reduces memory usage by the size of the target data set.)
            </li><li>
              The entire, readily prepared patch is passed through a
              compressor.
              (The original uses three separate bzip2 streams to
              sequentially serialize control, differential and extra data
              separately.)
            </li><li>
              The original header did not contain the size of the extra
              data, which was stored last, with its size implicitly
              extending to the end of the patch.
              The adaption includes the extra data size in the header,
              allowing more verification tests to be applied with only the
              header being readily parsed.
              This also enables the I/O layer to allocate perfectly sized
              memory with only the header data being available.
            </li>
          </ul>
        </section>

        <section>
          <name>An example algorithm</name>
          <t>
            A very fast and simple algorithm that processes data linewise
            is presented here.
          </t><blockquote>
            <em>Informative remark:</em>
            Like SMTP DKIM does not know about MIME,
            it treats the body (and the header fields, in that respect) as
            <tt>CRLF</tt> terminated lines of bytes,
            with certain byte-based ("relaxed") normalizations applied on top.

            MIME reencoding (may) happen along the message path:
            the MIME content-transfer-encoding type, its line length(s),
            as well as character sets, and more, can theoretically be in flux.

            With the advent of tracking of differential changes it is expected
            that software becomes smarter, by adapting more to what exists in
            messages, instead of performing "brute force modifications".

            For example, a service provider that rewrites URIs within messages
            can ensure that the line lengths of a base64 formatted input are
            preserved after the rewrite, as base64, and with the underlaying
            character set being unchanged, and that, where modifications took
            place, the lengths of only the modified lines are adjusted so to
            keep the differential changes as minimal as possible.

            In such a world a very fast linewise algorithm is sufficient.
          </blockquote><t>
            Initialize a "list of lines" that can be iterated over
            uni-directionally to 0.
            While there is still input data from the target (egress) data set:
          </t><ul><li>
            Search for <tt>LF</tt> line feed.
            If found, advance over it,
            otherwise use the entire remaining input.
          </li><li>
            Verify the resulting data length fits into 31-bit, minus 1.
          </li><li>
            Create a hash of the data that is proof against complexity attacks.
          </li><li>
            Put the data at the end of the "list of lines".
          </li></ul><t>
            Initialize a "hashmap" to 0.
            If any, store all members of the "list of lines" therein,
            indexed by their hashes.
          </t><t>
            Initialize an "absolute position",
            a "current length of differences",
            and a "current length of extra data" to 0.
            Initialize a "former line" to 0.
            Also initialize an "overall length of differences",
            and an "overall length of extra data" to 0.
            While there is still input data from the source (ingress) data set:
          </t><ul><li>
            Search for <tt>LF</tt> line feed.
            If found, advance over it,
            otherwise use the entire remaining input.
          </li><li>
            Verify the resulting data length fits into 31-bit, minus 1.
          </li><li><t>
            If the "hashmap" is not 0:
            </t><ul><li>
              Create a hash of the data (with the same algorithm as above).
            </li><li>
              If the "former line" is not 0,
              check whether its next line (in the "list of lines"), if any,
              matches the current data.

              If so,
              make the next line the "former line",
              verify the resulting "overall length of differences"
              will fit in 31-bit, minus 1;

              Add that many bytes to the "absolute position",
              add that many bytes to the "current length of differences",
              add that many zero bytes to "differences".
            </li><li>
              Otherwise search "hashmap" for the hash
              (ensure an exact data match, as necessary).

              If a match is found,
              then if either the "current length of differences" is not 0,
              or the "current length of extra data" is not 0,
              or if no control tuple has yet been dumped,
              then dump a control tuple first,
              and set the "current length of extra data" to 0;

              Make it the "former line",
              verify the resulting "overall length of differences"
              will fit in 31-bit, minus 1;

              If the offset of the start of the "former line"
              (within the target (egress) data set)
              does not equal the "absolute position",
              ensure the relative seek of the formerly dumped control tuple
              is set to the subtraction of the start of the "former line"
              and the "absolute position";

              Set the "current length of differences" to that many bytes,
              set the "absolute position" to the start of the "former line"
              plus that many bytes,
              add that many zero bytes to "differences".

              (Optimization: dumping an otherwise "empty" initial control
              tuple is not necessary if no relative seek is to be applied.)
            </li></ul>
          </li><li>
            Otherwise the line is extra data.

            Verify the resulting "overall length of extra data"
            will fit in 31-bit, minus 1;

            Add that many bytes to the "current length of extra data",
            copy that many bytes to "extra data".
          </li></ul><t>
            After all the data has been worked,
            then if either the "current length of differences" is not 0,
            or the "current length of extra data" is not 0,
            then dump a control tuple.
          </t><t>
            Ensure the relative seek of the last control tuple, if any, is 0.
          </t><t>
            Here exemplary results of the FOSS
            <xref target="BSDIPA"/>
            plug-and-play ISO C99 and perl reference implementation that
            generates the above patch format
            with either (the string suffix sort based) BSDiff algorithm of
            Colin Percival, or the above textual variant:
          </t><sourcecode><![CDATA[
# Email, sent to/received reencoded from ML (4621 vs 5309 bytes):
$ diff -e .S1 .S2 | wc -c
2326
#  BSDiff: data: ctrl=216 (18 entries) diff=3554 extra=1067
#          857 result bytes; Code 0:001 secs, ZLIB I/O 0:000 secs
#          (BZ2 950 / 0:001, XZ 884 / 0:126, ZSTD 875 / 0:107)
# Textual: data: ctrl=108 (9 entries) diff=3043 extra=1578
#          1089 result bytes; Code 0:000 secs, ZLIB I/O 0:000 secs
#          (BZ2 1260 / 0:001, XZ 1144 / 0:127, ZSTD 1116 / 0:126)

# Large roff manual (428420 vs rewritten 390770 bytes)
$ diff -e .B1 .B2 | wc -c
241233
#  BSDiff: data: ctrl=54816 (4568 entries) diff=304307 extra=124113
#          74830 result bytes; Code 0:198 secs, ZLIB I/O 0:122 secs
#          (BZ2 67368 / 0:022, XZ 65216 / 0:137, ZSTD 69444 / 0:144)
# Textual: data: ctrl=54456 (4538 entries) diff=202309 extra=226111
#          97355 result bytes; Code 0:004 secs, ZLIB I/O 0:098 secs
#          (BZ2 81943 / 0:053, XZ 82364 / 0:253, ZSTD 86767 / 0:213)
          ]]></sourcecode>
        </section>
      </section>

      <section>
        <name>Rationale</name>
        <t>
          Differences are included to allow DKIM verifiers to restore
          previous message content for the purpose of cryptographically
          verifying elder signatures.

          This for example allows for collecting trustworthy statistics of
          organizational trust (<xref target="RFC5863"/>, section 2.5)
          in an automated fashion.

          Alternatively or in addition per-user decisions for certain
          message paths, involving certain modification per path hop,
          are made possible, and can be taken into account.
        </t><blockquote>
          For example, user interfaces could use traffic light semantics
          that unfold on click to traffic light semantics of all message
          versions, which would (with precautions) visualize differences.

          This can empower users to make decisions on the
          trustworthiness of intermediates, and, for example,
          request display of the From: header field as created by the
          original message sender for a message path that crosses a
          mailing-list.
          (As in, "<em>yes, i accept this hop changes From:, it is a mailing
          list</em>".)
        </blockquote><blockquote>
          <em>Informative remark:</em>
          The data exists in the DKIM "relaxed" normalized variant:
          former states are not meant to be usable messages.

          This is deemed acceptable because of the purpose of including
          differential changes,
          and because their visualization of a successfully verified
          DKIM/ACDC chain should still be sufficient to allow users,
          and automated systems, making responsible decisions.
        </blockquote>
      </section>
    </section>

    <section anchor="MITIGATIONS">
      <name>Mitigations for Future</name>
      <t>
        At the time of this writing the email infrastructure is
        deeply penetrated by mitigation code that circumvents problems
        incurred by standards like DMARC and SPF,
        driven by the desire to keep existing infrastructures
        (configurations) in an usable state.
      </t><t>
        For example, SPF will not survive a single hop, which means
        that alias expansion, a widely used core feature of the email
        infrastructure, does no longer easily work.
        The IETF has no solution for this problem,
        but the software world has created a "Sender Rewriting Scheme",
        involving dedicated software to implement mitigations,
        so that aliases can be used regardless.
      </t><t>
        As another example, DMARC causes a lot of mailing-lists to
        apply mitigations of various form and style: old signatures
        are removed, or renamed, often the From: header field is
        rewritten in a "User A via List B" style,
        and the Reply-To: header field will announce the real sender,
        unless that was already set.
        The introduction of this <em>requirement of blind trust</em> into
        "A via B" displays seems like a devastating psychological failure.
      </t>

      <section anchor="MITIGATE">
        <name>Mitigations</name>
        <t>
          This memo suggests to apply mitigations actively as part of
          DKIM processing, at minimum temporarily, until, at some future
          time, the email infrastructure has adapted to a new reality.
          Future engineers can then decide how to proceed further.
        </t><t>
          In any case it seems wise to move decisions on actual content
          changes away from the SMTP layer,
          to reduce failures to cryptographical signature failures,
          and let users and/or algorithms on a higher layer decide
          whether a certain content change or applied mitigation is
          "acceptable", or not.
        </t><ul><li><t>
          Remove existing DKIM/ACDC announcing DKIM-Signature: header fields.
          In case no mitigations have yet been applied to "RFC5322.From",
          and no such mitigation will be applied, as below,
          the signature linked to "sequence" 1 is an exception.
          This mitigation <bcp14>MUST</bcp14> be applied.
          The mitigation <bcp14>MAY</bcp14> be applied to non DKIM/ACDC linked
          DKIM-Signatures: as well in as far as local policy allows.
          Before the flag day DKIM/ACDC will create a single DKIM-Signature:
          that will verify correctly.
        </t></li><li><t>
          Mitigate non-local <tt>MAIL FROM</tt> envelopes.
        </t><t>
          Because a possible SPF check will fail on the next hop
          (in situations with a strict SPF policy that applies a policy),
          if a message that does not originate locally leaves the email
          system on egress,
          with a SMTP envelope <tt>MAIL FROM</tt> of a foreign domain,
          mitigate such addresses,
          so that the current hop becomes the, quoting
          <xref target="RFC3461"/>,
          <em>"final delivery for the [original] message"</em>.
          DKIM/ACDC software <bcp14>SHOULD</bcp14> offer options to
          exclude certain domains from these mitigations.
        </t><t>
          To mitigate, synthesize for example an address of the local
          domain with a "local-part" starting with
          <tt>DKIX=</tt>,
          followed by at least 16 bytes of the
          BASE64<xref target="RFC4648"/>
          encoded
          HMAC<xref target="RFC2104"/>
          of a dedicated cryptographic private key
          and the original <tt>MAIL FROM</tt>.
        </t><t>
          Alternatively, using a dedicated subdomain is an approach
          that avoids any possible "local-part" ambiguities.
          Then for example the IETF mailing-list From: header field
          DMARC mitigation approach could be used, which decomposes the
          original <tt>MAIL FROM</tt> by replacing the commercial at
          (U+0040, @) with its "hexadecimal value in quoted-printable
          notation" to end with "local-part=40domain",
          followed by the domains of the mitigating host:
          <tt>local-part=40domain@subdomain.domain</tt>.
        </t><blockquote>
          <em>Informative remark:</em>
          the SMTP size limit of "local-part" is 64 octets,
          however the overall "reverse-path" limit of RFC 821 and
          RFC 2821 was 256 octets.
        </blockquote><t>
          The synthesized address <bcp14>MUST</bcp14> be linkable to the
          original <tt>MAIL FROM</tt> for at least 864000 seconds
          (ten days: to reach into the next working week).
          It <bcp14>SHOULD</bcp14> be linkable only by
          Delivery Status Notifications<xref target="RFC3461"/>
          or (other) message bounces.
          If the bounce transports enough message data content this
          <bcp14>MAY</bcp14> be furtherly constrained to verifiable
          DKIM signatures of the local domain,
          even the exact message for which the address was synthesized.
          The optional bounce identifier "id" may be usable for this
          purpose.
        </t><blockquote>
          <em>Informative remark:</em>
          Except for linking purposes to the original envelope the
          synthesized address is otherwise "transparent",
          and should appear as if it does not exist:
          DKIM/ACDC software is expected to cause appropriate rejection
          on SMTP level at the earliest possible time.
        </blockquote></li><li><t>
          Mitigate From: header fields, if necessary.
        </t><t>
          When a message was changed in between ingress and egress,
          so that the DKIM signature (not only: related to the From:
          header field) will no longer verify.
          Then, if the From: header field was not already locally
          mitigated (by for example mailing-list software),
          actively mitigate the From: header field,
          so that the current hop becomes the, quoting
          <xref target="RFC3461"/>,
          <em>"final delivery for the [original] message"</em>
          in respect to the
          IMF<xref target="RFC5322"/>
          message that is visible to recipients.
          DKIM/ACDC software <bcp14>SHOULD</bcp14> offer options
          to exclude certain domains from these mitigations.
        </t><t>
          To mitigate, place the original "name-addr" in the
          Reply-To: header field, unless that already exists,
          set the Author: header field if it can be ensured that
          From: was, actually, the author,
          and replace From: with synthesized content.
          The examples of non-local <tt>MAIL FROM</tt> envelope
          mitigation apply also here in respect to "addr-spec";
          yet, the dedicated subdomain approach results in visually
          more appealing header field content.
          For the "display-name" a
          "From: X via &lt;Y&gt;" notation <bcp14>MAY</bcp14> be used,
          where "X" denotes the original "display-name".
        </t><t>
          For example, if the original content was
          "Forename Surname &lt;for.sur@example1.net&gt;"
          then the mitigation could be
          <tt>"Forename Surname via"
          &lt;for.sur=40example1.net@dkim.example2.net&gt;</tt>.
          Without dedicated subdomains a variant of the widely
          known construct
          <tt>"Forename Surname &lt;for(DOT)sur(AT)example1(DOT)net&gt;" via
          &lt;dkix-dedicated@example2.net&gt;</tt>
          may be used.
          Whether DKIM/ACDC dedicated subdomain or DKIM/ACDC dedicated
          address, the backing software implementation is expected to
          rewrite the address 
        </t></li></ul>
      </section>
    </section>

    <section>
      <name>Example</name>
      <t>
        An example that shows the flow of a single message with multiple
        different recipients, including mailing-lists and aliases.
        It assumes all recipients announced DKIM/ACDC support.
        It provides full mitigations and support for SPF and DMARC.
      </t><sourcecode><![CDATA[
Originator (yet forged for recipient domain f.g):

  MAIL FROM: <a@b.c>
  RCPT TO: <d@f.g>
  RCPT TO: <e@f.g>
  ...
  DKIX-AC: w=1; s=K1ed; o=b.c; f=a; d=f.g; t=d; t=e; b=..
    DKIM-Signature: w=1; s=K1; ..
  DKIX-Sig: acdc=1:N0C:O; s=K1ed; ..
  From: a@b.c
  To: d@f.g, e@f.g, x@y.z, u@v.w, r@s.t, o@p.q
  ...

f.g, local delivery (to d@ and e@):

  ...
  DKIX-Sig: acdc=2:N0C:AIV; s=K2ed; ..
  DKIX-Sig: acdc=1:N0C:O; s=K1ed; ..
  From: a@b.c
  ...

x@y.z -- a mailing-list!
It redistributes after RFC 2369 and RFC 2919 additions,
in-message unsubscribe footer, and From: mitigated
(in best RFC 3461 manner):

  MAIL FROM: <x@y.z>
  RCPT TO: <l@m.n>
  ...
  DKIX-AC: w=2; s=K2ed; o=y.z; f=x; d=m.n; t=l; b=..
  DKIX-DC: w=2; h=BASE64; b=BASE64
    DKIM-Signature: w=2; s=K2; ..
  DKIX-Sig: acdc=2:V0C0U3:ADEOVYy; s=K2ed; dch=..
  DKIX-Sig: acdc=1:N0C:O; s=K1ed; ..
  From: a(AT)b(DOT)c via <x@y.z>
  Reply-To: a@b.c
  ...
  List-Unsubscribe: bla

u@v.w -- an expanded alias!
The hop honours RFC 3461, and changes MAIL FROM;
it keeps DKIM-Signature: w=1 for DMARC compatibility:

  MAIL FROM: <u@v.w>
  RCPT TO: <realu@realv.realw>
  ...
  DKIX-AC: w=2; s=K2ed; o=v.w; f=u; d=realv.realw; t=realu; b=..
    DKIM-Signature: w=2; s=K2; ..
  DKIX-Sig: acdc=2:N0C:EOVy; s=K2ed; ..
    DKIM-Signature: w=1; s=K1; ..
  DKIX-Sig: acdc=1:N0C:O; s=K1ed; ..
  From: a@b.c
  ...

r@s.t -- an expanded alias!
Note: invalid DKIM/ACDC, because no MAIL FROM update,
will later fail SPF;
it keeps DKIM-Signature: w=1 for DMARC compatibility:

  MAIL FROM: <a@b.c>
  RCPT TO: <realr@reals.realt>
  ...
  DKIX-AC: w=2; s=K2ed; o=b.c; f=a; d=reals.realt; t=realr; b=..
    DKIM-Signature: w=2; s=K2; ..
  DKIX-Sig: acdc=2:N0C:EVy; s=K2ed; ..
    DKIM-Signature: w=1; s=K1; ..
  DKIX-Sig: acdc=1:N0C:O; s=K1ed; ..
  From: a@b.c
  ...

... the same, but DKIM/ACDC compliant:

  MAIL FROM: <DKIX=a=40b.c@s.t>
  RCPT TO: <realr@reals.realt>
  ...
  DKIX-AC: w=2; s=K2ed; o=s.t; f=DKIX=a=40b.c; ..
    DKIM-Signature: w=2; s=K2; ..
  DKIX-Sig: acdc=2:N0C:EOVy; s=K2ed; ..
    DKIM-Signature: w=1; s=K1; ..
  DKIX-Sig: acdc=1:N0C:O; s=K1ed; ..
  From: a@b.c
  ...

o@p.q -- a mailing-list!
Note: invalid DKIM/ACDC, because no From: mitigation,
c/would later fail DMARC;
it redistributes after RFC 2369 and RFC 2919 additions,
and in-message unsubscribe footer.

  MAIL FROM: <o@p.q>
  RCPT TO: <X@X.X>
  ...
  DKIX-AC: w=2; s=K2ed; o=p.q; f=o; d=X.X; t=X; b=..
  DKIX-DC: w=2; h=BASE64; b=BASE64
    DKIM-Signature: w=2; s=K2; ..
  DKIX-Sig: acdc=2:V0C0U3:DEOVYy; s=K2ed; dch=..
  DKIX-Sig: acdc=1:V0C0U3:O; s=K1ed; ..
  From: a@b.c
  ...
  List-Unsubscribe: bla

... the same, but DKIM/ACDC compliant
(using dedicated mitigation subdomain):

  MAIL FROM: <o@p.q>
  RCPT TO: <X@X.X>
  ...
  DKIX-AC: w=2; s=K2ed; o=p.q; f=o; d=X.X; t=X; b=..
  DKIX-DC: w=2; h=BASE64; b=BASE64
    DKIM-Signature: w=2; s=K2; d=dkim.p.q; ..
  DKIX-Sig: acdc=2:V0C0U3:DEOVYy; s=K2ed; d=dkim.p.q; dch=..
  DKIX-Sig: acdc=1:N0C:O; s=K1ed; ..
  From: "a@b.c" via <a=40b.c@dkim.p.q>
  Reply-To: a@b.c
  ...
  List-Unsubscribe: bla

l@m.n (recipient of x.y.z mailing-list), local delivery:

  ...
  DKIX-Sig: acdc=3:V0C0U3:IVYy; s=K3ed; ..
  DKIX-DC: w=2; h=BASE64; b=BASE64
  DKIX-Sig: acdc=2:V0C0U3:ADEOVYy; s=K2ed; dch=..
  DKIX-Sig: acdc=1:N0C:O; s=K1ed; ..
  From: a(AT)b(DOT)c via <x@y.z>
  ...

realr@reals.realt -- expanded alias target, local delivery:

  ...
  DKIX-Sig: acdc=3:N0C:IVy; s=K3ed; ..
  DKIX-Sig: acdc=2:N0C:EOVy; s=K2ed; ..
  DKIX-Sig: acdc=1:N0C:O; s=K1ed; ..
  From: a@b.c
  ...
      ]]></sourcecode>
    </section>

    <section anchor="IANA">
      <name>IANA Considerations</name>
      <t>
        IANA is asked to add the header fields
        DKIX-Sig:, DKIX-AC:, DKIX-DC:, and  DKIX-Store:
        to the "Permanent Message Header Field Names" registry.
        IANA is asked to add
        "eda"
        to the "DKIM Key Type" registry.
        IANA is asked to add the tag
        "w="
        to the "DKIM-Signature Tag Specifications" registry.
      </t>
    </section>

    <section anchor="Security">
      <name>Security Considerations</name>
      <t>
        Public key cryptography is the safest approach to identification
        of counterparts and verification of data.
        This specification enables DKIM to cryptographically verify
        SMTP envelopes, and to cryptographically verify all message
        transitions back to the original message sender.
      </t>
    </section>

  </middle>
  <back>

    <references>
      <name>Normative References</name>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.4648.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6376.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8463.xml"/>
    </references>

    <references>
      <name>Informative References</name>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.1123.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.1950.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2045.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2104.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2119.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2920.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3207.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3461.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.3463.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5234.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5321.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5322.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.5863.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.6377.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.7208.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.8174.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9057.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9562.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9787.xml"/>
      <xi:include href="https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9788.xml"/>
      <reference anchor="BSDIPA" target="https://github.com/sdaoden/s-bsdipa">
        <front><title>BSDIPA, a mutation of BSDiff</title><author/></front>
      </reference>
    </references>

    <section anchor="HFDB">
      <name>Header field database</name>
      <t>
        The database of header fields, in an automatically extractable form.
        Lines starting with EQUALS SIGN U+003D form start and, with a following
        SOLIDUS U+002F, end tags.
        The tag "HFDB" encloses the entire database.
        The header fields are case-insensitive, followed by whitespace,
        followed by its assigned bit number.
        Lines starting with NUMBER SIGN U+0023 are comments.
      </t><sourcecode><![CDATA[
=HFDB
# sorted for normal 4, list 6
# RFC 5322, 3.6 / 5322-bis, I.
from 0
sender 1
reply-to 2
date 3
to 4
cc 5
bcc 6
message-id 7
in-reply-to 8
references 9
subject 10
# RFC 9057
author 11
# RFC 2045
mime-version 12
content-type 13
content-transfer-encoding 14
# (rest usually not in main header)
content-id 15
content-description 16
# RFC 1806
content-disposition 17
# RFC 9788
hp-outer 18
# draft-ietf-drums-mail-followup-to
mail-followup-to 19
# draft-josefsson-openpgp-mailnews-header
openpgp 20
# RFC 2369
list-id 21
list-help 22
list-subscribe 23
list-unsubscribe 24
list-post 25
list-owner 26
list-archive 27
# RFC 5064
archived-at 28
# draft-ietf-sml-structured-email
content-purpose 29
# RFC 5322, 3.6 / 5322-bis, II.
resent-from 30
resent-sender 31
resent-to 32
resent-cc 33
resent-date 34
resent-message-id 35
resent-bcc 36
#comments
keywords 37
# RFCs 3282 / 4021
content-language 38

# RFC 5703
original-from 39
original-subject 40
# RFC 4021 / draft-ietf-mailmaint-expires
expires 41

# RFC 8058 (last)
list-unsubscribe-post 42
=/HFDB
      ]]></sourcecode>

      <section anchor="HFDB_CODE">
        <name>Example code for managing "hfdb-bits"</name>
        <t>
          Example C code to interpret and create the DKIM/ACDC "hfdb-bits" tag.
        </t><sourcecode><![CDATA[
#include <string.h>
#include <strings.h>

/* 0-based */
#define HFDB_ENTRIES (42 +1)

#define HFDB_STORE_BITS ((HFDB_ENTRIES + (8 - 1)) & ~(8 - 1))
#define HFDB_STORE_SIZE (HFDB_STORE_BITS / 8)
#define HFDB_STORE_C2OFF(C) ((hfdb_u8)(C) / 8)
#define HFDB_STORE_C2BIT(C) ((hfdb_u8)(C) & (8 - 1))
#define HFDB_STORE_SET(SP,BIT) \
   ((SP)->s_dat[HFDB_STORE_C2OFF(BIT)] |= (1u << HFDB_STORE_C2BIT(BIT)))
#define HFDB_STORE_CLEAR(SP,BIT) \
   ((SP)->s_dat[HFDB_STORE_C2OFF(BIT)] &= ~(1u << HFDB_STORE_C2BIT(BIT)))
#define HFDB_STORE_TEST(SP,BIT) \
   ((SP)->s_dat[HFDB_STORE_C2OFF(BIT)] & (1u << HFDB_STORE_C2BIT(BIT)))

#define HFDB_STRING_SIZE (HFDB_STORE_BITS / 5)

typedef unsigned char hfdb_u8;
struct hfdb_store{
   hfdb_u8 s_max; /* Max bit set in .s_dat, +1 */
   hfdb_u8 s_dat[HFDB_STORE_SIZE];
};

/* Number of bits set/characters stored, -1 on error */
static int hfdb_from_cp(struct hfdb_store *sp, char const *cp);
static int hfdb_to_cp(struct hfdb_store *sp, char cp[HFDB_STRING_SIZE +1]);

static int
hfdb_from_cp(struct hfdb_store *sp, char const *cp){
   int rv, addbits;

   memset(sp, 0, sizeof(*sp));

   rv = 0;
   for(addbits = 0; *cp != '\0'; addbits += 5, ++cp){
      int bs;

      bs = (int)(unsigned)*cp;
      /* Support case-insensitivity */
      if(bs >= 'a')
         bs -= 'a' - 'A';
    /* 5 bits/char: 0b11111: 36#V: 0-9A-V */
      if(bs > 'V' || bs < '0')
         break;
      bs -= '0'; /* "atoi" */
      if(bs > 9){
         bs -= 7;
         /* ..but ASCII U+003A..U+0040 not allowed */
         if(bs <= 9)
            break;
      }

      for(; bs != 0; ++rv){
         int b;

         b = ffs(bs);
         --b;
         bs ^= 1 << b;
         b += addbits;
         if(b >= HFDB_ENTRIES)
            goto jleave;
         HFDB_STORE_SET(sp, b);
         sp->s_max = ++b;
      }
   }

jleave:
   return (*cp == '\0' ? rv : -1);
}

static int
hfdb_to_cp(struct hfdb_store *sp, char cp[HFDB_STRING_SIZE +1]){
   int xmax, addbits;
   char *cursor, *lx;

   lx = cursor = cp;
   xmax = (sp->s_max <= HFDB_ENTRIES) ? sp->s_max : HFDB_ENTRIES;

   for(addbits = 0; addbits < xmax; addbits += 5){
      int c, b;

      b = 5;
      c = xmax - addbits;
      if(b > c)
         b = c;
      for(c = 0; b > 0;){
         int bx;

         bx = addbits + --b;
         if(HFDB_STORE_TEST(sp, bx))
            c |= 1u << b;
      }
      *cursor++ = "0123456789ABCDEFGHIJKLMNOPQRSTUV"[c];
      if(c != 0)
         lx = cursor;
   }
   *lx = '\0';

   return (int)(lx - cp);
}
        ]]></sourcecode>
      </section>
    </section>

    <section anchor="FurtherDKIMUpdates">
      <name>Further DKIM Updates</name>
      <ul><li><t>
        This specification obsoletes the simple canonicalization type;
        It <bcp14>MUST NOT</bcp14> be used by DKIM/ACDC compatible software.
      </t><t>
        <em>Rationale:</em> in order to minimize processing cost in time and
        space for and of differential processing,
        being able to work on and with only one data representation is
        beneficial.
      </t><t>
        The "extremely crude ASCII Art attacks" mentioned in
        DKIM<xref target="RFC6376"/>
        section 8.1 are considered to be a rather artificial attack vector.

        Furthermore the statement of DKIM section
        5.4.1. "Recommended Signature Content"
        that e-commerce sites (etc) <em>will generally prefer "simple"
        canonicalization</em>
        does not match reality in the author's experience.

        Almost exclusively it is relied on enriched format messages
        with dedicated whitespace rules, like HTML,
        or even more refined (compressable, encryptable, optionally
        interactive, scripted) formats, like PDF.

        In addition, and foremost, choosing space-preserving MIME content
        transfer encodings is the, used, natural choice, as appropriate.

        As a personal comment, because rarely used in practice, there exist
        possibilities to sign and/or encrypt actual message content to
        ensure its privacy on a per recipient base, like S/MIME and PGP,
        which use dedicated, replicable normalization algorithms to protect
        their content.
      </t><t>
        In operational reality the "relaxed" normalization is by far the
        most commonly used form, percent-wise it possibly can be estimated
        in the high nineties.
        It follows that whitespace granularity that exact does not matter
        for domain signatures,
        and if reduction to a single algorithm is desired,
        "relaxed" is the only viable form for header fields (anyway),
        and using it for message bodies is a most widely accepted variant.
      </t></li><li><t>
        This specification obsoletes the DKIM "l=" tag that restricts the
        number of DKIM covered bytes of the normalized message body.
        It <bcp14>MUST NOT</bcp14> be used by DKIM/ACDC compatible software,
        and all the message body <bcp14>MUST</bcp14> always be used to
        create the body hash.
      </t><t>
        <em>Rationale:</em> "l=" has always been insufficient to deal with
        message changes caused by mailing-lists etc,
        but effectively includes the security risk that message parts which
        are not covered by the signature appear as "valid content" to users
        looking at a DKIM verified message.
        The DKIM/ACDC differential changes offer a better approach to deal
        with message changes, while completely covered message bodies
        ensure content validity.
      </t></li><li><t>
        For the "i=" tag this specification obsoletes the possible use of
        DKIM-Quoted-Printable for the optional "Local-part".
      </t><t>
        <em>Rationale:</em> because the syntax is "a standard email
        address where the local-part MAY be omitted", quoted-printable
        encoding is not necessary for representation.
      </t></li><li><t>
        This specification obsoletes the DKIM "z=" tag that was defined
        "for diagnostic use" to copy a freely defined set of header fields
        and their values present during signature creation.
        It <bcp14>MUST NOT</bcp14> be used by DKIM/ACDC compatible software.
      </t><t>
        <em>Rationale:</em> the DKIM/ACDC differential changes provide access
        to the same information.
      </t></li><li><t>
        For the "q=" tag this specification obsoletes the possible use of
        DKIM-Quoted-Printable for the optional "x-sig-q-tag-args"
        of possibly introduced future query types.
      </t><t>
        <em>Rationale:</em> shall ever a new type become standardized
        beside the dns/txt that is with DKIM from the very start,
        that standard can very well give meaning to a
        "hyphenated-word" proxy identifier without making use of
        byte values which would require encoding.
      </t></li><li><t>
        This specification obsoletes the DKIM key representation tag "n="
        that was meant to include "notes that might be of interest to
        a human", "intended for use by administrators, not end users",
        and which "should be used sparingly".
      </t><t>
        <em>Rationale:</em> no use case has been encountered in the DNS,
        let alone serious such; if future space unconstrained key
        providers other than DNS should ever exist and be used to
        distribute DKIM keys, it is likely that they support inclusion
        of strings via some method that need not be included in the DKIM
        key representation itself.
      </t></li><li><t>
        Because above changes remove all use cases for the
        "dkim-quoted-printable" encoding defined in RFC 6376 2.11,
        this specification obsoletes the DKIM-Quoted-Printable encoding.
      </t></li></ul>
    </section>

    <section anchor="Acknowledgements">
      <name>Acknowledgements</name>
      <t>
        Thanks to, in the order of appearance,
        Jesse Thompson,
        Richard Clayton for arguments against reliance on header field
        stacks, and pro the numbering scheme,
        and especially for noticing the partial transaction replay attack
        problem,
        Douglas Foster,
        Michael Thomas for explicit man-in-the-middle replay addressing;
        Alessandro Vesely inspired the explicitness of the E flag,
        Bron Gondwana for the inspiration to split up binary
        differences of headers and body,
        as well as the IANA registry revision,
        Lasse Collin for LZMA2 (and clarification vs XZ),
        and Julian Seward for bzip2.
        A big fat acknowledgment is due to Murray S. Kucherawy.
        Special thanks to Klaus Schulze, Manuel Goettsching,
        both also as Ash Ra Tempel,
        Laeuten der Seele,
        Laurent Garnier,
        as well as the Sleeping Environmental Bot broadcast.
      </t>
    </section>

 </back>
</rfc>
<!-- vim:set tw=1000:s-ts-mode -->
