<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE rfc [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
<!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.24 (Ruby 3.3.6) -->
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" ipr="trust200902" docName="draft-kohbrok-mls-dmls-00" category="info" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true" version="3">
  <!-- xml2rfc v2v3 conversion 3.28.0 -->
  <front>
    <title abbrev="DMLS">Decentralized Messaging Layer Security</title>
    <seriesInfo name="Internet-Draft" value="draft-kohbrok-mls-dmls-00"/>
    <author fullname="Konrad Kohbrok">
      <organization>Phoenix R&amp;D</organization>
      <address>
        <email>konrad.kohbrok@datashrine.de</email>
      </address>
    </author>
    <date year="2025" month="March" day="17"/>
    <area/>
    <workgroup>Messaging Layer Security</workgroup>
    <keyword>security</keyword>
    <keyword>authenticated key exchange</keyword>
    <keyword>end-to-end encryption</keyword>
    <abstract>
      <?line 45?>

<t>Messaging Layer Security provides strong end-to-end security guarantees for
group messaging including Forward Secrecy (FS) and Post-Compromise Security
(PCS). However, MLS requires a Delivery Service (DS) to facilitate agreement
between group members on the order of Commit messages. In decentralized settings
the only way to implement a functional DS is to require group members to retain
key material so they can process commits out-of-order. Retaining key material
this way is in violation of the MLS deletion schedule and significantly reduces
the FS of the protocol. This draft specifies Decentralized MLS, based on the the
Fork-Resilient Continuous Group Key Agreement protocol FREEK proposed by Alwen
et al. <xref target="FRCGKA"/>. In essence, DMLS extends MLS such that key material can be
retained to process Commits out-of-order with minimal losses to FS, thus
allowing safer deployment in decentralized environments.</t>
    </abstract>
    <note removeInRFC="true">
      <name>About This Document</name>
      <t>
        The latest revision of this draft can be found at <eref target="https://phnx-im.github.io/dmls-spec/draft-kohbrok-mls-dmls.html"/>.
        Status information for this document may be found at <eref target="https://datatracker.ietf.org/doc/draft-kohbrok-mls-dmls/"/>.
      </t>
      <t>
        Discussion of this document takes place on the
        Messaging Layer Security  mailing list (<eref target="mailto:mls@ietf.org"/>),
        which is archived at <eref target="https://mailarchive.ietf.org/arch/browse/mls/"/>.
        Subscribe at <eref target="https://www.ietf.org/mailman/listinfo/mls/"/>.
      </t>
      <t>Source for this draft and an issue tracker can be found at
        <eref target="https://github.com/phnx-im/dmls-spec"/>.</t>
    </note>
  </front>
  <middle>
    <?line 60?>

<section anchor="introduction">
      <name>Introduction</name>
      <t>TODO: Introduction</t>
      <t>Open Questions:
- Why do removed members need to receive their commit confirmation from their
  removers? They should be able to process the removing commit without the init
  secret in the first place.
- Is it safe to use the commit secret regularly in the key schedule <em>and</em> to
  derive the commit confirmation or do we need an additional derivation step to
  ensure domain separation?
- Why would we need to generate a fresh signature key pair with each update?
- Do we need an additional membership tag?</t>
    </section>
    <section anchor="epoch-identifiers">
      <name>Epoch identifiers</name>
      <t>In MLS, each epoch is identified by a 64 bit unsigned integer, with the epoch
increasing by one with each commit. The integer identifies epochs uniquely as
long as there is only one chain of Commits. However, in a decentralized context
there can be conflicting commits. For example, if two group member send a commit
at the same time with different subsets of group members receiving a different
commit first. After processing the newly arrived Commit, all group members would
be in the same epoch, but in different group states. For subsequently arriving
messages, it is unclear from the integer designating the epoch, which state the
message belongs to. In such scenarios it is important that epochs are uniquely
identifiable.</t>
      <t>When using DMLS, epochs are represented as byte strings of length <tt>KDF.Nh</tt> (thus
depending on the group's ciphersuite). The byte string identifying an epoch is
derived from the epoch's <tt>epoch_secret</tt> and can thus be learned when creating or
processing the commit that initiates that epoch.</t>
      <t><tt>pseudocode
epoch = DeriveSecret(epoch_secret, "epoch")
</tt></t>
    </section>
    <section anchor="dmls-key-schedule">
      <name>DMLS key schedule</name>
      <t>DMLS conceptually modifies the MLS key schedule by enabling the creation of
multiple <tt>init_secret</tt>s, where each init secret can be used to initialize a
subsequent epoch.</t>
      <t>The individual <tt>init_secret</tt>s are derived through a puncturable pseudorandom
function (PPRF, <xref target="puncturable-pseudorandom-function"/>) keyed by the
<tt>base_init_secret</tt>.</t>
      <figure>
        <name>The DMLS Key Schedule</name>
        <artset>
          <artwork type="svg"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="384" width="400" viewBox="0 0 400 384" class="diagram" text-anchor="middle" font-family="monospace" font-size="13px" stroke-linecap="round">
              <path d="M 152,88 L 152,176" fill="none" stroke="black"/>
              <path d="M 152,248 L 152,272" fill="none" stroke="black"/>
              <path d="M 152,304 L 152,336" fill="none" stroke="black"/>
              <path d="M 152,128 L 176,128" fill="none" stroke="black"/>
              <polygon class="arrowhead" points="184,128 172,122.4 172,133.6" fill="black" transform="rotate(0,176,128)"/>
              <polygon class="arrowhead" points="160,336 148,330.4 148,341.6" fill="black" transform="rotate(90,152,336)"/>
              <polygon class="arrowhead" points="160,272 148,266.4 148,277.6" fill="black" transform="rotate(90,152,272)"/>
              <polygon class="arrowhead" points="160,176 148,170.4 148,181.6" fill="black" transform="rotate(90,152,176)"/>
              <g class="text">
                <text x="28" y="36">(above</text>
                <text x="72" y="36">the</text>
                <text x="108" y="36">same</text>
                <text x="140" y="36">as</text>
                <text x="168" y="36">the</text>
                <text x="200" y="36">MLS</text>
                <text x="232" y="36">key</text>
                <text x="288" y="36">schedule)</text>
                <text x="152" y="52">|</text>
                <text x="156" y="84">epoch_secret</text>
                <text x="248" y="132">DeriveSecret(.,</text>
                <text x="348" y="132">&lt;label&gt;)</text>
                <text x="192" y="148">=</text>
                <text x="236" y="148">&lt;secret&gt;</text>
                <text x="160" y="196">DeriveSecret(.,</text>
                <text x="284" y="196">"parent_init")</text>
                <text x="152" y="212">|</text>
                <text x="164" y="244">parent_init_secret</text>
                <text x="156" y="292">DeriveChildSecret(.,</text>
                <text x="296" y="292">"child_init",</text>
                <text x="316" y="308">commit_confirmation,</text>
                <text x="304" y="324">GroupContext_[n])</text>
                <text x="160" y="356">init_secret_[n]</text>
              </g>
            </svg>
          </artwork>
          <artwork type="ascii-art"><![CDATA[
        (above the same as the MLS key schedule)
                          |
                          V
                     epoch_secret
                          |
                          |
                          +--> DeriveSecret(., <label>)
                          |    = <secret>
                          |
                          V
                    DeriveSecret(., "parent_init")
                          |
                          V
                   parent_init_secret
                          |
                          V
                 DeriveChildSecret(., "child_init",
                          |          commit_confirmation,
                          |          GroupContext_[n])
                          V
                    init_secret_[n]
]]></artwork>
        </artset>
      </figure>
      <sourcecode type="pseudocode"><![CDATA[
commit_confirmation = DeriveSecret(path_secret[n], "conf")

DeriveChildSecret(prf_key, label, input_secret, context) =
  DeriveFSSecret(prf_key, ExpandWithLabel(input_secret, label, context, KDF.Nh))
]]></sourcecode>
    </section>
    <section anchor="puncturable-pseudorandom-function">
      <name>Puncturable pseudorandom function</name>
      <t>A PPRF allows the derivation of keys in a forward secure way. In particular, a
PRF that was evaluated with a given key and input can't be evaluated with those
same parameters again. Storing the original input key thus doesn't harm the
forward secrecy of (deleted) output keys.</t>
      <t>The MLS Secret Tree as defined in <xref target="RFC9420"/> already represents a PPRF an
needs to be modified only slightly for the purpose of this document.</t>
      <t>In the context of MLS, the Secret Tree has as many leaves as the group has
members. To derive child init secrets, the same tree is used but with <tt>KDF.Nh</tt>
leaves.</t>
      <t>The function <tt>DeriveFSSecret(secret, input)</tt> thus follows these steps:</t>
      <ul spacing="normal">
        <li>
          <t>Check if <tt>secret</tt> and <tt>input</tt> are of length <tt>KDF.Nh</tt></t>
        </li>
        <li>
          <t>With <tt>secret</tt> as the root node secret and <tt>input</tt> as the leaf index, derive
the direct path nodes and the copath nodes as defined in Section 9 of
<xref target="RFC9420"/></t>
        </li>
        <li>
          <t>With <tt>leaf_node_secret</tt> as the resulting secret compute the final output using
<tt>DeriveSecret(leaf_node_secret, "pprf")</tt></t>
        </li>
      </ul>
    </section>
    <section anchor="state-consolidation">
      <name>State consolidation</name>
      <t>The changes to MLS outlined above allow the processing of multiple commits for
each epoch with improved forward secrecy. However, once a fork was created, they
do not help in returning group members to a single, agreed-upon group state.</t>
      <t>There is no one semantic to consolidate forks that is optimal for all given
applications. Even more so if the application uses extensions that store
additional data in the group's context.</t>
      <t>This section thus details a simple state-consolitation procedure that focuses on
consolidating group membership and key material only. To keep it simple, our
approach makes a few assumptions.</t>
      <t>TODO: The following is work in progress. While the assumptions won't disappear
entirely, they will become weaker in future iterations.</t>
      <ul spacing="normal">
        <li>
          <t>One group forked at epoch e_i</t>
        </li>
        <li>
          <t>Only one partition, half of the group on one side, the other on the other side</t>
        </li>
        <li>
          <t>Both sides of the partition have a server that helps them agree on commit
ordering (imagine a netsplit in a federated approach with only two servers
involved)</t>
        </li>
        <li>
          <t>The two servers involved coordinate in allowing commits/preventing forks</t>
        </li>
        <li>
          <t>Neither clients nor servers keep around old messages, but do keep around old
group states s.t. they can process old messages</t>
        </li>
        <li>
          <t>No insider attacks, i.e. no insider is trying to create a fork and then make
the others accept the new state</t>
        </li>
        <li>
          <t>No access control: All parties can add and remove members as they please</t>
        </li>
        <li>
          <t>KeyPackages are accessible: All parties can access KeyPackages of all other
parties</t>
        </li>
      </ul>
      <t>Open Questions:
- How to determine which fork wins, i.e. which fork is merged into which?
  Options:
  - Arbitrary: The fork with the alphanumerically highest transcript hash wins
- Is it mandatory that the consolitation algorithm is deterministic s.t.
  everyone can compute it and arrive at the same result?</t>
      <t>Timeline:
- Alice, Alan, Bob and Betty are in a group
- Alice and Alan on server A, Bob and Betty on server B
- There is a disconnect between servers A and B
- All group members keep sending messages
- Alice adds Albert to the group
- Betty removes Bob from the group
- The servers reconnect
- All parties receive and process all messages from the other side
- All parties now have two forks of the same group
- One party (say Alice) starts the consolitation procedure (see below)</t>
      <section anchor="consolidation-algorithm">
        <name>Consolidation algorithm</name>
        <ul spacing="normal">
          <li>
            <t>Given two forks, choose the one with the alphanumerically larger transcript hash</t>
          </li>
          <li>
            <t>On the losing fork, create a commit with a proposal that indicates that this
fork is closed</t>
          </li>
          <li>
            <t>On the winning fork, create a commit that consolidates the group membership of
both forks:
            </t>
            <ul spacing="normal">
              <li>
                <t>If a member was removed in the losing fork but not on the winning fork,
remove it in the commit</t>
              </li>
              <li>
                <t>If a member was added in the losing fork, but not on the winning fork, add
it in the commit</t>
              </li>
            </ul>
          </li>
        </ul>
        <t>Open Questions:
- What if a member was removed in both forks and then re-added in the winning
  fork? Should it still be removed in the consolidating commit? Resolving this
  is tricky if not everyone has the message traces for both forks.
- What if there is no overlap in members? In that case, there is no way to
  consolidate, because no one can create a commit in the other fork.
  - Maybe that's okay? In that case, there's not much to consolidate. Should the
    losing fork be closed? Or should both forks live on? Might depend on the
    application.</t>
      </section>
    </section>
    <section anchor="security-considerations">
      <name>Security Considerations</name>
      <t>TODO Security</t>
      <ul spacing="normal">
        <li>
          <t>Note that while the PPRF gives you FS for init secrets, you also need to keep
the secret state of old RatchetTree states around, thus damaging their FS</t>
        </li>
      </ul>
    </section>
    <section anchor="iana-considerations">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
  </middle>
  <back>
    <references anchor="sec-combined-references">
      <name>References</name>
      <references anchor="sec-normative-references">
        <name>Normative References</name>
        <reference anchor="RFC9420">
          <front>
            <title>The Messaging Layer Security (MLS) Protocol</title>
            <author fullname="R. Barnes" initials="R." surname="Barnes"/>
            <author fullname="B. Beurdouche" initials="B." surname="Beurdouche"/>
            <author fullname="R. Robert" initials="R." surname="Robert"/>
            <author fullname="J. Millican" initials="J." surname="Millican"/>
            <author fullname="E. Omara" initials="E." surname="Omara"/>
            <author fullname="K. Cohn-Gordon" initials="K." surname="Cohn-Gordon"/>
            <date month="July" year="2023"/>
            <abstract>
              <t>Messaging applications are increasingly making use of end-to-end security mechanisms to ensure that messages are only accessible to the communicating endpoints, and not to any servers involved in delivering messages. Establishing keys to provide such protections is challenging for group chat settings, in which more than two clients need to agree on a key but may not be online at the same time. In this document, we specify a key establishment protocol that provides efficient asynchronous group key establishment with forward secrecy (FS) and post-compromise security (PCS) for groups in size ranging from two to thousands.</t>
            </abstract>
          </front>
          <seriesInfo name="RFC" value="9420"/>
          <seriesInfo name="DOI" value="10.17487/RFC9420"/>
        </reference>
      </references>
      <references anchor="sec-informative-references">
        <name>Informative References</name>
        <reference anchor="FRCGKA" target="https://eprint.iacr.org/2023/394.pdf">
          <front>
            <title>Fork-Resilient Continuous Group Key Agreement</title>
            <author initials="J." surname="Alwen" fullname="Joël Alwen">
              <organization/>
            </author>
            <author initials="M." surname="Mularczyk" fullname="Marta Mularczyk">
              <organization/>
            </author>
            <author initials="Y." surname="Tselekounis" fullname="Yiannis Tselekounis">
              <organization/>
            </author>
            <date year="2024" month="February" day="22"/>
          </front>
        </reference>
      </references>
    </references>
    <?line 251?>

<section numbered="false" anchor="acknowledgments">
      <name>Acknowledgments</name>
      <t>TODO acknowledge.</t>
    </section>
  </back>
  <!-- ##markdown-source:
H4sIAAAAAAAAA61a7W4bR5b9309RywAbCUtShhMsEGEcjSxZGa/j2CsZGywW
C6nYXWQX1Ozq6aoWzWScF5rHmBebc25VN5uU7NmdGSORyO6qW/fz3I/SbDbL
gg2VOVWTS5ObOrS6sr+YQr013uuVrVfqR701rboxedfasJ1kerFozQM3vP3x
ZpLlOpiVa7enytZLl2WFy2u9BsGi1cswu3flonX3s3XlZwV/PHuW+W6xtt5b
V4dtg5WvX324UuorpSvvQNfWhWkMftRhMlUTU9jgWqsrfnl9/hK/XItP1x+u
JlndrRemPc0KcHGa5a72pvadP1Wh7UwGLr/JdGs0qE6yjWvvV63rGnz7vHj3
ZouFxWmmZsqnp/ysu1CCI0t5C4VVynzMS12vDN+C3VlwM/zCx7zdNgHSZQ+m
7sCWUn/7WKWiLib8uNa2wkeo6/fWhOXctSs+1m1e4nEZQuNPT064io/sg5n3
y0744AQa33hzgv0n3LeyoewW2NmU9ceZXZ+IIXxjcr6tIJAPI7pp1Txum1u3
W3/ytFHnZVhXkyyjjlxL1YGuUsuuqqIvvHF1qwv8kn3yEszq2v6iqahT9b50
prYf1fW/XspbE1VwL/vm6bzfw8ral62tzbwwWVa7do39D1BxRucbvil1dX3x
w5vzU6EVdLsyELCXzzSgEOZW562o7Pmz59+cfPPdt/OmWMYNKSKu4DCza+Nt
ZWF5dQF/tXXnOq9+oD3VGzjB+ao1Zk1Xla3ihwoUv509ez57/lweDmqRfzMV
dfIf7i9/rtR5tTH1wZu3ug1ave1o3V+29wdv/9vqurZeffCmMveuw+csy2Yz
uOjCI37zkGWf8zPVtO7BFsYrrHR4PfLb3tnVqtOtroPBKug0E99V64GirfOq
K/gJ+tnotiD11uRbdXR1c6w0SL13Pswu3BqnIdDNcHx29P7i5niu/uA25sG0
UwUEUa35Y2dbHKbVpalgv3aLDe2DzY06ugTF4NRS5zBCgHKV7hWeLUzYGFOr
nkEigVeuVghUuFcBud0SVluvbUj8Gz9Xr2tV7EGdNwF2XflM9tXVVm30lqfa
dVPJUWBt2dU5XVVX6vJGQf14nzg/YEBeBG1rQglCORiCl/KOfG1VrmtaIQc/
KhfewHMXZm45E57n6lp2U8FjAuAOp5Iz/LK1erCukuChkOScuizgEvLM56Up
usqIObxd1XYJ5KoDhGvxAqeLtFc3/W6wFFzuqrn6wHMkzhVDHhthm4Pk8OPN
VC20x8ekbvyf/b/CZTgQofrq1Rt+bRwJLrYpJgzUDnZ+/TXG8qdPYjqoDQBr
porZBxAc4LpeZPddXoIPHfbUJvpemCyaBPRhnl79F0+oX22AemoN/a+xuXI4
Tkx6BYkBhz7TVeU2NI7XSyxHqqrcViSyh45l6geLKONLP48hurZFUQG6voIs
iEBYQhJF9uHd5bvTg2fvkATVf3YAZ3z1p9lM/VxuVUH3WrsH0O89rjZRLgSh
QfzQGLZNzoVf9dIKMsJUSwRkfA1QiWRafwaTQ2O+dF0F/cNnFnCckZ5oYFlM
sRNZqgl6k3dQVgA9TxgQNfAhDvWwcqVzMwfrr+G0QXRGyp0XLntiaWdrVsQ8
+GiiQUMOnnwLV77FZpwEOyU5n5QS5QG0tDFRMbC/LlBDxOCVrXGZD6aJ9Fgz
II4Lh6yD56YBAHLJWdL5RjTTEwT/K1ObVtAIKjW+lBDTgUTIc6NtciSj4ZRd
w7RAYpefYyuZsrTgSK/O6CCvGoe9lmUQY7AFysP/JfSEqonv/W6JBI9W//6t
WkAlXU2m8BDJzqyItsIRlSZbkTKhde1pVOxztRmxHNVKMDD9/t05PhLwOML+
sTOwl/ZZxXSixVmgBesjkpIqqiRb76DYj/Afz/VB0MCSAWGdRToxesW8lc3D
zgFBBXgDANAEaVACjG3cHhTDkAA/nTZkOjqrRxJFhl8naQu7RBgzfFGVIhN4
MroP6DGseLTeLc+S44mbz9X5EnDTBwyX8qjabKibls5aJOmnALXq4ABxL6Sz
3u2FRVExULaLwDKwGbd65sKkA2EcdhB0l9PAQNYnvCnjztJWeWV0O0DAYFZU
A+K8Pdfp4E1p4QdyjqB7ogdr0NLERMFjQV0PA+rWOp/OQuJ0KGHqEPE4eQsK
8cFjst6ZiDXAxp9RWwMVyMNldPHdnhYFm4EtWXfDwRZbcITyhSmbxqpMvYIh
795cXs1/Ku/UkcB0bCFIL2Uo0dvXyLm2gWf5zgZzHP17RLD38a1Yux5iLIuI
U+y0J29A7k4+3EYEu5N0S58lD3RcqpwxuKF8DDdRM6qqA1dJ3iTqIpxamnek
Pajo7u6u8aZDf+VQ/EbOXiAxkzGpwMLRmBd2Tvw6OeZOAopkzDGkZpk8QnDl
pgkdHBN50xUxxPuSYg+DgROw9KIa2BaJpAbJ1l0VLGJR3VGAXiOensRIFljh
mx7tU2h3PkJqlJoYoHS2c+lB/IhEBZy7AKcHh4if9DYKJUy9KhGtDYu2rpV8
FnWHwhYon/XVnDp6//76aooiY7R0Nl4665d++nRMXUSQZUDcsQC6HbMBLn/7
7TeltX9YpaJdqSO9cClXSVzrp1V7PGx4/O9PX3j3X0+/G3vC30n5S+/+bTb7
ft/15lP1u0oDHL7/oiT88UL9LjL2/T9V5kN2JsjicCCx0OSfqt4R4X9MxU9Q
j1JclLYqRqLk/B4lmf4t9cZ/EVBux3XR/3GnFOsXMQvf/k/9v19S3dOWGCmG
BBgU2a+nsa1+MWEgC+6wH7hJ7j9Rn2LwjCDuCREOAa/RofdyHERFYTGMnT1W
Y9MubxFwUyVeytKj6cKAlanqOFYvst4GVzeHO199bIAJP6Ns+JE0jvZJJLqJ
0lTFfHR8LOIDft9/BoyG1jLLzhXhSEmLEWFiVK4i1YELH2umZWq9pWk3bAsl
G8Mzg81ZRKPOyEhLUsgGoGMedNXJ7ErqHq1WkLEWDGLSElmIyV8HovLBatT6
3mSCX6yN1yawbtErFHZzdcPxXEoI+LSyLGgjPVKXVFg440m61K3kz2wkgMwO
IN2RdK+mOGZDlnb7hPz0l2gO9QEdJFG0MEsby1vA979cX1189+3zZ58+QXtI
SsV2VzZwshD1WmcsvaWfg4wp1RWxUvWVXZWsoMBZ7Ii7lh1pbJDZEru8Yys3
lzo8Jm0xNVdIzcJnYyZLcIn/1rreshB4ML5H/1jE4X2WakBUIq5vayTYx6nS
T0eVKwmznJNeuYuN2FD8ZPGYpLQhy90deHTvsmKk47tooqUb3M4baY7Qc6Jn
uShNfs/6+m5c5NzJ3jtJvI+LMPZNwtewJXWRzgVVI7j7ImCPVFwDEZbM9Obj
NGmEw1HGgoWnoKVEzAsNL7ujIcYP91wDEosKvmOJovY8ZWCSJ95y8+0hu8az
qGGzn2oWtwarJjW49PPkqlK6gv7dHjwdEmZSAppMjqUeu5HamjNrV9lCp0FA
KQ1TvYpjB/o9jqhEnFhJCDr0M5u+hoQJhvqrnypxeDfqFMVRLGdyUsjux9+o
J2M1GBHmXoBDajxTiA9uMzTWNWxYmqqheiFU18qs6tEQTCtyxt5MRnbFrGtc
PW5fopfGZrF20ip6g2ABgnH/TjFGmEnlMDvLJsh0hpEq3RSRLNNNU3E6z2HJ
XL0iuK0dqHsnzSH0NVrB+PFxfMR7iETbA8lMNp4W6KD7rmxoIGLUC/dgxicH
izDHKVPlRXb2pVHQWRIlxKPFbAVhWw5dAlfIDKw/8oVDjXIyQHffm20RuAQ5
7o1pZL5iYzfsupb6aB3Nv9b3Ml1dmg0c23frJuqonzoJVLh+rMUhI01vhVFY
zkObPwOSotePCGAdIb2wHkehz8nYOrVo7qKrwOFgm4WBOyJBGTDRkuiykzEJ
2q9W93zM1Lu6B0Wamr6eKn+FElvep2GCZDipZgCf1bIfX8a9zJL0InRxETId
pwjDSFi+8CUIvsQ3+eyHCWhPGYQZZrBsi4CIRqK/CyasozeTZporqDhrpu6O
4JZIf9xcA7bhbSGla1PIvKhQg1UkHCXzcG4Rz/IZi6cHVyFCj8EkLTN6O7zD
0TgT+BNkZjCMJFPknyDxPdAYeCSRA1I/GSvi5zKcZcC1A1nxHg0Nwr9cVajd
6IAJpnCHC/oLrTSFUH4e5o+H22NKZIAtHhWOmA1B5/ecTMzNnKHfv+BYvZXe
m/EvuNMjUYL6Wrw5JQQxKDw7Z/vaT1wiU/FAvvExYltXnapzOKSYGUzncQAn
hOMkdACviP5bhVBCiwdSqFTfg2NKIgkv0rUL3hI9ohnPHG+BgxGmhN1M9auf
GvD+gcjOQgDRsaYjxSlMxGJoKals9BQqW5t2Fcd8Lr45wyHvmkSUF0fn7cKG
VvOSNga7kEvDQF01yDcobVpgI0cAJQoh8ART6NrnrW1YtvlSGBgmucBpwJRr
tzE+Ujk0QjldrVAMhnJNFnuBrCe40184deVVjwwIdT1kVhtrgjg0U+OZXUzG
Z0AtuzZMiFTYOQAdsX5eaQDCS7eQzS9NCFsxlASf+Gq/VhZwOSM4Rfj54dbd
q5cxCmOS4vjPQ8qaZUh/+9QH0XncL+ccDvgkfnyaR41iInFUoCQ9r7Ay0PgD
nBGlhJ3onl6YHAZQ/RIatOcBmTxyl7jo/bK/GCCHfXjSI3tWdlT3MHJMooZn
Ci4Sj2I6Trgpxum5eZcgequOvN5GAY8Zkm3wTzjJLhWiJo2zxQ26t6++4u3R
rizaORNzxQ/SuAx8oOUqnUsXCsMU+0nPrngT3B46trAdS0/ne8yc7vBndOPB
mZJcVCH5plldIX8R4PswsMTwPjLzildaO/qIoPrzBwiFUdUzbhVGVYDUsQum
LxE/RvhrQEw/9mbR1l8R2UeCCaazhHNP8CTtfEJDO1zlDInu8Tnw3SdPmX7x
GG6Tox6d8eSlF/X8efl2qtglidbM9jhLpyfTnKmbeNfFiinEKuVQY/ulWOTu
TF0bPHyIza5YWjKWze+35JDiDqBWph6in5vzZj7eqI84no/kC+NaGFQqLRV2
svyZkqaTHoKcNN1bHa+rMzV2nikrL817tlRaC8geeJwdF0ZkaC5Gfqu3i1ic
otx193r75OFfexF4Ldeue+X6vNcvG32aec/9TAqLM/WuHS4ddzbkXwCA4TP1
lv24inP85EXxryl2VTxKx0w6qf5PF4gatugry1jg7v76QIqCkMruzVDSymyA
PYRXW9fxTpxG2u+/+YJ/njTcABLSUxmSesN4VQJQZOFzrUNemiBjgFQlxfpp
mhoFvY5/TRHvaq9uRI7X5z+dP5ZhPHwQt4JFZaXO+wJa7pYXqDdI5Ty/B1pX
pljJzXP262n8KylTvJgsIYSZfEqa0cNKNGN/Bae7aasMJgAA

-->

</rfc>
