It builds on the X3DH and Double Ratchet specifications, with some adaptations to operate in a decentralized environment.
Motivation # Nodes on a network may want to communicate with each other in a secure manner, without other nodes network being able to read their messages.">
It builds on the X3DH and Double Ratchet specifications, with some adaptations to operate in a decentralized environment.
Motivation # Nodes on a network may want to communicate with each other in a secure manner, without other nodes network being able to read their messages." />
Oskar Thorén <ahref="mailto:oskar@status.im">oskar@status.im</a>
,
Dean Eigenmann <ahref="mailto:dean@status.im">dean@status.im</a>
</li>
</ul><h1id="abstract">
Abstract
<aclass="anchor"href="#abstract">#</a>
</h1>
<p>This document describes a method that can be used to provide a secure channel between two peers, and thus provide confidentiality, integrity, authenticity and forward secrecy.
It is transport-agnostic and works over asynchronous networks.</p>
<p>It builds on the <ahref="https://signal.org/docs/specifications/x3dh/">X3DH</a> and <ahref="https://signal.org/docs/specifications/doubleratchet/">Double Ratchet</a> specifications, with some adaptations to operate in a decentralized environment.</p>
<h1id="motivation">
Motivation
<aclass="anchor"href="#motivation">#</a>
</h1>
<p>Nodes on a network may want to communicate with each other in a secure manner, without other nodes network being able to read their messages.</p>
<h1id="specification">
Specification
<aclass="anchor"href="#specification">#</a>
</h1>
<h2id="definitions">
Definitions
<aclass="anchor"href="#definitions">#</a>
</h2>
<ul>
<li>
<p><strong>Perfect Forward Secrecy</strong> is a feature of specific key-agreement protocols which provide assurances that session keys will not be compromised even if the private keys of the participants are compromised.
Specifically, past messages cannot be decrypted by a third-party who manages to get a hold of a private key.</p>
</li>
<li>
<p><strong>Secret channel</strong> describes a communication channel where a Double Ratchet algorithm is in use.</p>
</li>
</ul>
<h2id="design-requirements">
Design Requirements
<aclass="anchor"href="#design-requirements">#</a>
</h2>
<ul>
<li><strong>Confidentiality</strong>: The adversary should not be able to learn what data is being exchanged between two Status clients.</li>
<li><strong>Authenticity</strong>: The adversary should not be able to cause either endpoint to accept data from any third party as though it came from the other endpoint.</li>
<li><strong>Forward Secrecy</strong>: The adversary should not be able to learn what data was exchanged between two clients if, at some later time, the adversary compromises one or both of the endpoints.</li>
<li><strong>Integrity</strong>: The adversary should not be able to cause either endpoint to accept data that has been tampered with.</li>
</ul>
<p>All of these properties are ensured by the use of <ahref="https://signal.org/docs/specifications/doubleratchet/">Signal’s Double Ratchet</a></p>
<h2id="conventions">
Conventions
<aclass="anchor"href="#conventions">#</a>
</h2>
<p>Types used in this specification are defined using the <ahref="https://developers.google.com/protocol-buffers/">Protobuf</a> wire format.</p>
<p>End-to-end encryption (E2EE) takes place between two clients.
The main cryptographic protocol is a Double Ratchet protocol, which is derived from the <ahref="https://otr.cypherpunks.ca/Protocol-v3-4.1.1.html">Off-the-Record protocol</a>, using a different ratchet.
<ahref="/spec/10/">The Waku v2 protocol</a> subsequently encrypts the message payload, using symmetric key encryption.
Furthermore, the concept of prekeys (through the use of <ahref="https://signal.org/docs/specifications/x3dh/">X3DH</a>) is used to allow the protocol to operate in an asynchronous environment.
It is not necessary for two parties to be online at the same time to initiate an encrypted conversation.</p>
<p>More details can be found in the <code>X3DH Prekey bundle creation</code> section of <ahref="https://specs.status.im/spec/2#x3dh-prekey-bundles">2/ACCOUNT</a>.</p>
<p>Prekey bundles MAY be extracted from any peer’s messages, or found via searching for their specific topic, <code>{IK}-contact-code</code>.</p>
<p>The following methods can be used to retrieve prekey bundles from a peer’s messages:</p>
<p>Waku SHOULD be used for retrieving prekey bundles.</p>
<p>Since bundles stored in QR codes or ENS records cannot be updated to delete already used keys, the bundle MAY be rotated every 24 hours, and distributed via Waku.</p>
<h2id="flow">
Flow
<aclass="anchor"href="#flow">#</a>
</h2>
<p>The key exchange can be summarized as follows:</p>
<ol>
<li>
<p>Initial key exchange: Two parties, Alice and Bob, exchange their prekey bundles, and derive a shared secret.</p>
</li>
<li>
<p>Double Ratchet: The two parties use the shared secret to derive a new encryption key for each message they send.</p>
</li>
<li>
<p>Chain key update: The two parties update their chain keys. The chain key is used to derive new encryption keys for future messages.</p>
</li>
<li>
<p>Message key derivation: The two parties derive a new message key from their chain key, and use it to encrypt a message.</p>
<p><ahref="https://signal.org/docs/specifications/x3dh/#sending-the-initial-message">Section 3 of the X3DH protocol</a> describes the initial key exchange flow, with some additional context:</p>
<ul>
<li>The peers’ identity keys <code>IK_A</code> and <code>IK_B</code> correspond to their public keys;</li>
<li>Since it is not possible to guarantee that a prekey will be used only once in a decentralized world, the one-time prekey <code>OPK_B</code> is not used in this scenario;</li>
<li>Nodes SHOULD not send Bundles to a centralized server, but instead provide them in a decentralized way as described in the <ahref="#pre-keys">Pre-keys section</a>.</li>
</ul>
<p>Alice retrieves Bob’s prekey bundle, however it is not specific to Alice. It contains:</p>
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#75715e">// Signed prekey 'SPK_B' for each device, indexed by 'installation-id'
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#75715e">// When the bundle was created locally
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#66d9ef">uint32</span> version <spanstyle="color:#f92672">=</span><spanstyle="color:#ae81ff">2</span>;<spanstyle="color:#960050;background-color:#1e0010">
</span></span></span></code></pre></div><p>The <code>signature</code> is generated by sorting <code>installation-id</code> in lexicographical order, and concatenating the <code>signed-pre-key</code> and <code>version</code>:</p>
<p>Having established the initial shared secret <code>SK</code> through X3DH, it SHOULD be used to seed a Double Ratchet exchange between Alice and Bob.</p>
<p>Refer to the <ahref="https://signal.org/docs/specifications/doubleratchet/">Double Ratchet spec</a> for more details.</p>
<p>The initial message sent by Alice to Bob is sent as a top-level <code>ProtocolMessage</code> (<ahref="https://github.com/status-im/status-go/blob/a904d9325e76f18f54d59efc099b63293d3dcad3/services/shhext/chat/encryption.proto#L65">reference wire format</a>) containing a map of <code>DirectMessageProtocol</code> indexed by <code>installation-id</code> (<ahref="https://github.com/status-im/status-go/blob/1ac9dd974415c3f6dee95145b6644aeadf02f02c/services/shhext/chat/encryption.proto#L56">reference wire format</a>):</p>
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#75715e">// The installation id of the sender
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#75715e">// A sequence of bundles
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#75715e">// One to one message, encrypted, indexed by installation_id
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#75715e">// Public message, not encrypted
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#75715e"></span><spanstyle="color:#75715e">// if a bundle is available, contains payload encrypted with the Double Ratchet algorithm;
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#75715e"></span><spanstyle="color:#75715e">// otherwise, payload encrypted with output key of DH exchange (no Perfect Forward Secrecy).
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#75715e">// Bob's bundle signed prekey
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#75715e"></span><spanstyle="color:#66d9ef">bytes</span> id <spanstyle="color:#f92672">=</span><spanstyle="color:#ae81ff">4</span>;<spanstyle="color:#960050;background-color:#1e0010">
<p><code>DR_header</code>: Double ratchet header (<ahref="https://github.com/status-im/status-go/blob/a904d9325e76f18f54d59efc099b63293d3dcad3/services/shhext/chat/encryption.proto#L31">reference wire format</a>). Used when Bob’s public bundle is available:</p>
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#75715e">// Alice's current ratchet public key (as mentioned in [DR spec section 2.2](https://signal.org/docs/specifications/doubleratchet/#symmetric-key-ratchet))
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#75715e">// number of the message in the sending chain
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#75715e"></span><spanstyle="color:#66d9ef">uint32</span> n <spanstyle="color:#f92672">=</span><spanstyle="color:#ae81ff">2</span>;<spanstyle="color:#960050;background-color:#1e0010">
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#75715e">// length of the previous sending chain
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#960050;background-color:#1e0010"></span><spanstyle="color:#75715e">// Bob's bundle ID
</span></span></span><spanstyle="display:flex;"><span><spanstyle="color:#75715e"></span><spanstyle="color:#66d9ef">bytes</span> id <spanstyle="color:#f92672">=</span><spanstyle="color:#ae81ff">4</span>;<spanstyle="color:#960050;background-color:#1e0010">
<p>The chain key MUST be updated according to the <code>DR_Header</code> received in the <code>EncryptedMessageProtocol</code> message, described in <ahref="#2-double-ratchet">2.Double Ratchet</a>.</p>
<p>The message key MUST be derived from a single ratchet step in the symmetric-key ratchet as described in <ahref="https://signal.org/docs/specifications/doubleratchet/#symmetric-key-ratchet">Symmetric key ratchet</a></p>
<p>The message key MUST be used to encrypt the next message to be sent.</p>
<p>Inherits the security considerations of <ahref="https://signal.org/docs/specifications/x3dh/#security-considerations">X3DH</a> and <ahref="https://signal.org/docs/specifications/doubleratchet/#security-considerations">Double Ratchet</a>.</p>
</li>
<li>
<p>Inherits the security considerations of the <ahref="/spec/10/">Waku v2 protocol</a>.</p>
</li>
<li>
<p>The protocol is designed to be used in a decentralized manner, however, it is possible to use a centralized server to serve prekey bundles. In this case, the server is trusted.</p>