<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
<xep xmlns="">
<header>
  <title>OpenPGP for XMPP</title>
  <abstract>Specifies end-to-end encryption and authentication of data with the help of
  OpenPGP, announcement, discovery and retrieval of public keys and a
  mechanism to synchronize secret keys over multiple
  devices.</abstract>
  
<legal>
<copyright>This XMPP Extension Protocol is copyright © 1999 – 2024 by the <link url="https://xmpp.org/">XMPP Standards Foundation</link> (XSF).</copyright>
<permissions>Permission is hereby granted, free of charge, to any person obtaining a copy of this specification (the "Specification"), to make use of the Specification without restriction, including without limitation the rights to implement the Specification in a software program, deploy the Specification in a network service, and copy, modify, merge, publish, translate, distribute, sublicense, or sell copies of the Specification, and to permit persons to whom the Specification is furnished to do so, subject to the condition that the foregoing copyright notice and this permission notice shall be included in all copies or substantial portions of the Specification. Unless separate permission is granted, modified works that are redistributed shall not contain misleading information regarding the authors, title, number, or publisher of the Specification, and shall not claim endorsement of the modified works by the authors, any organization or project to which the authors belong, or the XMPP Standards Foundation.</permissions>
<warranty>## NOTE WELL: This Specification is provided on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. ##</warranty>
<liability>In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall the XMPP Standards Foundation or any author of this Specification be liable for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising from, out of, or in connection with the Specification or the implementation, deployment, or other use of the Specification (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if the XMPP Standards Foundation or such author has been advised of the possibility of such damages.</liability>
<conformance>This XMPP Extension Protocol has been contributed in full conformance with the XSF's Intellectual Property Rights Policy (a copy of which can be found at &lt;<link url="https://xmpp.org/about/xsf/ipr-policy">https://xmpp.org/about/xsf/ipr-policy</link>&gt; or obtained by writing to XMPP Standards Foundation, P.O. Box 787, Parker, CO 80134 USA).</conformance>
</legal>
  <number>0373</number>
  <status>Experimental</status>
  <type>Standards Track</type>
  <sig>Standards</sig>
  <approver>Council</approver>
  <dependencies>
    <spec>XMPP Core</spec>
    <spec>XEP-0030</spec>
    <spec>XEP-0082</spec>
    <spec>XEP-0163</spec>
    <spec>XEP-0223</spec>
    <spec>XEP-0334</spec>
  </dependencies>
  <supersedes/>
  <supersededby/>
  <shortname>ox</shortname>
  
  <author>
    <firstname>Florian</firstname>
    <surname>Schmaus</surname>
    <email>flo@geekplace.eu</email>
    <jid>flo@geekplace.eu</jid>
  </author>

  <author>
    <firstname>Dominik</firstname>
    <surname>Schürmann</surname>
    <email>dominik@dominikschuermann.de</email>
    <jid>dominik@dominikschuermann.de</jid>
  </author>
  <author>
    <firstname>Vincent</firstname>
    <surname>Breitmoser</surname>
    <email>look@my.amazin.horse</email>
    <jid>valodim@stratum0.org</jid>
  </author>
  <revision>
    <version>0.7.0</version>
    <date>2021-05-04</date>
    <initials>ps</initials>
    <remark>
      <p>Recommend PubSub access model 'open' for public key data node and metadata node.</p>
    </remark>
  </revision>
  <revision>
    <version>0.6.0</version>
    <date>2020-11-22</date>
    <initials>fs</initials>
    <remark>
      <p>Fix 'to'-attribute requirements: All content elements which are signed using OpenPGP need
      that attribute to prevent Surreptitious Forward Attacks. The &lt;crypt/&gt; element does not require
      one, as the intented recipient is established by the encryption itself. The XEP had the
      requirements for &lt;sign/&gt; and &lt;crypt/&gt; mixed up.</p>
    </remark>
  </revision>
  <revision>
    <version>0.5.0</version>
    <date>2020-06-19</date>
    <initials>fs</initials>
    <remark>
      <ul>
        <li>Use RFC 4880 terminology: it is "primary key", not "master key".</li>
        <li>Clarify encryption of secret key material.</li>
        <li>Move the information from the 'date' attribute into the item ID.</li>
      </ul>
    </remark>
  </revision>
  <revision>
    <version>0.4.0</version>
    <date>2018-07-30</date>
    <initials>ps</initials>
    <remark>Fix node name in examples</remark>
  </revision>
  <revision>
    <version>0.3.3</version>
    <date>2018-07-30</date>
    <initials>ps</initials>
    <remark>Improve note about OpenGPG fingerprint; editorial fixes</remark>
  </revision>
  <revision>
    <version>0.3.2</version>
    <date>2018-07-05</date>
    <initials>ps</initials>
    <remark>Add example and small editorial fixes</remark>
  </revision>
  <revision>
    <version>0.3.1</version>
    <date>2018-05-21</date>
    <initials>ps</initials>
    <remark>Fix slightly incorrect reference to RFC 4880</remark>
  </revision>
  <revision>
    <version>0.3.0</version>
    <date>2018-04-16</date>
    <initials>fs</initials>
    <remark>
      Split public keys into metadata and data nodes.
    </remark>
  </revision>
  <revision>
    <version>0.2.1</version>
    <date>2017-11-13</date>
    <initials>fs</initials>
    <remark>
      <ul>
        <li>Recommend setting the PubSub configuration field 'send_last_published_item' to 'on_sub'.</li>
        <li>Only recommend persistent PubSub nodes.</li>
      </ul>
    </remark>
  </revision>
  <revision>
    <version>0.2</version>
    <date>2017-09-11</date>
    <initials>XEP Editor (jwi)</initials>
    <remark>Defer due to lack of activity.</remark>
  </revision>
  <revision>
    <version>0.1.3</version>
    <date>2016-07-15</date>
    <initials>fs (XEP Editor: ssw)</initials>
    <remark><p>Update acknowledgements.</p></remark>
  </revision>
  <revision>
    <version>0.1.2</version>
    <date>2016-07-11</date>
    <initials>bjc (XEP Editor: ssw)</initials>
    <remark><p>Minior editorial fixes.</p></remark>
  </revision>
  <revision>
    <version>0.1.1</version>
    <date>2016-06-04</date>
    <initials>fs</initials>
    <remark><p>Minior editorial fixes.</p></remark>
  </revision>
  <revision>
    <version>0.1</version>
    <date>2016-05-10</date>
    <initials>XEP Editor (ssw)</initials>
    <remark><p>Initial published version approved by the XMPP Council.</p></remark>
  </revision>
  <revision>
    <version>0.0.1</version>
    <date>2016-03-25</date>
    <initials>fs</initials>
    <remark><p>First draft.</p></remark>
  </revision>
</header>

<section1 topic="Introduction" anchor="intro">

  <p>This XMPP extension protocol specifies the foundations of
  end-to-end encryption and authentication, based on digital
  signatures, of data with the help of OpenPGP. Additional XEPs will
  use this extension protocol as building block when specifying their
  own OpenPGP profile suiting their use case. One such profile is the
  Instant Messaging Profile specified in <span class="ref"><link url="https://xmpp.org/extensions/xep-0374.html">OpenPGP for XMPP Instant Messaging (XEP-0374)</link></span> <note>XEP-0374: OpenPGP for XMPP Instant Messaging &lt;<link url="https://xmpp.org/extensions/xep-0374.html">https://xmpp.org/extensions/xep-0374.html</link>&gt;.</note>.</p>

  <p>XMPP provides the mechanisms to solve a lot of issues that come
  with modern day OpenPGP usage. For example, based on <span class="ref"><link url="https://xmpp.org/extensions/xep-0163.html">Personal Eventing Protocol (XEP-0163)</link></span> <note>XEP-0163: Personal Eventing Protocol &lt;<link url="https://xmpp.org/extensions/xep-0163.html">https://xmpp.org/extensions/xep-0163.html</link>&gt;.</note> this
  specification describes a standardized way to discover OpenPGP
  public keys of other entities. But unlike the OpenPGP keyservers,
  this process establishes a strong relation between the key and the
  key's owning entity (usually a human user). A similar mechanism
  described herein allows to synchronize the secret key(s) across
  multiple devices.</p>

  <p>OpenPGP in return allows for end-to-end encrypted data to be
  exchanged between one, two or even multiple entities
  (multi-end-to-multi-end encryption). Therefore this XEP can be used
  for example to implement end-to-end encrypted <span class="ref"><link url="https://xmpp.org/extensions/xep-0045.html">Multi-User Chat (XEP-0045)</link></span> <note>XEP-0045: Multi-User Chat &lt;<link url="https://xmpp.org/extensions/xep-0045.html">https://xmpp.org/extensions/xep-0045.html</link>&gt;.</note>.</p>

</section1>

<section1 topic="Glossary" anchor="glossary">

  <dl>
    <di><dt>OpenPGP element</dt><dd>An XMPP extension element: &lt;openpgp/&gt; qualified by the 'urn:xmpp:openpgp:0' namespace</dd></di>
    <di><dt>OpenPGP content element</dt><dd>An element embedded via OpenPGP in a &lt;openpgp/&gt; element. Either one of &lt;signcrypt/&gt;, &lt;sign/&gt; or &lt;crypt/&gt;, qualified by the 'urn:xmpp:openpgp:0' namespace.</dd></di>
    <di><dt>PEP</dt><dd><span class="ref"><link url="https://xmpp.org/extensions/xep-0163.html">Personal Eventing Protocol (XEP-0163)</link></span> <note>XEP-0163: Personal Eventing Protocol &lt;<link url="https://xmpp.org/extensions/xep-0163.html">https://xmpp.org/extensions/xep-0163.html</link>&gt;.</note></dd></di>
    <di><dt>Public-Key metadata node ("metadata node")</dt><dd>A PEP node containing metadata of the entity's public OpenPGP key.</dd></di>
    <di><dt>Public-Key data node ("data node")</dt><dd>A PEP node containing an entity's public OpenPGP key.</dd></di>
    <di><dt>Secret-Key node</dt><dd>A PEP node containing an entity's encrypted secret OpenPGP key.</dd></di>
    <di><dt>OpenPGP v4 Fingerprint String</dt><dd>A String representing the OpenPGP v4 fingerprint
    of a key. If the key consists of a primary key and subkeys, this is the fingerprint of the
    primary key.</dd></di>
  </dl>

</section1>

<section1 topic="OpenPGP Encrypted and Signed Data" anchor="signcrypt">

  <section2 topic="Exchanging OpenPGP Encrypted and Signed Data" anchor="exchange">

    <p>The &lt;openpgp/&gt; extension element qualified by the
    'urn:xmpp:openpgp:0' namespace is used in order to exchange
    encrypted and signed data.</p>

    <example caption="The &lt;openpgp/&gt; extension within a message."><![CDATA[
<message to='juliet@example.org'>
  <openpgp xmlns='urn:xmpp:openpgp:0'>
    BASE64_OPENPGP_MESSAGE
  </openpgp>
</message>]]></example>

    <p>The text content of &lt;openpgp/&gt; ("BASE64_OPENPGP_MESSAGE") is a
    Base64 encoded (<span class="ref"><link url="http://tools.ietf.org/html/rfc4648">RFC 4648</link></span> <note>RFC 4648: The Base16, Base32, and Base64 Data Encodings &lt;<link url="http://tools.ietf.org/html/rfc4648">http://tools.ietf.org/html/rfc4648</link>&gt;.</note> <link url="https://tools.ietf.org/html/rfc4648#section-4">§ 4</link>)
    OpenPGP message as specified in <span class="ref"><link url="http://tools.ietf.org/html/rfc4880">RFC 4880</link></span> <note>RFC 4880: OpenPGP Message Format &lt;<link url="http://tools.ietf.org/html/rfc4880">http://tools.ietf.org/html/rfc4880</link>&gt;.</note> which contains an
    encrypted and/or signed UTF-8 (<span class="ref"><link url="http://tools.ietf.org/html/rfc3629">RFC 3629</link></span> <note>RFC 3629: UTF-8, a transformation format of ISO 10646 &lt;<link url="http://tools.ietf.org/html/rfc3629">http://tools.ietf.org/html/rfc3629</link>&gt;.</note>) encoded string. This
    string MUST correspond to exactly one OpenPGP content element,
    that is, it represents either a &lt;signcrypt/&gt;, a &lt;sign/&gt; or a &lt;crypt/&gt;
    extension element qualified by the 'urn:xmpp:openpgp:0'
    namespace. Note that OpenPGP's ASCII Armor is not used, instead
    the XMPP client MUST encode the raw bytes of the OpenPGP message using
    Base64.</p>

    <p>In case of a &lt;signcrypt/&gt; element, the OpenPGP message embedded
    in the &lt;openpgp/&gt; element MUST be encrypted and signed, and SHOULD
    also be encrypted to self. In case of a &lt;sign/&gt; element, the
    OpenPGP message MUST be signed and MUST NOT be encrypted. In case
    of &lt;crypt/&gt; the OpenPGP message MUST NOT be signed, but MUST be
    encrypted.</p>

    <example caption="The &lt;signcrypt/&gt; extension element."><![CDATA[
<signcrypt xmlns='urn:xmpp:openpgp:0'>
  <to jid='juliet@example.org'/>
  <time stamp='2014-07-10T17:06:00+02:00'/>
  <rpad>
    f0rm1l4n4-mT8y33j!Y%fRSrcd^ZE4Q7VDt1L%WEgR!kv
  </rpad>
  <payload>
    <body xmlns='jabber:client'>
      This is a secret message.
    </body>
  </payload>
</signcrypt>]]></example>

    <p>OpenPGP content elements MUST possess exactly one 'time'
    element as direct child elements. The &lt;signcrypt/&gt; and &lt;sign/&gt;
    content elements MUST contain at least one 'to' element(s), which
    MUST have a 'jid' attribute containing the intended recipient's
    XMPP address of the signed and/or encrypted data to prevent
    Surreptitious Forward Attacks<note>Jee Hea An, Yevgeniy Dodis, and
    Tal Rabin. 2002. On the Security of Joint Signature and
    Encryption. In Proceedings of the International Conference on the
    Theory and Applications of Cryptographic Techniques: Advances in
    Cryptology (EUROCRYPT '02), Lars R. Knudsen
    (Ed.). Springer-Verlag, London, UK, UK, 83-107. &lt;<link url="https://www.iacr.org/archive/eurocrypt2002/23320080/adr.pdf">https://www.iacr.org/archive/eurocrypt2002/23320080/adr.pdf</link>&gt;</note>.
    The XMPP address found in the 'to' element's 'jid' attribute
    SHOULD be without Resourcepart (i.e., a bare JID). A &lt;crypt/&gt; content
    element may not carry a 'to' attribute. The 'time' element MUST
    have a 'stamp' attribute which contains the timestamp when the
    OpenPGP content element was signed and/or encrypted in the
    DateTime format as specified in <span class="ref"><link url="https://xmpp.org/extensions/xep-0082.html">XMPP Date and Time Profiles (XEP-0082)</link></span> <note>XEP-0082: XMPP Date and Time Profiles &lt;<link url="https://xmpp.org/extensions/xep-0082.html">https://xmpp.org/extensions/xep-0082.html</link>&gt;.</note> § 3.2. The &lt;signcrypt/&gt;
    and &lt;crypt/&gt; elements SHOULD furthermore contain a 'rpad' element
    which text content is a random-length random-content padding.</p>

    <table caption="OpenPGP Content Element Properties">
      <tr>
        <th>Content Element</th>
        <th>'to' Element</th>
        <th>'time' Element</th>
        <th>&lt;rpad/&gt; Element</th>
        <th>&lt;payload/&gt; Element</th>
      </tr>
      <tr>
        <td>&lt;signcrypt/&gt;</td>
        <td>MUST have at least one</td>
        <td>MUST have exactly one</td>
        <td>SHOULD have exactly one</td>
        <td>MUST have exactly one</td>
      </tr>
      <tr>
        <td>&lt;sign/&gt;</td>
        <td>MUST have at least one</td>
        <td>MUST have exactly one</td>
        <td>OPTIONAL</td>
        <td>MUST have exactly one</td>
      </tr>
      <tr>
        <td>&lt;crypt/&gt;</td>
        <td>OPTIONAL</td>
        <td>MUST have exactly one</td>
        <td>SHOULD have exactly one</td>
        <td>MUST have exactly one</td>
      </tr>
    </table>

    <p>OpenPGP content elements MUST possess exactly one &lt;payload/&gt;
    element. The child elements of &lt;payload/&gt; can be seen as OpenPGP
    secured Stanza extension elements which are encrypted and/or
    signed. After the &lt;openpgp/&gt; element and the including &lt;signcrypt/&gt;,
    &lt;sign/&gt; or &lt;crypt/&gt; element was verified, they are processed
    according to the specification of the relevant OpenPGP for XMPP
    profile (see for example <span class="ref"><link url="https://xmpp.org/extensions/xep-0374.html">OpenPGP for XMPP Instant Messaging (XEP-0374)</link></span> <note>XEP-0374: OpenPGP for XMPP Instant Messaging &lt;<link url="https://xmpp.org/extensions/xep-0374.html">https://xmpp.org/extensions/xep-0374.html</link>&gt;.</note>).</p>

  </section2>

  <section2 topic="Verification of &lt;openpgp/&gt; Content" anchor="openpgp-verification">

    <p>Recipients MUST verify that the signature is valid, that the
    signature's key corresponds to the sender's key, and that the
    sender's key has a User ID containing the sender's XMPP
    address in the form "xmpp:juliet@example.org" (for details see
    <link url="#openpgp-user-ids">"OpenPGP User IDs"</link>). Thus,
    the recipient may
    need to retrieve the key from the Personal Eventing Protocol node
    as described above. At least one of the XMPP addresses found in
    the 'to' elements contained in OpenPGP content element MUST
    correspond to the outer 'to' of the XMPP &lt;message/&gt;. Furthermore,
    recipients are RECOMMENDED to verify the 'time' element for
    plausibility or to display it to a user for verification.</p>

  </section2>

</section1>

<section1 topic="Announcing and Discovering Public Keys via PEP" anchor="announcing-discover-pubkey">

  <p>Parties interested in exchanging encrypted data between each
  other via OpenPGP need to know the public key(s) of the
  recipients. The following section specifies a mechanism to announce
  and discover public keys.</p>

  <p>Two PEP node types are invovled: A "medatata node" is used to store meta information about
  OpenPGP keys used by an entity while the actual public keys are stored in "data nodes".</p>

  <section2 topic="The OpenPGP Public-Key Data Node" anchor="announcing-pubkey">

    <p>The public key data, as specified in <span class="ref"><link url="http://tools.ietf.org/html/rfc4880">RFC 4880</link></span> <note>RFC 4880: OpenPGP Message Format &lt;<link url="http://tools.ietf.org/html/rfc4880">http://tools.ietf.org/html/rfc4880</link>&gt;.</note>, is stored in a PEP data
    node. Note that OpenPGP's ASCII Armor is not used, instead the XMPP client MUST encode the
    public key using Base64. The id of the node MUST be "urn:xmpp:openpgp:0:public-keys:" followed
    by the fingerprint string of the OpenPGP public-key contained in the data node.</p>

    <p>In absence of a use-case specific access model, it is RECOMMENDED to use the 'open' access
    model for the public key data node in order to give entities without presence subscription
    read access to the public key.</p>

    <p>The access model can be changed efficiently by using publish-options.</p>

    <p>The <em>OpenPGP v4 fingerprint string</em> is obtained as follows: First the raw bytes of the
    fingerprint are computed as specified in <cite>RFC 4880 § 12.2.</cite>. Then the bytes are
    encoded as a hexadecimal string using upper case characters<note>This matches the representation
    used by GnuPG minus the SPACE separation.</note>.</p>

    <p> The publishing entity SHOULD set the PubSub item ID to the time the item is published encoded
    as DateTime format specified in <span class="ref"><link url="https://xmpp.org/extensions/xep-0082.html">XMPP Date and Time Profiles (XEP-0082)</link></span> <note>XEP-0082: XMPP Date and Time Profiles &lt;<link url="https://xmpp.org/extensions/xep-0082.html">https://xmpp.org/extensions/xep-0082.html</link>&gt;.</note>.</p>

    <p>The data node MUST contain an &lt;pubkey/&gt; element qualified by the 'urn:xmpp:openpgp:0'
    namespace. The element MUST include a &lt;data/&gt; element which contains the data of the key
    Base64 encoded.</p>

    <example caption="Saving the public key in the data node."><![CDATA[
<iq type='set' from='juliet@example.org/balcony' id='publish1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='urn:xmpp:openpgp:0:public-keys:1357B01865B2503C18453D208CAC2A9678548E35'>
      <item id='2020-01-21T10:46:21Z'>
        <pubkey xmlns='urn:xmpp:openpgp:0'>
           <data>
             BASE64_OPENPGP_PUBLIC_KEY
           </data>
        </pubkey>
      </item>
    </publish>
    <publish-options>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#publish-options</value>
        </field>
        <field var='pubsub#access_model'>
          <value>open</value>
        </field>
      </x>
    </publish-options>
  </pubsub>
</iq>]]></example>

  </section2>

  <section2 topic="The OpenPGP Public Key Metadata Node" anchor="announcing-pubkey-list">

    <p>To update the public keys used by an entity, the metadata node is updated. Before adding a
    OpenPGP key fingerprint to the metadata node, the publisher MUST ensure that the public key is available
    at the corresponding data node.</p>

    <p>Just like with the public key data node, in absence of a use-case specific access model,
    it is RECOMMENDED to set the access model of the metadata node to 'open', such that entities
    without mutual presence subscription are still able to access the node items.</p>

    <p> The ID of the metadata node is 'urn:xmpp:openpgp:0:public-keys'. It contains a
    &lt;public-keys-list/&gt; element qualified by the 'urn:xmpp:openpgp:0' namespace containing one
    or more &lt;pubkey-metadata/&gt; elements. Every pubkey-metadata element MUST have a
    'v4-fingerprint' attribute, containing the OpenPGP v4 fingerprint string, and a 'date'
    attribute, containing the time the key was published or updated in DateTime format of
    <span class="ref"><link url="https://xmpp.org/extensions/xep-0082.html">XMPP Date and Time Profiles (XEP-0082)</link></span> <note>XEP-0082: XMPP Date and Time Profiles &lt;<link url="https://xmpp.org/extensions/xep-0082.html">https://xmpp.org/extensions/xep-0082.html</link>&gt;.</note>. An OpenPGP V4 fingerprint MUST NOT occur in the list more than once.</p>

    <example caption="Publishing a public key to the metadata node."><![CDATA[
<iq type='set' from='juliet@example.org/balcony' id='publish1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <publish node='urn:xmpp:openpgp:0:public-keys'>
      <item>
        <public-keys-list xmlns='urn:xmpp:openpgp:0'>
          <pubkey-metadata
            v4-fingerprint='1357B01865B2503C18453D208CAC2A9678548E35'
            date='2018-03-01T15:26:12Z'
            />
          <pubkey-metadata
            v4-fingerprint='67819B343B2AB70DED9320872C6464AF2A8E4C02'
            date='1953-05-16T12:00:00Z'
            />
        </public-keys-list>
      </item>
    </publish>
    <publish-options>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#publish-options</value>
        </field>
        <field var='pubsub#access_model'>
          <value>open</value>
        </field>
      </x>
    </publish-options>
  </pubsub>
</iq>]]></example>

  </section2>

  <section2 topic="Discovering Public Keys of a User" anchor="discover-pubkey-list">

    <p>In order to discover the OpenPGP public keys of a remote entity, the interested entity first
    queries the remote entity's metadata note to learn about the currently annouced OpenPGP
    keys.</p>

    <example caption="Requesting the metadata node of a user."><![CDATA[
<iq from='romeo@example.org/orchard'
    to='juliet@example.org'
    type='get'
    id='getmeta'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='urn:xmpp:openpgp:0:public-keys'/>
  </pubsub>
</iq>]]></example>

    <example caption="Personal Eventing Protocol result containing the metadata node of the user."><![CDATA[
<iq from='juliet@example.org'
    to='romeo@example.org/orchard'
    type='result'
    id='getmeta'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='urn:xmpp:openpgp:0:public-keys'>
      <item>
        <public-keys-list xmlns='urn:xmpp:openpgp:0'>
          <pubkey-metadata
            v4-fingerprint='1357B01865B2503C18453D208CAC2A9678548E35'
            date='2018-03-01T15:26:12Z'
            />
          <pubkey-metadata
            v4-fingerprint='67819B343B2AB70DED9320872C6464AF2A8E4C02'
            date='1953-05-16T12:00:00Z'
            />
        </public-keys-list>
      </item>
    </items>
  </pubsub>
</iq>]]></example>

  </section2>

  <section2 topic="Requesting Public Keys" anchor="discover-pubkey">

    <p>OpenPGP key(s) can be retrieved by querying the data node for a specific
    fingerprint.</p>

    <example caption="Requesting an OpenPGP public key from an XMPP entity."><![CDATA[
<iq from='romeo@example.org/orchard'
    to='juliet@example.org'
    type='get'
    id='getpub'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='urn:xmpp:openpgp:0:public-keys:1357B01865B2503C18453D208CAC2A9678548E35'
           max_items='1'/>
  </pubsub>
</iq>]]></example>

    <example caption="Personal Eventing Protocol result containing the requested public key."><![CDATA[
<iq from='juliet@example.org'
    to='romeo@example.org/orchard'
    type='result'
    id='getpub'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='urn:xmpp:openpgp:0:public-keys:1357B01865B2503C18453D208CAC2A9678548E35'>
      <item id='2020-01-21T10:46:21Z'>
        <pubkey xmlns='urn:xmpp:openpgp:0'>
          <data>
            BASE64_OPENPGP_PUBLIC_KEY
          </data>
        </pubkey>
      </item>
    </items>
  </pubsub>
</iq>]]></example>

    <p>Note that the result may contain multiple pubkey elements. Only
    the public keys found in the most recent item MUST be used. Requesters
    may want to limit the results to the most recent item using the
    'max_items' attribute set to '1'. Clients could alternatively use
    <span class="ref"><link url="https://xmpp.org/extensions/xep-0059.html">Result Set Management (XEP-0059)</link></span> <note>XEP-0059: Result Set Management &lt;<link url="https://xmpp.org/extensions/xep-0059.html">https://xmpp.org/extensions/xep-0059.html</link>&gt;.</note> as an alternative to 'max_items' but accoding to
    <span class="ref"><link url="https://xmpp.org/extensions/xep-0060.html">Publish-Subscribe (XEP-0060)</link></span> <note>XEP-0060: Publish-Subscribe &lt;<link url="https://xmpp.org/extensions/xep-0060.html">https://xmpp.org/extensions/xep-0060.html</link>&gt;.</note> RSM is not (yet) mandatory for PubSub
    services.</p>

    <p>Some XMPP services may not provide the Personal Eventing
    Protocol feature required to provide the mechanism described
    here. If so, they will return an &lt;iq/&gt; error of type
    service-unavailable.</p>

  </section2>

  <section2 topic="Receiving notifications about key changes" anchor="pubsub-notifications">

    <p>Entities creating PEP nodes defined herein SHOULD configure the nodes as notification-only
    nodes by setting 'pubsub#deliver_payloads" configuration field to 'false'.</p>

    <p>Entities which are subscribed to the metadata node or advertise the
    "urn:xmpp:openpgp:0:public-keys+notify" feature via <span class="ref"><link url="https://xmpp.org/extensions/xep-0030.html">Service Discovery (XEP-0030)</link></span> <note>XEP-0030: Service Discovery &lt;<link url="https://xmpp.org/extensions/xep-0030.html">https://xmpp.org/extensions/xep-0030.html</link>&gt;.</note> (see <span class="ref"><link url="https://xmpp.org/extensions/xep-0060.html">Publish-Subscribe (XEP-0060)</link></span> <note>XEP-0060: Publish-Subscribe &lt;<link url="https://xmpp.org/extensions/xep-0060.html">https://xmpp.org/extensions/xep-0060.html</link>&gt;.</note> <link url="https://xmpp.org/extensions/xep-0060.html#filtered-notifications">§ 9.2</link>) receive a
    notification upon a node update. Entities subscribed to PEP nodes defined herein MUST be prepared
    that PubSub notifications may be without the payload and only contain the published item's ID.</p>

  </section2>

</section1>

<section1 topic="Synchronizing the Secret Key with a Private PEP Node" anchor="synchro-pep">

  <!--
  TODO: Also split in metadata and data node? Probably not, because it could cause stale secret
  keys on the service (since it is not possible to list all PEP nodes starting with
  e.g. urn:xmpp:openpgp:0:secret-keys and delete old ones. We could split later anyways.
  -->

    <p>A private PEP node is used to allow XMPP clients to synchronize
    the user's secret OpenPGP key. Where private PEP node is defined: A
    PEP node in whitelist mode where only the bare JID of the key
    owner is whitelisted as described in <span class="ref"><link url="https://xmpp.org/extensions/xep-0223.html">Best Practices for Persistent Storage of Private Data via Publish-Subscribe (XEP-0223)</link></span> <note>XEP-0223: Best Practices for Persistent Storage of Private Data via Publish-Subscribe &lt;<link url="https://xmpp.org/extensions/xep-0223.html">https://xmpp.org/extensions/xep-0223.html</link>&gt;.</note>. The secret key is
    additionally encrypted.</p>

    <section2 topic="Required PEP features" anchor="synchro-pep-requirements">

      <p>The used PEP server MUST support PEP and the whitelist access
      model. It SHOULD also support persistent items.</p>

        <section3 topic="Discovering support" anchor="synchro-pep-discover-support">

          <example caption="Account owner queries server regarding protocol support"><![CDATA[
<iq from='juliet@capulet.lit/balcony'
    to='juliet@capulet.lit'
    id='disco1'
    type='get'>
  <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>
]]></example>

        <p>The service discovery result must contain a PEP identity
        '&lt;identity category='pubsub' type='pep'/&gt;, and the
        'http://jabber.org/protocol/pubsub#access-whitelist'
        feature. Ideally it also contains the
        'http://jabber.org/protocol/pubsub#persistent-items'
        feature</p>

        <example caption="Server communicates protocol support"><![CDATA[
<iq from='juliet@capulet.lit'
    to='juliet@capulet.lit/balcony'
    id='disco1'
    type='result'>
  <query xmlns='http://jabber.org/protocol/disco#info'>
    <identity category='account' type='registered'/>
    <identity category='pubsub' type='pep'/>
    <feature var='http://jabber.org/protocol/pubsub#access-presence'/>
    <feature var='http://jabber.org/protocol/pubsub#auto-create'/>
    <feature var='http://jabber.org/protocol/pubsub#auto-subscribe'/>
    <feature var='http://jabber.org/protocol/pubsub#config-node'/>
    <feature var='http://jabber.org/protocol/pubsub#create-and-configure'/>
    <feature var='http://jabber.org/protocol/pubsub#create-nodes'/>
    <feature var='http://jabber.org/protocol/pubsub#filtered-notifications'/>
    <feature var='http://jabber.org/protocol/pubsub#persistent-items'/>
    <feature var='http://jabber.org/protocol/pubsub#publish'/>
    <feature var='http://jabber.org/protocol/pubsub#retrieve-items'/>
    <feature var='http://jabber.org/protocol/pubsub#subscribe'/>
    ...
  </query>
</iq>]]></example>

       </section3>

    </section2>

    <section2 topic="Requesting Information About the Secret Key PEP Node" anchor="req-info-secret-pep-node">

      <p>In order to synchronize the secret key over a private PEP node,
      clients first need to discover and verify the node for the correct
      settings.</p>

      <section3 topic="Client Sends Request" anchor="client-sends-secret-request">

  <example caption="Requesting the user's secret key."><![CDATA[
<iq from='romeo@example.org/orchard'
    to='juliet@example.org'
    type='get'
    id='getsecret'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='urn:xmpp:openpgp:0:secret-key'
           max_items='1'/>
  </pubsub>
</iq>]]></example>

      </section3>
      <section3 topic="PEP Service Success Response" anchor="client-receives-secret-response">

  <example caption="Personal Eventing Protocol result containing the requested secret key."><![CDATA[
<iq from='juliet@example.org'
    to='romeo@example.org/orchard'
    type='result'
    id='getsecret'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='urn:xmpp:openpgp:0:secret-key'>
      <item>
        <secretkey xmlns='urn:xmpp:openpgp:0'>
            BASE64_OPENPGP_ENCRYPTED_SECRET_KEY
        </secretkey>
      </item>
    </items>
  </pubsub>
</iq>]]></example>

      </section3>
      <section3 topic="PEP Node Does Not Exist Response" anchor="error-pep-node-inexistent">

        <p>If the node does not exist the service will return an &lt;iq/&gt;
        error indicating the item-not-found error condition. The
        client MUST then create it with an whitelist access model.</p>

        <example caption="Node does not exist"><![CDATA[
<iq from='juliet@example.org'
    to='romeo@example.org/orchard'
    type='error'
    id='getsecret'>
  <error type='cancel'>
    <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>]]></example>

      </section3>

      <section3 topic="PEP Not Supported" anchor="pep-not-supported">

        <p>The service will return a service-unavailable error &lt;iq/&gt; if
        it does not support PEP.</p>

        <example caption="Node does not exist"><![CDATA[
<iq from='juliet@example.org'
    to='romeo@example.org/orchard'
    type='error'
    id='getsecret'>
  <error type='cancel'>
    <service-unavailable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
  </error>
</iq>]]></example>

      </section3>

    </section2>
    <section2 topic="Creating the Secret Key PEP Node" anchor="create-secret-node">

      <example caption="Client creates secret key PEP node"><![CDATA[
<iq type='set'
    from='juliet@example.org/balcony'
    id='create-node'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <create node='urn:xmpp:openpgp:0:secret-key'/>
    <configure>
      <x xmlns='jabber:x:data' type='submit'>
        <field var='FORM_TYPE' type='hidden'>
          <value>http://jabber.org/protocol/pubsub#node_config</value>
        </field>
        <field var='pubsub#access_model'>
          <value>whitelist</value>
        </field>
        <field var='pubsub#send_last_published_item'>
          <value>on_sub</value>
        </field>
      </x>
    </configure>
  </pubsub>
</iq>]]></example>
      <example caption="Service informs requesting entity of success"><![CDATA[
<iq type='result'
    to='juliet@example.org/balcony'
    id='create-node'/>]]></example>

      <p>The node is now created and the only affiliated entity is the
      bare JID of the user, who created the node, with an affiliation as
      'owner'.</p>

    </section2>

    <section2 topic="Encrypting the Secret Key Backup" anchor="backup-encryption">

      <p>In order to set a new secret key, clients store the encrypted
      secret key as Base64 encoded raw OpenPGP message within an
      &lt;secretkey/&gt; element qualified by the 'urn:xmpp:openpgp:0'
      namespace. These secret key backups are created as follows:</p>

      <ol>
        <li>All secret keys that should be included in the backup MUST
        be concatenated in their transferable key format (<cite>RFC
        4880</cite> <link url="http://tools.ietf.org/html/rfc4880#section-11.2">§
        11.1</link>). The octet indicating string-to-key usage conventions
        MUST be set to zero in the corresponding Secret-Key Packet(s)
        (<span class="ref"><link url="http://tools.ietf.org/html/rfc4880">RFC 4880</link></span> <note>RFC 4880: OpenPGP Message Format &lt;<link url="http://tools.ietf.org/html/rfc4880">http://tools.ietf.org/html/rfc4880</link>&gt;.</note> <link url="https://tools.ietf.org/html/rfc4880#section-5.5.3">§ 5.5.3</link>).
        The secret key material will be encrypted in step 4 using a
        Symmetric-Key Encrypted Session Key Packet.
        </li>
        <li>A backup code is generated from secure random: The backup
        code consists of 24 upper case characters from the Latin
        alphabet and numbers without 'O' ("LATIN CAPITAL LETTER O")
        and '0' ("DIGIT ZERO") (alphabet:
        <tt>123456789ABCDEFGHIJKLMNPQRSTUVWXYZ</tt>) grouped into
        4-character chunks, e.g.,
        <tt>TWNK-KD5Y-MT3T-E1GS-DRDB-KVTW</tt>. The characters MUST be
        generated from cryptographically secure random. For example
        <tt><link url="https://lwn.net/Articles/606141/">getrandom(2)</link></tt>,
        <tt><link url="https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html">SecureRandom</link></tt>
        or <tt>/dev/urandom</tt>. More information about the
        randomness requirements for security can be found in <span class="ref"><link url="http://tools.ietf.org/html/rfc4086">RFC 4086</link></span> <note>RFC 4086: Randomness Requirements for Security &lt;<link url="http://tools.ietf.org/html/rfc4086">http://tools.ietf.org/html/rfc4086</link>&gt;.</note>
        </li>
        <li>The whole backup code including the dashes is directly
        used as a string to encrypt the concatenated transferable keys
        as an OpenPGP message. More precisely: It is used as the
        symmetric-key for a Symmetric-Key Encrypted Session Key Packet
        according to <span class="ref"><link url="http://tools.ietf.org/html/rfc4880">RFC 4880</link></span> <note>RFC 4880: OpenPGP Message Format &lt;<link url="http://tools.ietf.org/html/rfc4880">http://tools.ietf.org/html/rfc4880</link>&gt;.</note> <link url="http://tools.ietf.org/html/rfc4880#section-5.3">§
        5.3</link>; the symmetric-key is thus 29 characters long
        including the dashes.  The encryption algorithm MUST be one of
        the standardized OpenPGP symmetric algorithms, e.g, AES-128.
        </li>
      </ol>

    </section2>

</section1>

<section1 topic="Business Rules" anchor="rules">

  <section2 topic="OpenPGP Packet Format Version Restriction" anchor="openpgp-packet-format-version">

    <p>Implementations of this XEP MUST generate and accept only
    version 4 (or higher) OpenPGP packets. Lower version OpenPGP
    packets are insecure in many aspects (see for example <cite>RFC
    4880</cite> <link url="http://tools.ietf.org/html/rfc4880#section-5.5.2">§
    5.5.2</link>.).</p>

  </section2>

  <section2 topic="PubSub Node Configuration" anchor="pubsub-node-configuration">

    <p>The Public-Key <em>metadata</em> node and the Secret-Key node SHOULD be configured to either
    never send the latest item, or to send the latest item only when a new entity subscribed. Thus
    the nodes 'send_last_published_item' configuration option SHOULD be set to either 'never' or
    'on_sub' (see <span class="ref"><link url="https://xmpp.org/extensions/xep-0060.html">Publish-Subscribe (XEP-0060)</link></span> <note>XEP-0060: Publish-Subscribe &lt;<link url="https://xmpp.org/extensions/xep-0060.html">https://xmpp.org/extensions/xep-0060.html</link>&gt;.</note> <link url="https://xmpp.org/extensions/xep-0060.html#registrar-formtypes-config">§ 16.4.4</link>).</p>

  </section2>

  <section2 topic="Key Enforcement" anchor="key-enforcement">

    <p>Whenever an entity becomes aware that the metadata node has changed (e.g., by receiving a PEP
    update from their own account), it SHOULD check that the list contains the key they use. If the
    key has been removed, the entity SHOULD reannounce it.</p>

  </section2>

</section1>

<section1 topic="Implementors Advice" anchor="implementors-advice">

  <section2 topic="Design Principles and Techniques" anchor="design-and-techniques">

    <p>OpenPGP implementations have a sad history of being not very
    user-friendly which results in users either not using OpenPGP or in
    users wrongly using OpenPGP. Implementors of this XEP, and
    additional future XEPs based on this XEP, therefore should read
    <span class="ref"><link url="http://g10code.com/steed.html">STEED</link></span><note>Koch,
    Werner, and Marcus Brinkman "STEED — Usable End-to-End
    Encryption", White Paper, g10 GmbH, 2011-10-17. &lt;<link url="http://g10code.com/steed.html">http://g10code.com/steed.html</link>&gt;</note>
    and <span class="ref"><link url="https://www.cs.berkeley.edu/~tygar/papers/Why_Johnny_Cant_Encrypt/OReilly.pdf">"Why
    Johnny can't encrypt"</link></span><note>Whitten, Alma, and
    J. Doug Tygar. "Why Johnny Can't Encrypt: A Usability Evaluation
    of PGP 5.0." Usenix Security. Vol. 1999. 1999. &lt;<link url="https://www.cs.berkeley.edu/~tygar/papers/Why_Johnny_Cant_Encrypt/OReilly.pdf">https://www.cs.berkeley.edu/~tygar/papers/Why_Johnny_Cant_Encrypt/OReilly.pdf</link>&gt;</note>. Implementors
    of this XEP are encouraged to provide the concepts described in
    STEED:</p>

    <ul>
      <li>Automatic key generation</li>
      <li>Automatic key distribution</li>
      <li>Opportunistic encryption</li>
      <li>Trust upon first contact</li>
    </ul>

    <p>Furthermore implementors should design the user interface for
    effective security by following the design principles and
    techniques for security mentioned in "Why Johnny Can't
    Encrypt".</p>

  </section2>

  <section2 topic="Stanza Size" anchor="stanza-size">

    <p>Implementors should be aware that the size OpenPGP public and
    secret keys is somewhere in the range of tens of
    kilobytes. Applying Base64 encoding on keys, as it is described
    herein, further increases the size. The formula to determine the
    Base64 encoded size is: ceil(bytes / 3) * 4. Thus the lower bound
    for the maximum stanza size of 10000 bytes, as specified in <cite>RFC
    6120</cite> § 13.12. 4., is usually exceeded. However all XMPP server
    implementations, the authors are aware of, follow the
    recommendation of the RFC and do not blindly set the maximum
    stanza size to such a low value, but use a much higher
    threshold. Therefore, this should hardly be an issue for
    implementations. Nevertheless, it is advised to keep the size of
    OpenPGP keys small by removing all signatures except the most
    recent self-signature on each User ID before exporting the key
    (cf. GnuPG's <tt>--export-options export-minimal</tt>).
    In addition, implementors are advised to handle
    &lt;policy-violation/&gt; error responses when trying to
    transmit Base64 encoded keys.</p>

  </section2>

  <section2 topic="XMPP Address Normalization" anchor="xmpp-address-normalization">

    <p>The format of XMPP addresses, sometimes called JIDs, is well
    defined. Thus they need to be normalized, as defined in
    <span class="ref"><link url="http://tools.ietf.org/html/rfc7622">RFC 7622</link></span> <note>RFC 7622: Extensible Messaging and Presence Protocol (XMPP): Address Format &lt;<link url="http://tools.ietf.org/html/rfc7622">http://tools.ietf.org/html/rfc7622</link>&gt;.</note>. When implementations are required to compare XMPP
    addresses for equality, as it is the case in <link url="#openpgp-verification">"Verification of &lt;openpgp/&gt;
    Content"</link>, then they also have to compare the normalized
    versions of the addresses.</p>

  </section2>

</section1>

<section1 topic="Rationale" anchor="rationale">

  <section2 topic="Key Handling" anchor="key-handling">

    <p>This specification intentionally does not specify if the used
    OpenPGP key should be a primary key or a subkey. It is even
    possible to announce multiple public keys in the Personal Eventing
    Protocol node. Implementations MUST be prepared to find multiple
    public keys. The authors however believe that for ease of use only
    one OpenPGP key specially crafted for the XMPP use case should be
    created, announced and used.</p>

  </section2>

  <section2 topic="OpenPGP Element and Content Element Design" anchor="openpgp-element-design">

    <p>The &lt;openpgp/&gt; and OpenPGP content elements are container
    elements for arbitrary signed and encrypted data and can thus act
    as building blocks for encrypted data included in Message, IQ and
    Presence stanzas. For example, future specifications may use them
    to implement encrypted versions of <span class="ref"><link url="https://xmpp.org/extensions/xep-0047.html">In-Band Bytestreams (XEP-0047)</link></span> <note>XEP-0047: In-Band Bytestreams &lt;<link url="https://xmpp.org/extensions/xep-0047.html">https://xmpp.org/extensions/xep-0047.html</link>&gt;.</note> or <span class="ref"><link url="https://xmpp.org/extensions/xep-0261.html">Jingle In-Band Bytestreams Transport Method (XEP-0261)</link></span> <note>XEP-0261: Jingle In-Band Bytestreams Transport Method &lt;<link url="https://xmpp.org/extensions/xep-0261.html">https://xmpp.org/extensions/xep-0261.html</link>&gt;.</note>.</p>

    <p>Note that signed OpenPGP messages already contain a timestamp
    as per the OpenPGP specification. OpenPGP content elements
    nevertheless require the 'time' element because not every OpenPGP
    API may provide access to the embedded OpenPGP timestamp.</p>

    <p>The 'rpad' element of the OpenPGP content elements exists to
    prevent length-based side channel attacks.</p>

  </section2>

  <section2 topic="Addressing the Issues and Problems of XEP-0027" anchor="solving-xep0027-issues">

    <p>This specification addresses all relevant issues of <span class="ref"><link url="https://xmpp.org/extensions/xep-0027.html">Current Jabber OpenPGP Usage (XEP-0027)</link></span> <note>XEP-0027: Current Jabber OpenPGP Usage &lt;<link url="https://xmpp.org/extensions/xep-0027.html">https://xmpp.org/extensions/xep-0027.html</link>&gt;.</note>
    (<link url="https://xmpp.org/extensions/xep-0027.html#security">§
    4</link>, <link url="https://xmpp.org/extensions/xep-0027.html#issues">§
    5</link>). It mitigates replay attacks by including the
    recipient's address and a timestamp in the OpenPGP content
    element<note>Full Replay attack prevention would require a
    counter based approach.</note>. It allows for both, signing and
    encrypting of the element. The scope of the specification was
    deliberately limited to OpenPGP.</p>

    <p>Features like signed presences, which is provided by <span class="ref"><link url="https://xmpp.org/extensions/xep-0027.html">Current Jabber OpenPGP Usage (XEP-0027)</link></span> <note>XEP-0027: Current Jabber OpenPGP Usage &lt;<link url="https://xmpp.org/extensions/xep-0027.html">https://xmpp.org/extensions/xep-0027.html</link>&gt;.</note>,
    may be added later on as add-on XEP to this.</p>

  </section2>

  <section2 topic="Not using OpenPGP ASCII Armor" anchor="openpgp-ascii-armor">

    <p>We decided against OpenPGP ASCII Armor (which contains an
    additional checksum) and in favor for Base64, because
    encoding should be part of the network application rather than the
    crypto layer. Also XMPP, needs no additional error correction of payload.
    In "MIME Security with OpenPGP" (<span class="ref"><link url="http://tools.ietf.org/html/rfc3156">RFC 3156</link></span> <note>RFC 3156: MIME Security with OpenPGP &lt;<link url="http://tools.ietf.org/html/rfc3156">http://tools.ietf.org/html/rfc3156</link>&gt;.</note>), ASCII Armor
    has only been chosen to be backwards compatible with legacy applications
    supporting non-MIME OpenPGP emails only.</p>

  </section2>

  <section2 topic="OpenPGP User IDs" anchor="openpgp-user-ids">

    <p>OpenPGP User IDs normally consist of a name - email address pair, e.g.,
      "Juliet &lt;juliet@example.org&gt;" (<span class="ref"><link url="http://tools.ietf.org/html/rfc4880">RFC 4880</link></span> <note>RFC 4880: OpenPGP Message Format &lt;<link url="http://tools.ietf.org/html/rfc4880">http://tools.ietf.org/html/rfc4880</link>&gt;.</note> <link url="http://tools.ietf.org/html/rfc4880#section-5.11">§ 5.11</link>).
    For this XEP, we require User IDs of the format "xmpp:juliet@example.org".
    First, it is required to have at least one User ID indicating the use
    of this OpenPGP key. When doing certification of keys (key signing),
    the partner must know what User ID she actually certifies.
    Second, this format uses the standardized URI from <span class="ref"><link url="https://xmpp.org/extensions/xep-0147.html">XMPP URI Query Components (XEP-0147)</link></span> <note>XEP-0147: XMPP URI Query Components &lt;<link url="https://xmpp.org/extensions/xep-0147.html">https://xmpp.org/extensions/xep-0147.html</link>&gt;.</note> to indicate
    that this User ID corresponds to a key that is used for XMPP.
    Third, having the Real Name inside provides no additional security
    or guideline if this key should be certified. The XMPP address
    is the only trust anchor here.</p>

    </section2>

</section1>

<section1 topic="Security Considerations" anchor="security">

  <p>The scope of this XEP is intentionally limited, so that the
  specification just defines way for XMPP entities to discover,
  announce and synchronize OpenPGP keys, and how to exchange signed
  and encrypted data between two or more parties. Everything else is
  outside its scope. For example, how 'secure' the key material is
  protected on the endpoints is up to the implementation.</p>

  <p>And while this XEP specifies a mechanism how to discover and
  retrieve a public key, it does not define how the trust relation to
  this key should be established. Even if key discovery and retrieval
  over XMPP provides a stronger coupling between the possessing entity
  (the XMPP address) and the key, as compared to the OpenPGP keyservers,
  how a XMPP server authenticates a remote server is a server policy,
  which does vary from server to server. Implementation MUST provide a
  way for the user to establish and assign trust to a public key. For
  example by using a QR code shown on the recipient's device screen.</p>

  <p>Besides the protocol defined herein, OpenPGP implementations are
  another big attack surface. Needless to say that the security of
  encrypted data exchanged using this protocol depends on the security
  of the used OpenPGP implementation. It is strongly RECOMMENED to use
  existing implementations instead of writing your own. OpenPGP
  implementations have suffered from various vulnerabilities in the past
  which opened up DoS attack vectors. For example <link url="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-4402">CVE-2013-4402</link>
  and <link url="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-4617">CVE-2014-4717</link>.</p>

</section1>

<section1 topic="IANA Considerations" anchor="iana">

  <p>This document requires no interaction with the <span class="ref"><link url="http://www.iana.org/">Internet Assigned Numbers Authority (IANA)</link></span> <note>The Internet Assigned Numbers Authority (IANA) is the central coordinator for the assignment of unique parameter values for Internet protocols, such as port numbers and URI schemes. For further information, see &lt;<link url="http://www.iana.org/">http://www.iana.org/</link>&gt;.</note>.</p>

</section1>

<section1 topic="XMPP Registrar Considerations" anchor="registrar">

  <section2 topic="Protocol Namespaces" anchor="registrar-ns">

    <p>The <span class="ref"><link url="https://xmpp.org/registrar/">XMPP Registrar</link></span> <note>The XMPP Registrar maintains a list of reserved protocol namespaces as well as registries of parameters used in the context of XMPP extension protocols approved by the XMPP Standards Foundation. For further information, see &lt;<link url="https://xmpp.org/registrar/">https://xmpp.org/registrar/</link>&gt;.</note> includes 'urn:xmpp:openpgp:0' in its registry of protocol namespaces (see &lt;<link url="https://xmpp.org/registrar/namespaces.html">https://xmpp.org/registrar/namespaces.html</link>&gt;).</p>

  </section2>

</section1>

<section1 topic="XML Schema" anchor="schema">

  <p>TODO: Add after the XEP leaves the 'experimental' state.</p>

</section1>

<section1 topic="Acknowledgements" anchor="acknowledgements">

  <p>Thanks to Emmanuel Gil Peyrot, Sergei Golovan, Marc Laporte, Georg
  Lukas, Adithya Abraham Philip, Brian Cully, fiaxh, Paul Schaub,
  Philipp Hörist and Stefan Kropp for their feedback.</p>

  <p>The first draft of this specification was worked out and written
  on the wall of the 'Kymera' room in one of Google's buildings by the
  authors, consisting of members of the XMPP Standards Foundation and
  the OpenKeychain project, at the GSOC Mentors Summit 2015. The
  authors would like to thank Google for making it possible by
  bringing the right people together.</p>

</section1>
</xep>
<!-- Local Variables: -->
<!-- fill-column: 100 -->
<!-- indent-tabs-mode: nil -->
<!-- End: -->
