negative zero

What is Session?

2021 April 28

[crypto] [decentralization] [info] [messaging] [oxen] [privacy] [session] [tech]

Updated 2021 May 24 with information about Session's security audit.

Updated 2021 May 25 with a correction: Session doesn't use Lokinet yet, but it does use Oxen Service Nodes.

Updated 2021 May 25 with an update on whether I would use Session.

Updated 2022 January 14 with a note about how much $OXEN someone must have to stake.

Updated 2022 January 25 with a correction about the Session Protocol's full implementation.

People have been talking about Session as an alternative to Signal for a while. When I first heard of it, I looked it up, saw it had something to do with cryptocurrencies, and decided it wasn't worth my time.

Well, yesterday I finally got around to revisiting it and learning a little more about how it works.

Session is a fork of Signal which is designed to be decentralized (unlike Signal), anonymous (unlike Signal), and private (originally using the Signal Protocol for end-to-end encryption, later moving to a simpler protocol).


Session runs on Lokinet, which is an anonymity network that tries to solve some of the issues of Tor. Session has not implemented Lokinet (which includes UDP support) yet, but it does use the Oxen Service Nodes as I described. Lokinet runs on a proof-of-stake cryptocurrency called Oxen. Here's how it works... Oxen Service Nodes must stake 15,000 $OXEN (28,950 USD at time of writing) and maintain high performance and uptime to participate in the network. This is done to protect against Sybil attacks by making it expensive to set up new nodes, and to ensure high network performance. Session uses these service nodes to relay messages anonymously (via onion routing).

(Note added 2021/01/14: Multiple people can pool their resources to stake. The minimum Service Node operator staking requirement is 3,750 $OXEN (25%). That's still a lot of money, but it's a lot less than 15,000 $OXEN.)

When both parties are online, the service nodes simply relay messages. However, when the recipient is offline, the message must be stored long enough for it to be delivered when that party comes back online. In this case, a "swarm" of service nodes stores the message on the recipient's behalf for a designated period of time.

Anonymity and Metadata Protection

Session does not require any information to sign up. Signing up simply entails generating keys and joining the network. Users specify nicknames, but they are simply identified by their public keys. Messages are anonymously routed through Lokinet Oxen Service Nodes.


The Session Protocol sacrifices some of the benefits of the Signal Protocol: forward secrecy, backward secrecy, and deniability, arguing that these properties are generally irrelevant. The cryptography is pretty straight-forward...

Note: The following is actually an intermediate protocol for backwards compatibility. The full version, which is even simpler, is below it.

  1. Alice and Bob each have a long-term X25519 keypair.
  2. Alice: (ISK_1, IPK_1)

    Bob: (ISK_2, IPK_2)

  3. Alice writes a message and signs it with her long-term private key.
  4. Alice: S = sign(M, ISK_1)

  5. Alice generates an ephemeral keypair. She performs an ECDH using her ephemeral keypair's secret key and Bob's public key. She then generates a shared secret from this using a key derivation function.
  6. Alice: (ESK, EPK)

    Alice: SK = HKDF(ECDH(ESK, IPK_2))

  7. Alice concatenates her signature and her message, then encrypts the result with the shared secret.
  8. Alice: C = AES-GCM(S || M, SK)

  9. Alice sends the ciphertext and ephemeral public key to Bob.
  10. Bob: C, EPK

  11. Bob computes the shared secret. He can now decrypt the ciphertext and verify Alice's signature.
  12. Bob: SK = HKDF(ECDH(ISK_2, EPK))

Full Implementation

This section was added on 2022 January 25.

  1. Alice and Bob each have a long-term Curve25519 keypair.
  2. Alice: (alice_privkey_ed25519, alice_pubkey_ed25519)

    Bob: (bob_privkey_x25519, bob_pubkey_x25519)

  3. Alice writes a message and concatenates her Ed25519 public key and Bob's X25519 public key.
  4. Alice: m = message || alice_pubkey_ed25519 || bob_pubkey_x25519

  5. Alice signs this message with her private key.
  6. Alice: s = signature(m, alice_privkey_ed25519)

  7. Alice encrypts the message, her public key, and the signature with the libsodium crypto_box_sealed() function.
  8. Alice: x = crypto_box_sealed(message || alice_pubkey_ed25519 || s, recipient_pubkey_x25519)

  9. Alice sends this sealed box x to Bob, who can now decrypt it and verify Alice's signature.
  10. Bob: x

As you can see here, Alice signs the message with her long-term private key, giving this interaction the property of non-repudiation. Rather than offer cryptographic deniability, Session intends to allow users to modify local copies of messages sent by other users, thus casting into doubt any message displayed in the Session client. It's a fun solution, but Bob could still store Alice's signature and use that as evidence.

Client Support

Session is available cross-platform (on Android, iOS, Windows, macOS, and GNU/Linux). The desktop version is Electron, because of course it is. The UI is pretty simple, but it looks nice enough. AppImage seems to be the distribution method of choice for the GNU/Linux version, but there's also a .deb.

The Android version does not yet qualify for the main F-Droid repo because it includes code to enable Google push notifications. Session offers its own F-Droid repo, and the app can alternatively be downloaded as an APK.

Security Audit

This section was added on 2021 May 24.

Session has undergone a third-party security audit. I want to talk briefly about it.

The security evaluation was performed by Quarkslab and discusses issues found with the Android, iOS, and Electron versions of the program (in that order). Here are some things I think are worth noting:

Session announcement

Quarkslab announcement

Quarkslab audit (PDF)


I personally don't plan to start using Session or Lokinet. The involvement of a cryptocurrency raises some alarms for me, and I don't agree with providing such a high barrier for entry to participation as a service node in the Lokinet/Oxen network. Call me a cynic, but I don't think "node operators are required to be rich" is a good way to achieve decentralization. I'm also not impressed by Session's crypto, given it descends from Signal but decided to take out some of its security features. I'm also quite uninterested in adding more Electron to my life.

That said, I do like that it's designed with decentralization and anonymity in mind. We need something that's as easy to use as Signal but decentralized, and anonymous, with metadata protections.

Update 2021 May 5: There's a lot of buzz about Session right now, which makes me think it might actually start to reach a mainstream audience (like Signal did). I think Session meets my criteria for something I would use if asked, but I wouldn't ask someone else to use it. That's to say, I don't plan to start using it, but if someone asks me to, I probably will. Certainly, I'd prefer Session over unencrypted emails with someone's Google account, which is how most people talk to me.

Links and Sources