mirror of https://github.com/status-im/specs.git
60 lines
43 KiB
HTML
60 lines
43 KiB
HTML
<!DOCTYPE html> <html lang="en-US"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <title>2/ACCOUNT - Status Specification</title> <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon"> <link rel="stylesheet" href="/assets/css/just-the-docs-default.css"> <script type="text/javascript" src="/assets/js/vendor/lunr.min.js"></script> <script type="text/javascript" src="/assets/js/just-the-docs.js"></script> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- Begin Jekyll SEO tag v2.7.1 --> <title>2/ACCOUNT | Status Specification</title> <meta name="generator" content="Jekyll v4.2.1" /> <meta property="og:title" content="2/ACCOUNT" /> <meta property="og:locale" content="en_US" /> <link rel="canonical" href="https://specs.status.im/spec/2" /> <meta property="og:url" content="https://specs.status.im/spec/2" /> <meta property="og:site_name" content="Status Specification" /> <meta name="twitter:card" content="summary" /> <meta property="twitter:title" content="2/ACCOUNT" /> <script type="application/ld+json"> {"@type":"WebPage","url":"https://specs.status.im/spec/2","headline":"2/ACCOUNT","@context":"https://schema.org"}</script> <!-- End Jekyll SEO tag --> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-link" viewBox="0 0 24 24"> <title>Link</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"> <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path> </svg> </symbol> <symbol id="svg-search" viewBox="0 0 24 24"> <title>Search</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"> <circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line> </svg> </symbol> <symbol id="svg-menu" viewBox="0 0 24 24"> <title>Menu</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu"> <line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line> </svg> </symbol> <symbol id="svg-arrow-right" viewBox="0 0 24 24"> <title>Expand</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"> <polyline points="9 18 15 12 9 6"></polyline> </svg> </symbol> <symbol id="svg-doc" viewBox="0 0 24 24"> <title>Document</title> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file"> <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline> </svg> </symbol> </svg> <div class="side-bar"> <div class="site-header"> <a href="https://specs.status.im/" class="site-title lh-tight"> Status Specification </a> <a href="#" id="menu-button" class="site-button"> <svg viewBox="0 0 24 24" class="icon"><use xlink:href="#svg-menu"></use></svg> </a> </div> <nav role="navigation" aria-label="Main" id="site-nav" class="site-nav"> <ul class="nav-list"><li class="nav-list-item active"><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="https://specs.status.im/spec/" class="nav-list-link">Stable specs</a><ul class="nav-list "><li class="nav-list-item "><a href="https://specs.status.im/spec/1" class="nav-list-link">1/CLIENT</a></li><li class="nav-list-item "><a href="https://specs.status.im/spec/10" class="nav-list-link">10/WAKU-USAGE</a></li><li class="nav-list-item "><a href="https://specs.status.im/spec/11" class="nav-list-link">11/WAKU-MAILSERVER</a></li><li class="nav-list-item "><a href="https://specs.status.im/spec/15" class="nav-list-link">15/NOTIFICATIONS</a></li><li class="nav-list-item active"><a href="https://specs.status.im/spec/2" class="nav-list-link active">2/ACCOUNT</a></li><li class="nav-list-item "><a href="https://specs.status.im/spec/3" class="nav-list-link">3/WHISPER-USAGE</a></li><li class="nav-list-item "><a href="https://specs.status.im/spec/4" class="nav-list-link">4/WHISPER-MAILSERVER</a></li><li class="nav-list-item "><a href="https://specs.status.im/spec/5" class="nav-list-link">5/SECURE-TRANSPORT</a></li><li class="nav-list-item "><a href="https://specs.status.im/spec/6" class="nav-list-link">6/PAYLOADS</a></li><li class="nav-list-item "><a href="https://specs.status.im/spec/8" class="nav-list-link">8/EIPS</a></li><li class="nav-list-item "><a href="https://specs.status.im/spec/9" class="nav-list-link">9/ETHEREUM-USAGE</a></li></ul></li><li class="nav-list-item"><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="https://specs.status.im/draft/" class="nav-list-link">Draft specs</a><ul class="nav-list "><li class="nav-list-item "><a href="https://specs.status.im/draft/12" class="nav-list-link">12/IPFS gateway for Sticker Pack</a></li><li class="nav-list-item "><a href="https://specs.status.im/draft/13" class="nav-list-link">13/3RD-PARTY-USAGE</a></li><li class="nav-list-item "><a href="https://specs.status.im/draft/14" class="nav-list-link">14/Dapp browser API usage</a></li><li class="nav-list-item "><a href="https://specs.status.im/draft/16" class="nav-list-link">16/Keycard Usage for Wallet and Chat Keys</a></li><li class="nav-list-item "><a href="https://specs.status.im/draft/3" class="nav-list-link">3/WHISPER-USAGE</a></li><li class="nav-list-item "><a href="https://specs.status.im/draft/6" class="nav-list-link">6/PAYLOADS</a></li><li class="nav-list-item "><a href="https://specs.status.im/draft/7" class="nav-list-link">7/GROUP-CHAT</a></li></ul></li><li class="nav-list-item"><a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a><a href="https://specs.status.im/raw/" class="nav-list-link">Raw specs</a><ul class="nav-list "><li class="nav-list-item "><a href="https://specs.status.im/raw/16" class="nav-list-link">16/PUSH-NOTIFICATION-SERVER</a></li></ul></li><li class="nav-list-item"><a href="https://specs.status.im/development" class="nav-list-link">DEVELOPMENT</a></li><li class="nav-list-item"><a href="https://specs.status.im/style-guideline" class="nav-list-link">STYLE-GUIDELINE</a></li></ul> </nav> <footer class="site-footer"> This site uses <a href="https://github.com/pmarsceill/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll. </footer> </div> <div class="main" id="top"> <div id="main-header" class="main-header"> <div class="search"> <div class="search-input-wrap"> <input type="text" id="search-input" class="search-input" tabindex="0" placeholder="Search Status Specification" aria-label="Search Status Specification" autocomplete="off"> <label for="search-input" class="search-label"><svg viewBox="0 0 24 24" class="search-icon"><use xlink:href="#svg-search"></use></svg></label> </div> <div id="search-results" class="search-results"></div> </div> </div> <div id="main-content-wrap" class="main-content-wrap"> <nav aria-label="Breadcrumb" class="breadcrumb-nav"> <ol class="breadcrumb-nav-list"> <li class="breadcrumb-nav-list-item"><a href="https://specs.status.im/spec/">Stable specs</a></li> <li class="breadcrumb-nav-list-item"><span>2/ACCOUNT</span></li> </ol> </nav> <div id="main-content" class="main-content" role="main"> <h1 id="2account"> <a href="#2account" class="anchor-heading" aria-labelledby="2account"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> 2/ACCOUNT </h1> <blockquote> <p>Version: 0.4</p> <p>Status: Stable</p> <p>Authors: Corey Petty <a href="mailto:corey@status.im">corey@status.im</a>, Oskar Thorén <a href="mailto:oskar@status.im">oskar@status.im</a>, Samuel Hawksby-Robinson <a href="mailto:samuel@status.im">samuel@status.im</a> (alphabetical order)</p> </blockquote> <h2 id="abstract"> <a href="#abstract" class="anchor-heading" aria-labelledby="abstract"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Abstract </h2> <p>This specification explains what Status account is, and how a node establishes trust.</p> <h2 id="table-of-contents"> <a href="#table-of-contents" class="anchor-heading" aria-labelledby="table-of-contents"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Table of Contents </h2> <ul> <li><a href="#abstract">Abstract</a></li> <li><a href="#table-of-contents">Table of Contents</a></li> <li><a href="#introduction">Introduction</a></li> <li><a href="#initial-key-generation">Initial Key Generation</a> <ul> <li><a href="#publicprivate-keypairs">Public/Private Keypairs</a></li> <li><a href="#x3dh-prekey-bundle-creation">X3DH Prekey bundle creation</a></li> </ul> </li> <li><a href="#account-broadcasting">Account Broadcasting</a> <ul> <li><a href="#x3dh-prekey-bundles">X3DH Prekey bundles</a></li> </ul> </li> <li><a href="#optional-account-additions">Optional Account additions</a> <ul> <li><a href="#ens-username">ENS Username</a></li> </ul> </li> <li><a href="#trust-establishment">Trust establishment</a> <ul> <li><a href="#terms-glossary">Terms Glossary</a></li> <li><a href="#contact-discovery">Contact Discovery</a> <ul> <li><a href="#public-channels">Public channels</a></li> <li><a href="#private-11-messages">Private 1:1 messages</a></li> </ul> </li> <li><a href="#initial-key-exchange">Initial Key Exchange</a> <ul> <li><a href="#bundles">Bundles</a></li> </ul> </li> <li><a href="#contact-verification">Contact Verification</a> <ul> <li><a href="#identicon">Identicon</a></li> <li><a href="#3-word-pseudonym--whisperwaku-key-fingerprint">3 word pseudonym / Whisper/Waku key fingerprint</a></li> <li><a href="#ens-name">ENS name</a></li> </ul> </li> </ul> </li> <li><a href="#public-key-serialization">Public Key Serialization</a> <ul> <li><a href="#basic-serialization-example">Basic Serialization Example</a></li> <li><a href="#public-key-compression-rationale">Public Key “Compression” Rationale</a></li> <li><a href="#key-encoding">Key Encoding</a></li> <li><a href="#public-key-types">Public Key Types</a></li> <li><a href="#deserialization-process-flow">De/Serialization Process Flow</a> <ul> <li><a href="#serialization-example">Serialization Example</a></li> <li><a href="#deserialization-example">Deserialization Example</a></li> </ul> </li> </ul> </li> <li><a href="#security-considerations">Security Considerations</a></li> <li><a href="#changelog">Changelog</a> <ul> <li><a href="#version-03">Version 0.3</a></li> </ul> </li> </ul> <!-- markdown-toc end --> <h2 id="introduction"> <a href="#introduction" class="anchor-heading" aria-labelledby="introduction"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Introduction </h2> <p>The core concept of an account in Status is a set of cryptographic keypairs. Namely, the combination of the following:</p> <ol> <li>a Whisper/Waku chat identity keypair</li> <li>a set of cryptocurrency wallet keypairs</li> </ol> <p>The node verifies or derives everything else associated with the contact from the above items, including:</p> <ul> <li>Ethereum address (future verification, currently the same base keypair)</li> <li>3 word mnemonic name</li> <li>identicon</li> <li>message signatures</li> </ul> <h2 id="initial-key-generation"> <a href="#initial-key-generation" class="anchor-heading" aria-labelledby="initial-key-generation"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Initial Key Generation </h2> <h3 id="publicprivate-keypairs"> <a href="#publicprivate-keypairs" class="anchor-heading" aria-labelledby="publicprivate-keypairs"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Public/Private Keypairs </h3> <ul> <li>An ECDSA (secp256k1 curve) public/private keypair MUST be generated via a <a href="https://github.com/bitcoin/bips/blob/master/bip-0043.mediawiki">BIP43</a> derived path from a <a href="https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki">BIP39</a> mnemonic seed phrase.</li> <li>The default paths are defined as such: <ul> <li>Whisper/Waku Chat Key (<code class="language-plaintext highlighter-rouge">IK</code>): <code class="language-plaintext highlighter-rouge">m/43'/60'/1581'/0'/0</code> (post Multiaccount integration) <ul> <li>following <a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1581.md">EIP1581</a> <!-- WE CURRENTLY DO NOT IMPLEMENT ENCRYPTION KEY, FOR FUTURE - C.P. --> <!-- - DB encryption Key (`DBK`): `m/43'/60'/1581'/1'/0` (post Multiaccount integration) --> <!-- - following [EIP1581](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1581.md) --></li> </ul> </li> <li>Status Wallet paths: <code class="language-plaintext highlighter-rouge">m/44'/60'/0'/0/i</code> starting at <code class="language-plaintext highlighter-rouge">i=0</code> <ul> <li>following <a href="https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki">BIP44</a></li> <li>NOTE: this (<code class="language-plaintext highlighter-rouge">i=0</code>) is also the current (and only) path for Whisper/Waku key before Multiaccount integration</li> </ul> </li> </ul> </li> </ul> <h3 id="x3dh-prekey-bundle-creation"> <a href="#x3dh-prekey-bundle-creation" class="anchor-heading" aria-labelledby="x3dh-prekey-bundle-creation"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> X3DH Prekey bundle creation </h3> <ul> <li>Status follows the X3DH prekey bundle scheme that <a href="https://en.wikipedia.org/wiki/Signal_Messenger#2013%E2%80%932018:_Open_Whisper_Systems">Open Whisper Systems</a> (not to be confused with the Whisper sub-protocol) outlines <a href="https://signal.org/docs/specifications/x3dh/#the-x3dh-protocol">in their documentation</a> with the following exceptions: <ul> <li>Status does not publish one-time keys <code class="language-plaintext highlighter-rouge">OPK</code> or perform DH including them, because there are no central servers in the Status implementation.</li> </ul> </li> <li>A client MUST create X3DH prekey bundles, each defined by the following items: <ul> <li>Identity Key: <code class="language-plaintext highlighter-rouge">IK</code></li> <li>Signed prekey: <code class="language-plaintext highlighter-rouge">SPK</code></li> <li>Prekey signature: <code class="language-plaintext highlighter-rouge">Sig(IK, Encode(SPK))</code></li> <li>Timestamp</li> </ul> </li> <li>These bundles are made available in a variety of ways, as defined in section 2.1.</li> </ul> <h2 id="account-broadcasting"> <a href="#account-broadcasting" class="anchor-heading" aria-labelledby="account-broadcasting"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Account Broadcasting </h2> <ul> <li>A user is responsible for broadcasting certain information publicly so that others may contact them.</li> </ul> <h3 id="x3dh-prekey-bundles"> <a href="#x3dh-prekey-bundles" class="anchor-heading" aria-labelledby="x3dh-prekey-bundles"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> X3DH Prekey bundles </h3> <ul> <li>A client SHOULD regenerate a new X3DH prekey bundle every 24 hours. This MAY be done in a lazy way, such that a client that does not come online past this time period does not regenerate or broadcast bundles.</li> <li>The current bundle SHOULD be broadcast on a Whisper/Waku topic specific to his Identity Key, <code class="language-plaintext highlighter-rouge">{IK}-contact-code</code>, intermittently. This MAY be done every 6 hours.</li> <li>A bundle SHOULD accompany every message sent.</li> <li>TODO: retrieval of long-time offline users bundle via <code class="language-plaintext highlighter-rouge">{IK}-contact-code</code></li> </ul> <h2 id="optional-account-additions"> <a href="#optional-account-additions" class="anchor-heading" aria-labelledby="optional-account-additions"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Optional Account additions </h2> <h3 id="ens-username"> <a href="#ens-username" class="anchor-heading" aria-labelledby="ens-username"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> ENS Username </h3> <ul> <li>A user MAY register a public username on the Ethereum Name System (ENS). This username is a user-chosen subdomain of the <code class="language-plaintext highlighter-rouge">stateofus.eth</code> ENS registration that maps to their Whisper/Waku identity key (<code class="language-plaintext highlighter-rouge">IK</code>).</li> </ul> <!-- ### User Profile Picture - An account MAY edit the `IK` generated identicon with a chosen picture. This picture will become part of the publicly broadcast profile of the account. --> <!-- TODO: Elaborate on wallet account and multiaccount --> <!-- TODO: Elaborate on security implications --> <h2 id="trust-establishment"> <a href="#trust-establishment" class="anchor-heading" aria-labelledby="trust-establishment"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Trust establishment </h2> <p><strong>Trust establishment deals with users verifying they are communicating with who they think they are.</strong></p> <h3 id="terms-glossary"> <a href="#terms-glossary" class="anchor-heading" aria-labelledby="terms-glossary"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Terms Glossary </h3> <div class="table-wrapper"><table> <thead> <tr> <th>term</th> <th>description</th> </tr> </thead> <tbody> <tr> <td>privkey</td> <td>ECDSA secp256k1 private key</td> </tr> <tr> <td>pubkey</td> <td>ECDSA secp256k1 public key</td> </tr> <tr> <td>Whisper/Waku key</td> <td>pubkey for chat with HD derivation path m/43’/60’/1581’/0’/0</td> </tr> </tbody> </table></div> <h3 id="contact-discovery"> <a href="#contact-discovery" class="anchor-heading" aria-labelledby="contact-discovery"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Contact Discovery </h3> <h4 id="public-channels"> <a href="#public-channels" class="anchor-heading" aria-labelledby="public-channels"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Public channels </h4> <ul> <li>Public group channels in Status are a broadcast/subscription system. All public messages are encrypted with a symmetric key derived from the channel name, <code class="language-plaintext highlighter-rouge">K_{pub,sym}</code>, which is publicly known.</li> <li>A public group channel’s symmetric key MUST creation must follow the <a href="https://web3js.readthedocs.io/en/1.0/web3-shh.html#generatesymkeyfrompassword">web3 API</a>’s <code class="language-plaintext highlighter-rouge">web3.ssh.generateSymKeyFromPassword</code> function</li> <li>In order to post to a public group channel, a client MUST have a valid account created.</li> <li>In order to listen to a public group channel, a client must subscribe to the channel name. The sender of a message is derived from the message’s signature.</li> <li>Discovery of channel names is not currently part of the protocol, and is typically done out of band. If a channel name is used that has not been used, it will be created.</li> <li>A client MUST sign the message otherwise it will be discarded by the recipients.</li> <li>channel name specification: <ul> <li>matches <code class="language-plaintext highlighter-rouge">[a-z0-9\-]</code></li> <li>is not a public key</li> </ul> </li> </ul> <h4 id="private-11-messages"> <a href="#private-11-messages" class="anchor-heading" aria-labelledby="private-11-messages"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Private 1:1 messages </h4> <p>This can be done in the following ways:</p> <ol> <li>scanning a user generated QR code</li> <li>discovery through the Status app</li> <li>asynchronous X3DH key exchange</li> <li>public key via public channel listening <ul> <li><code class="language-plaintext highlighter-rouge">status-react/src/status_im/contact_code/core.cljs</code></li> </ul> </li> <li>contact codes</li> <li>decentralized storage (not implemented)</li> <li>Whisper/Waku</li> </ol> <h3 id="initial-key-exchange"> <a href="#initial-key-exchange" class="anchor-heading" aria-labelledby="initial-key-exchange"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Initial Key Exchange </h3> <h4 id="bundles"> <a href="#bundles" class="anchor-heading" aria-labelledby="bundles"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Bundles </h4> <ul> <li>An X3DH prekey bundle is defined as (<a href="https://github.com/status-im/status-go/messaging/chat/protobuf/encryption.pb.go">code</a>): <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Identity // Identity key
|
||
SignedPreKeys // a map of installation id to array of signed prekeys by that installation id
|
||
Signature // Prekey signature
|
||
Timestamp // When the bundle was lasted created locally
|
||
</code></pre></div> </div> <ul> <li>include BundleContainer</li> </ul> </li> <li>a new bundle SHOULD be created at least every 12 hours</li> <li>a node only generates a bundle when it is used</li> <li>a bundle SHOULD be distributed on the contact code channel. This is the Whisper and Waku topic <code class="language-plaintext highlighter-rouge">{IK}-contact-code</code>, where <code class="language-plaintext highlighter-rouge">IK</code> is the hex encoded public key of the user, prefixed with <code class="language-plaintext highlighter-rouge">0x</code>. The node encrypts the channel in the same way it encrypted public chats.</li> </ul> <h3 id="contact-verification"> <a href="#contact-verification" class="anchor-heading" aria-labelledby="contact-verification"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Contact Verification </h3> <p>To verify that contact key information is as it should be, use the following.</p> <h4 id="identicon"> <a href="#identicon" class="anchor-heading" aria-labelledby="identicon"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Identicon </h4> <p>A low-poly identicon is deterministically generated from the Whisper/Waku chat public key. This can be compared out of band to ensure the receiver’s public key is the one stored locally.</p> <h4 id="3-word-pseudonym--whisperwaku-key-fingerprint"> <a href="#3-word-pseudonym--whisperwaku-key-fingerprint" class="anchor-heading" aria-labelledby="3-word-pseudonym--whisperwaku-key-fingerprint"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> 3 word pseudonym / Whisper/Waku key fingerprint </h4> <p>Status generates a deterministic 3-word random pseudonym from the Whisper/Waku chat public key. This pseudonym acts as a human readable fingerprint to the Whisper/Waku chat public key. This name also shows when viewing a contact’s public profile and in the chat UI.</p> <ul> <li>implementation: <a href="https://github.com/status-im/status-react/tree/develop/src/status_im/utils/gfycat">gfycat</a></li> </ul> <h4 id="ens-name"> <a href="#ens-name" class="anchor-heading" aria-labelledby="ens-name"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> ENS name </h4> <p>Status offers the ability to register a mapping of a human readable subdomain of <code class="language-plaintext highlighter-rouge">stateofus.eth</code> to their Whisper/Waku chat public key. The user purchases this registration (currently by staking 10 SNT) and the node stores it on the Ethereum mainnet blockchain for public lookup.</p> <!-- TODO: Elaborate on security implications --> <!-- TODO: Incorporate or cut below into proper spec ### Possible Connection Breakdown possible connections - client - client (not really ever, this is facilitated through all other connections) - personal chat - ratcheted with X3DH - private group chat - pairwise ratcheted with X3DH - public chat - client - mailserver (statusd + ???) - a mailserver identifies itself by an [enode address](https://github.com/ethereum/wiki/wiki/enode-url-format) - client - Whisper/Waku node (statusd) - a node identifies itself by an enode address - client - bootnode (go-ethereum) - a bootnode identifies itself by - an enode address - `NOTE: redezvous information here` - client - ENS registry (ethereum blockchain -> default to infura) - client - Ethereum RPC (custom go-ethereum RPC API -> default to infura API) - client - IPFS (Status hosted IPFS gateway -> defaults to ???) - we have a status hosted IPFS gateway for pinning but it currently isn't used much. ### Notes A user in the system is a public-private key pair using the Elliptic-Curve Cryptography secp256k1 that Ethereum uses. - A 3-word random name is derived from the public key using the following package - `NOTE: need to find package` - This provides an associated human-readble fingerprint to the user's public key - A user can optionally add additional layers on top of this keypair - Chosen username - ENS username All messages sent are encrypted with the public key of the destination and signed by the private key of the given user using the following scheme: - private chat - X3DH is used to define shared secrets which is then double ratcheted - private group chat - considered pairwise private chats - public group chat - the message is encrypted with a symmetric key derived from the chat name --> <h2 id="public-key-serialization"> <a href="#public-key-serialization" class="anchor-heading" aria-labelledby="public-key-serialization"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Public Key Serialization </h2> <p>Idiomatically known as “public key compression” and “public key decompression”.</p> <p>The node SHOULD provide functionality for the serialization and deserialization of public / chat keys.</p> <p>For maximum flexibility, when implementing this functionality, the node MUST support public keys encoded in a range of encoding formats, detailed below.</p> <h3 id="basic-serialization-example"> <a href="#basic-serialization-example" class="anchor-heading" aria-labelledby="basic-serialization-example"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Basic Serialization Example </h3> <p>In the example of a typical hexadecimal encoded elliptical curve (EC) public key (such as a secp256k1 pk),</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x04261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6
|
||
</code></pre></div></div> <p>minor modification for compatibility and flexibility makes the key self-identifiable and easily parsable,</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fe70104261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6
|
||
</code></pre></div></div> <p>EC serialization and compact encoding produces a much smaller string representation of the original key.</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>zQ3shPyZJnxZK4Bwyx9QsaksNKDYTPmpwPvGSjMYVHoXHeEgB
|
||
</code></pre></div></div> <h3 id="public-key-compression-rationale"> <a href="#public-key-compression-rationale" class="anchor-heading" aria-labelledby="public-key-compression-rationale"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Public Key “Compression” Rationale </h3> <p>Serialized and compactly encoded (“compressed”) public keys have a number of UI / UX advantages over non-serialized less densely encoded public keys.</p> <p>Compressed public keys are smaller, and users may perceive them as less intimidating and less unnecessarily large. Compare the “compressed” and “uncompressed” version of the same public key from above example:</p> <ul> <li><code class="language-plaintext highlighter-rouge">0xe70104261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6</code></li> <li><code class="language-plaintext highlighter-rouge">zQ3shPyZJnxZK4Bwyx9QsaksNKDYTPmpwPvGSjMYVHoXHeEgB</code></li> </ul> <p>The user can transmit and share the same data, but at one third of the original size. 136 characters uncompressed vs 49 characters compressed, giving a significant character length reduction of 64%.</p> <p>The user client app MAY use the compressed public keys throughout the user interface. For example in the <code class="language-plaintext highlighter-rouge">status-react</code> implementation of the user interface the following places could take advantage of a significantly smaller public key:</p> <ul> <li><code class="language-plaintext highlighter-rouge">Onboarding</code> > <code class="language-plaintext highlighter-rouge">Choose a chat name</code></li> <li><code class="language-plaintext highlighter-rouge">Profile</code> > <code class="language-plaintext highlighter-rouge">Header</code></li> <li><code class="language-plaintext highlighter-rouge">Profile</code> > <code class="language-plaintext highlighter-rouge">Share icon</code> > <code class="language-plaintext highlighter-rouge">QR code popover</code></li> <li><code class="language-plaintext highlighter-rouge">Invite friends</code> url from <code class="language-plaintext highlighter-rouge">Invite friends</code> button and <code class="language-plaintext highlighter-rouge">+ -button</code> > <code class="language-plaintext highlighter-rouge">Invite friends</code></li> <li>Other user <code class="language-plaintext highlighter-rouge">Profile details</code></li> <li><code class="language-plaintext highlighter-rouge">Profile details</code> > <code class="language-plaintext highlighter-rouge">Share icon</code> > <code class="language-plaintext highlighter-rouge">QR code popover</code></li> </ul> <p>In the case of QR codes a compressed public key can reduce the complexity of the derived codes:</p> <div class="table-wrapper"><table> <thead> <tr> <th>Uncompressed</th> <th>Compressed</th> </tr> </thead> <tbody> <tr> <td><img src="https://user-images.githubusercontent.com/5702426/80531063-e98fcc80-8991-11ea-8c02-c354b5828d35.png" width="400" /></td> <td><img src="https://user-images.githubusercontent.com/5702426/80501933-f4356c00-8967-11ea-87d8-eae18becece9.png" width="400" /></td> </tr> </tbody> </table></div> <h3 id="key-encoding"> <a href="#key-encoding" class="anchor-heading" aria-labelledby="key-encoding"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Key Encoding </h3> <p>When implementing the pk de/serialization functionality, the node MUST use the <a href="https://github.com/multiformats/multibase">multiformats/multibase</a> encoding protocol to interpret incoming key data and to return key data in a desired encoding.</p> <p>The node SHOULD support the following <code class="language-plaintext highlighter-rouge">multibase</code> encoding formats.</p><pre><code class="language-csv">encoding, code, description, status
|
||
identity, 0x00, 8-bit binary (encoder and decoder keeps data unmodified), default
|
||
base2, 0, binary (01010101), candidate
|
||
base8, 7, octal, draft
|
||
base10, 9, decimal, draft
|
||
base16, f, hexadecimal, default
|
||
base16upper, F, hexadecimal, default
|
||
base32hex, v, rfc4648 case-insensitive - no padding - highest char, candidate
|
||
base32hexupper, V, rfc4648 case-insensitive - no padding - highest char, candidate
|
||
base32hexpad, t, rfc4648 case-insensitive - with padding, candidate
|
||
base32hexpadupper, T, rfc4648 case-insensitive - with padding, candidate
|
||
base32, b, rfc4648 case-insensitive - no padding, default
|
||
base32upper, B, rfc4648 case-insensitive - no padding, default
|
||
base32pad, c, rfc4648 case-insensitive - with padding, candidate
|
||
base32padupper, C, rfc4648 case-insensitive - with padding, candidate
|
||
base32z, h, z-base-32 (used by Tahoe-LAFS), draft
|
||
base36, k, base36 [0-9a-z] case-insensitive - no padding, draft
|
||
base36upper, K, base36 [0-9a-z] case-insensitive - no padding, draft
|
||
base58btc, z, base58 bitcoin, default
|
||
base58flickr, Z, base58 flicker, candidate
|
||
base64, m, rfc4648 no padding, default
|
||
base64pad, M, rfc4648 with padding - MIME encoding, candidate
|
||
base64url, u, rfc4648 no padding, default
|
||
base64urlpad, U, rfc4648 with padding, default
|
||
</code></pre><p><strong>Note</strong> this specification RECOMMENDs that implementations extend the standard <code class="language-plaintext highlighter-rouge">multibase</code> protocol to parse strings prepended with <code class="language-plaintext highlighter-rouge">0x</code> as <code class="language-plaintext highlighter-rouge">f</code> hexadecimal encoded bytes.</p> <p>Implementing this recommendation will allow the node to correctly interpret traditionally identified hexadecimal strings (e.g. <code class="language-plaintext highlighter-rouge">0x1337c0de</code>).</p> <p><em>Example:</em></p> <p><code class="language-plaintext highlighter-rouge">0xe70102261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc</code></p> <p>SHOULD be interpreted as</p> <p><code class="language-plaintext highlighter-rouge">fe70102261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc</code></p> <p>This specification RECOMMENDs that the consuming service of the node uses a compact encoding type, such as base64 or base58 to allow for as short representations of the key as possible.</p> <h3 id="public-key-types"> <a href="#public-key-types" class="anchor-heading" aria-labelledby="public-key-types"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Public Key Types </h3> <p>When implementing the pk de/serialization functionality, The node MUST support the <a href="https://github.com/multiformats/multicodec">multiformats/multicodec</a> key type identifiers for the following public key type.</p> <div class="table-wrapper"><table> <thead> <tr> <th>Name</th> <th>Tag</th> <th>Code</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code class="language-plaintext highlighter-rouge">secp256k1-pub</code></td> <td>key</td> <td><code class="language-plaintext highlighter-rouge">0xe7</code></td> <td>Secp256k1 public key</td> </tr> </tbody> </table></div> <p>For a public key to be identifiable to the node the public key data MUST be prepended with the relevant <a href="https://github.com/multiformats/unsigned-varint">multiformats/unsigned-varint</a> formatted code.</p> <p><em>Example:</em></p> <p>Below is a representation of an deserialized secp256k1 public key.</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>04
|
||
26 | 1c | 55 | 67 | 5e | 55 | ff | 25
|
||
ed | b5 | 0b | 34 | 5c | fb | 3a | 3f
|
||
35 | f6 | 07 | 12 | d2 | 51 | cb | aa
|
||
ab | 97 | bd | 50 | 05 | 4c | 6e | bc
|
||
3c | d4 | e2 | 22 | 00 | c6 | 8d | af
|
||
74 | 93 | e1 | f8 | da | 6a | 19 | 0a
|
||
68 | a6 | 71 | e2 | d3 | 97 | 78 | 09
|
||
61 | 24 | 24 | c7 | c3 | 88 | 8b | c6
|
||
</code></pre></div></div> <p>The <code class="language-plaintext highlighter-rouge">multicodec</code> code for a secp256k1 public key is <code class="language-plaintext highlighter-rouge">0xe7</code>.</p> <p>After parsing the code <code class="language-plaintext highlighter-rouge">0xe7</code> as a <code class="language-plaintext highlighter-rouge">multiformats/uvarint</code>, the byte value is <code class="language-plaintext highlighter-rouge">0xe7 0x01</code>, prepending this to the public key results in the below representation.</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>e7 | 01 | 04
|
||
26 | 1c | 55 | 67 | 5e | 55 | ff | 25
|
||
ed | b5 | 0b | 34 | 5c | fb | 3a | 3f
|
||
35 | f6 | 07 | 12 | d2 | 51 | cb | aa
|
||
ab | 97 | bd | 50 | 05 | 4c | 6e | bc
|
||
3c | d4 | e2 | 22 | 00 | c6 | 8d | af
|
||
74 | 93 | e1 | f8 | da | 6a | 19 | 0a
|
||
68 | a6 | 71 | e2 | d3 | 97 | 78 | 09
|
||
61 | 24 | 24 | c7 | c3 | 88 | 8b | c6
|
||
</code></pre></div></div> <h3 id="deserialization-process-flow"> <a href="#deserialization-process-flow" class="anchor-heading" aria-labelledby="deserialization-process-flow"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> De/Serialization Process Flow </h3> <p>When implementing the pk de/serialization functionality, the node MUST be passed a <code class="language-plaintext highlighter-rouge">multicodec</code> identified public key, of the above supported types, encoded with a valid <code class="language-plaintext highlighter-rouge">multibase</code> identifier.</p> <p>This specification RECOMMENDs that the node also accept an encoding type parameter to encode the output data. This provides for the case where the user requires the de/serialization key to be in a different encoding to the encoding of the given key.</p> <h4 id="serialization-example"> <a href="#serialization-example" class="anchor-heading" aria-labelledby="serialization-example"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Serialization Example </h4> <p>A hexadecimal encoded secp256k1 public chat key typically is represented as below:</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>0x04261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6
|
||
</code></pre></div></div> <p>To be properly interpreted by the node for serialization the public key MUST be prepended with the <code class="language-plaintext highlighter-rouge">multicodec</code> <code class="language-plaintext highlighter-rouge">uvarint</code> code <code class="language-plaintext highlighter-rouge">0xea 0x01</code> and encoded with a valid <code class="language-plaintext highlighter-rouge">multibase</code> encoding, therefore giving the following:</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fea0104261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6
|
||
</code></pre></div></div> <p>If adhering to the specification recommendation to provide the user with an output encoding parameter, the above string would be passed to the node with the following <code class="language-plaintext highlighter-rouge">multibase</code> encoding identifier.</p> <p>In this example the output encoding is defined as <code class="language-plaintext highlighter-rouge">base58 bitcoin</code>.</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>z
|
||
</code></pre></div></div> <p>The return value in this case would be</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>zQ3shPyZJnxZK4Bwyx9QsaksNKDYTPmpwPvGSjMYVHoXHeEgB
|
||
</code></pre></div></div> <p>Which after <code class="language-plaintext highlighter-rouge">multibase</code> decoding can be represented in bytes as below:</p> <div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>e7 | 01 | 02
|
||
26 | 1c | 55 | 67 | 5e | 55 | ff | 25
|
||
ed | b5 | 0b | 34 | 5c | fb | 3a | 3f
|
||
35 | f6 | 07 | 12 | d2 | 51 | cb | aa
|
||
ab | 97 | bd | 50 | 05 | 4c | 6e | bc
|
||
</code></pre></div></div> <h4 id="deserialization-example"> <a href="#deserialization-example" class="anchor-heading" aria-labelledby="deserialization-example"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Deserialization Example </h4> <p>For the user, the deserialization process is exactly the same as serialization with the exception that the user MUST provide a serialized public key for deserialization. Else the deserialization algorithm will fail.</p> <p>For further guidance on the implementation of public key de/serialization consult the <a href="https://github.com/status-im/status-go/blob/c9772325f2dca76b3504191c53313663ca2efbe5/api/utils_test.go"><code class="language-plaintext highlighter-rouge">status-go</code> implementation and tests</a>.</p> <h2 id="security-considerations"> <a href="#security-considerations" class="anchor-heading" aria-labelledby="security-considerations"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Security Considerations </h2> <p>-</p> <h2 id="changelog"> <a href="#changelog" class="anchor-heading" aria-labelledby="changelog"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Changelog </h2> <h3 id="version-04"> <a href="#version-04" class="anchor-heading" aria-labelledby="version-04"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Version 0.4 </h3> <p>Released <a href="https://github.com/status-im/specs/commit/e98a9b76b7d4e1ce93e0b692e1521c2d54f72c59">June 24, 2020</a></p> <ul> <li>Added details of public key serialization and deserialization</li> </ul> <h3 id="version-03"> <a href="#version-03" class="anchor-heading" aria-labelledby="version-03"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Version 0.3 </h3> <p>Released <a href="https://github.com/status-im/specs/commit/664dd1c9df6ad409e4c007fefc8c8945b8d324e8">May 22, 2020</a></p> <ul> <li>Added language to include Waku in all relevant places</li> <li>Change to keep <code class="language-plaintext highlighter-rouge">Mailserver</code> term consistent</li> <li>Added clarification to Open Whisper Systems</li> </ul> <h2 id="copyright"> <a href="#copyright" class="anchor-heading" aria-labelledby="copyright"><svg viewBox="0 0 16 16" aria-hidden="true"><use xlink:href="#svg-link"></use></svg></a> Copyright </h2> <p>Copyright and related rights waived via <a href="https://creativecommons.org/publicdomain/zero/1.0/">CC0</a>.</p> </div> </div> <div class="search-overlay"></div> </div> </body> </html>
|