2/ACCOUNT
Version: 0.4
Status: Stable
Authors: Corey Petty corey@status.im, Oskar Thorén oskar@status.im, Samuel Hawksby-Robinson samuel@status.im (alphabetical order)
Abstract
This specification explains what Status account is, and how a node establishes trust.
Table of Contents
- Abstract
- Table of Contents
- Introduction
- Initial Key Generation
- Account Broadcasting
- Optional Account additions
- Trust establishment
- Public Key Serialization
- Security Considerations
- Changelog
Introduction
The core concept of an account in Status is a set of cryptographic keypairs. Namely, the combination of the following:
- a Whisper/Waku chat identity keypair
- a set of cryptocurrency wallet keypairs
The node verifies or derives everything else associated with the contact from the above items, including:
- Ethereum address (future verification, currently the same base keypair)
- 3 word mnemonic name
- identicon
- message signatures
Initial Key Generation
Public/Private Keypairs
- An ECDSA (secp256k1 curve) public/private keypair MUST be generated via a BIP43 derived path from a BIP39 mnemonic seed phrase.
- The default paths are defined as such:
X3DH Prekey bundle creation
- Status follows the X3DH prekey bundle scheme that Open Whisper Systems (not to be confused with the Whisper sub-protocol) outlines in their documentation with the following exceptions:
- Status does not publish one-time keys
OPK
or perform DH including them, because there are no central servers in the Status implementation.
- Status does not publish one-time keys
- A client MUST create X3DH prekey bundles, each defined by the following items:
- Identity Key:
IK
- Signed prekey:
SPK
- Prekey signature:
Sig(IK, Encode(SPK))
- Timestamp
- Identity Key:
- These bundles are made available in a variety of ways, as defined in section 2.1.
Account Broadcasting
- A user is responsible for broadcasting certain information publicly so that others may contact them.
X3DH Prekey bundles
- 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.
- The current bundle SHOULD be broadcast on a Whisper/Waku topic specific to his Identity Key,
{IK}-contact-code
, intermittently. This MAY be done every 6 hours. - A bundle SHOULD accompany every message sent.
- TODO: retrieval of long-time offline users bundle via
{IK}-contact-code
Optional Account additions
ENS Username
- A user MAY register a public username on the Ethereum Name System (ENS). This username is a user-chosen subdomain of the
stateofus.eth
ENS registration that maps to their Whisper/Waku identity key (IK
).
Trust establishment
Trust establishment deals with users verifying they are communicating with who they think they are.
Terms Glossary
term | description |
---|---|
privkey | ECDSA secp256k1 private key |
pubkey | ECDSA secp256k1 public key |
Whisper/Waku key | pubkey for chat with HD derivation path m/43’/60’/1581’/0’/0 |
Contact Discovery
Public channels
- Public group channels in Status are a broadcast/subscription system. All public messages are encrypted with a symmetric key derived from the channel name,
K_{pub,sym}
, which is publicly known. - A public group channel’s symmetric key MUST creation must follow the web3 API’s
web3.ssh.generateSymKeyFromPassword
function - In order to post to a public group channel, a client MUST have a valid account created.
- 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.
- 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.
- A client MUST sign the message otherwise it will be discarded by the recipients.
- channel name specification:
- matches
[a-z0-9\-]
- is not a public key
- matches
Private 1:1 messages
This can be done in the following ways:
- scanning a user generated QR code
- discovery through the Status app
- asynchronous X3DH key exchange
- public key via public channel listening
status-react/src/status_im/contact_code/core.cljs
- contact codes
- decentralized storage (not implemented)
- Whisper/Waku
Initial Key Exchange
Bundles
- An X3DH prekey bundle is defined as (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
- include BundleContainer
- a new bundle SHOULD be created at least every 12 hours
- a node only generates a bundle when it is used
- a bundle SHOULD be distributed on the contact code channel. This is the Whisper and Waku topic
{IK}-contact-code
, whereIK
is the hex encoded public key of the user, prefixed with0x
. The node encrypts the channel in the same way it encrypted public chats.
Contact Verification
To verify that contact key information is as it should be, use the following.
Identicon
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.
3 word pseudonym / Whisper/Waku key fingerprint
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.
- implementation: gfycat
ENS name
Status offers the ability to register a mapping of a human readable subdomain of stateofus.eth
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.
Public Key Serialization
Idiomatically known as “public key compression” and “public key decompression”.
The node SHOULD provide functionality for the serialization and deserialization of public / chat keys.
For maximum flexibility, when implementing this functionality, the node MUST support public keys encoded in a range of encoding formats, detailed below.
Basic Serialization Example
In the example of a typical hexadecimal encoded elliptical curve (EC) public key (such as a secp256k1 pk),
0x04261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6
minor modification for compatibility and flexibility makes the key self-identifiable and easily parsable,
fe70104261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6
EC serialization and compact encoding produces a much smaller string representation of the original key.
zQ3shPyZJnxZK4Bwyx9QsaksNKDYTPmpwPvGSjMYVHoXHeEgB
Public Key “Compression” Rationale
Serialized and compactly encoded (“compressed”) public keys have a number of UI / UX advantages over non-serialized less densely encoded public keys.
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:
0xe70104261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6
zQ3shPyZJnxZK4Bwyx9QsaksNKDYTPmpwPvGSjMYVHoXHeEgB
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%.
The user client app MAY use the compressed public keys throughout the user interface. For example in the status-react
implementation of the user interface the following places could take advantage of a significantly smaller public key:
Onboarding
>Choose a chat name
Profile
>Header
Profile
>Share icon
>QR code popover
Invite friends
url fromInvite friends
button and+ -button
>Invite friends
- Other user
Profile details
Profile details
>Share icon
>QR code popover
In the case of QR codes a compressed public key can reduce the complexity of the derived codes:
Uncompressed | Compressed |
---|---|
Key Encoding
When implementing the pk de/serialization functionality, the node MUST use the multiformats/multibase encoding protocol to interpret incoming key data and to return key data in a desired encoding.
The node SHOULD support the following multibase
encoding formats.
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
Note this specification RECOMMENDs that implementations extend the standard multibase
protocol to parse strings prepended with 0x
as f
hexadecimal encoded bytes.
Implementing this recommendation will allow the node to correctly interpret traditionally identified hexadecimal strings (e.g. 0x1337c0de
).
Example:
0xe70102261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc
SHOULD be interpreted as
fe70102261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc
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.
Public Key Types
When implementing the pk de/serialization functionality, The node MUST support the multiformats/multicodec key type identifiers for the following public key type.
Name | Tag | Code | Description |
---|---|---|---|
secp256k1-pub | key | 0xe7 | Secp256k1 public key |
For a public key to be identifiable to the node the public key data MUST be prepended with the relevant multiformats/unsigned-varint formatted code.
Example:
Below is a representation of an deserialized secp256k1 public key.
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
The multicodec
code for a secp256k1 public key is 0xe7
.
After parsing the code 0xe7
as a multiformats/uvarint
, the byte value is 0xe7 0x01
, prepending this to the public key results in the below representation.
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
De/Serialization Process Flow
When implementing the pk de/serialization functionality, the node MUST be passed a multicodec
identified public key, of the above supported types, encoded with a valid multibase
identifier.
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.
Serialization Example
A hexadecimal encoded secp256k1 public chat key typically is represented as below:
0x04261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6
To be properly interpreted by the node for serialization the public key MUST be prepended with the multicodec
uvarint
code 0xea 0x01
and encoded with a valid multibase
encoding, therefore giving the following:
fea0104261c55675e55ff25edb50b345cfb3a3f35f60712d251cbaaab97bd50054c6ebc3cd4e22200c68daf7493e1f8da6a190a68a671e2d3977809612424c7c3888bc6
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 multibase
encoding identifier.
In this example the output encoding is defined as base58 bitcoin
.
z
The return value in this case would be
zQ3shPyZJnxZK4Bwyx9QsaksNKDYTPmpwPvGSjMYVHoXHeEgB
Which after multibase
decoding can be represented in bytes as below:
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
Deserialization Example
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.
For further guidance on the implementation of public key de/serialization consult the status-go
implementation and tests.
Security Considerations
-
Changelog
Version 0.4
Released June 24, 2020
- Added details of public key serialization and deserialization
Version 0.3
Released May 22, 2020
- Added language to include Waku in all relevant places
- Change to keep
Mailserver
term consistent - Added clarification to Open Whisper Systems
Copyright
Copyright and related rights waived via CC0.