Building on Foundations

Identity

The majority of popular messengers require the user to register via email or phone number in order to use the service. This approach provides some advantages, like social network discoverability, spam protection, etc. In the same time the major disadvantage is that it introduces significant privacy issues for users.
The use of phone numbers as the basis for user identity is a security breach. The problem comes from the fact that phone numbers are managed by the centralized service providers who can circumvent user control, allowing these provider to assume direct control of users phone number. Also SIM swapping attacks or service provider hacking can be exploited by third-party adversaries.
Using phone numbers as the basis for user registration also significantly hurts user privacy and anonymity. Many countries require client to provide identification documents in order to register a new phone number. It makes trivial for authorities to link particular account to a citizen. Leaking a database with the mapping between user phone numbers to account is another concern. As well as potential access to such database by dishonest employees.
Requirement to provide the phone number for registration also limit the establishement of multiple identities by a single user and prevents high-risk users without access to mobile phone accessing such services.
Tingl doesn’t require email or mobile phone as the basis of it’s identity system. Instead, X25519 keypairs is used. These pairs are not linked to any other identifier and new keypairs could be generated infinitely in seconds.

Account Restoration

Since Tingl doesn’t have central server to store user identities, it’s impossible to use traditional account restoration workflows. Instead, users promted to save their private key, represented as a mnemonic phrase, and later use this phrase to restore their access to the account. Hence the user’s contacts can use the same idenentity to message the client, rather than having to to generate a new identity and reinitiate conversation with the user’s contact list.

Bootstraping

To use onion routing, each Tingl client needs a list of all Service Nodes in the network. On startup the client fetches this list from a known trusted node. After startup the client periodically asks any known Service Node for updates. Each Service Node should have up-to-date list of available nodes, because of DHT discovery and gossiping between nodes.

Messaging

Offline Messaging

By default and if recipient status is offline, Offline Messaging scheme will be used. In case of Offline Messaging, the sender stores a message for the recipient in the network (see Kademlia DHT) and recipient can get this message from the network during predefined TTL. The sender creates the message protobuf and packs it in an envelope with additional metadata for Service Node to process: the identity key of the recipient, TTL timestamp and a nonce which proves the completion of required Proof-of-Work (see Spam). The sender sends the envelope to some Service Node inside the network via onion request and that Service Node populate the envelope inside the network.
Alice uses onion request to communicate with the network and store the envelope for Bob. Bob uses onion request to fetch envelopes.

Online Messaging

Tingl clients expose their online status in every offline message they send along with a Service Node address in the network they are listening to. This network can be used to send messages directly to the client. The recipient uses the sender’s listening node to respond to the original message and also exposes it’s own listening node thus establishing online connection between nodes. From this point clients are able to communicate with each other by sending messages to corresponding listening nodes and fetching incoming messages from their own listening nodes. If one of the communicating parties goes offline and listening node fails to deliver the messages, communication falls back to Offline Messaging scheme (see Offline Messaging). Online message envelopes don’t have Proof-of-Work nonce included and never stored or replicated in the network. Such messages should be delivered directly to the recipient.
Alice uses onion request to send a message to Bob’s listening node. Bob uses onion request to fetch Alice’s message and sends a message to Alice’s listenging node.

Signal Protocol

Onion routing together with DHT provide secure transport and storage layer. How- ever any secure messaging application also requires properties of Perfect Forward Secrecy (PFS) and deniable authentication to be satisfied.
To achieve these properties, Tingl implements Signal Protocol (https://signal.org/docs/). Signal protocol achieves propeties of PFS and deniable authentication in asyncrhonous environments by using Extended Triple Diffie-Hellman (https://signal.org/docs/specifications/x3dh/) (X3DH) key agreement algorithm and Double Ratchet (https://signal.org/docs/specifications/doubleratchet/) encrypted message exchange algorithm.
Let’s imagine Alice and Bob want to exchange secret. Each client has a long- term public key (
IKAIK_A
for Alice and
IKBIK_B
for Bob). Also Bob has a signed prekey
SPKBSPK_B
which he updates periodically, and set of one-time prekeys
OPKBOPK_B
, which a used in a single X3DH run.
During each protocol run, Alice generates a new ephemeral key pair with public key
EKAEK_A
.
After a successful protocol run Alice and Bob will share a 32-byte secret key
SKSK
.
To perform an X3DH key agreement with Bob, Alice obtains a ”prekey bundle”, verifies signatures and then generates an ephemeral key pair with public key
EKAEK_A
. Then Alice performs the following calculations:
DH1=DH(IKA,SPKB)DH2=DH(EKA,IKB)DH3=DH(EKA,SPKB)DH4=DH(EKA,OPKB)SK=KDF(DH1DH2DH3DH4)DH1 = DH(IK_A, SPK_B) \\ DH2 = DH(EK_A, IK_B) \\ DH3 = DH(EK_A, SPK_B) \\ DH4 = DH(EK_A,OPK_B) \\ SK = KDF(DH1||DH2||DH3||DH4)
DH1DH1
and
DH2DH2
provide mutual authentication, while
DH3DH3
and
DH4DH4
provide forward secrecy.
After calculating
SKSK
, Alice deletes her ephemeral private key and the
DHDH
outputs. Alice then calculates an ”associated data” byte sequence
ADAD
that contains identity information for both parties:
AD=Encode(IKA)Encode(IKB)AD = Encode(IK_A)||Encode(IK_B)
Alice may optionally append additional information to
ADAD
, such as Alice and Bob’s usernames, certificates, or other identifying information.
Alice then sends Bob an initial message containing:
  • Alice’s identity key
    IKAIK_A
  • Alice’s ephemeral key
    EKAEK_A
  • Identifiers stating which of Bob’s prekeys Alice used
  • An initial ciphertext encrypted with some AEAD encryption scheme using AD as associated data and using an encryption key which is either
    SKSK
    or the output from some cryptographic PRF keyed by
    SKSK
    .
Upon receiving Alice’s initial message, Bob retrieves Alice’s identity key and ephemeral key from the message. Bob also loads his identity private key, and the private key(s) corresponding to whichever signed prekey and one-time prekey Alice used.
Using these keys, Bob repeats the
DHDH
and
KDFKDF
calculations from the previous section to derive
SKSK
, and then deletes the
DHDH
values.
The Double Ratchet algorithm is used by two parties to exchange encrypted messages based on a shared secret key. It uses KDF chains to derive new keys for every message so that earlier keys can’t be calculated from later ones. The parties also send Diffie-Hellman public values attached to their messages. The results of Diffie-Hellman calculations are mixed into derived keys so that later keys can’t be calculated from earlier ones. These properties give protection to earlier or later encrypted messages in case of compromise party’s keys.
Double Ratchet.