SimpleX low-level protocol analysis
Background
The SimpleX Chat Protocol is utilized by SimpleX Chat clients for message exchange. It is built upon foundational SimpleX protocols, specifically the SimpleX Messaging Protocol (SMP) and the SimpleX Messaging Agent Protocol. This analysis will focus exclusively on the lower-level SimpleX protocols.
Topologically, SimpleX is similar to Nostr, where users post their information to servers they choose, for other users to view and follow. Networks like SimpleX and Nostr rely on users to choose servers to relay their communication, while servers seldom talk to each other. Such design could be called “Relayed Rendezvous Network”, which lack the global addressing mechanism. In Nostr, a user should choose a server first to discover, follow and interact with other users who choose this server, and two users without their chosen servers overlapping are even unable to discover each other. On SimpleX, a user without an working “contact queue” published is also unable to be discovered, although unlike Nostr, two SimpleX users without their chosen servers overlapping can establish sessions between them, for they choose server only to open Simplex queue to receive messages (see below), and they can connect to any server to send messages.
Client-Server protocol
Simplex queue, used for one-way message transmission. For communication between two users, messages are transmitted in two directions using different queues.
The design principle is to avoid the possibility of the server permanently identifying users; only users can recognize each other’s identities.
Each queue contains two randomly generated identifiers from the servers (RID, SID) and two public keys for signing user commands (RK, SK). Users must generate a separate pair of temporary public and private keys for each queue to sign commands, in order to prevent tracking by the server.
The simplex queue is created by the receiver, who informs the sender of its details through other means. The newly created queue is in a “half-open” state, during which anyone who discovers this half-open queue can attempt to send messages to it. At this point, the receiver can try to identify the sender’s identity and lock the queue for exclusive use by the two parties; thereafter, messages from other users will be rejected by the queue.
In the new version of the protocol, the sender can also lock the queue, which introduces the possibility of a queue created by the receiver being accessed by an unsolicited sender, rather than the expected sender locking it. Therefore, whether to allow the sender to lock the queue is controlled by the receiver at the time of queue creation.
The simplex queue is represented by a queue URI, which includes the server address, port, TLS certificate fingerprint, queue number, and the receiver’s queue public key. This public key is used solely for decrypting messages in the queue and not for long-term identification of the receiver’s identity
End-2-End protocol
The basic way for two clients to establish a connection is through an “invitation”—Alice opens a queue on her chosen server that allows the sender to lock it, appending her end-to-end encrypted handshake information to the queue URI, forming the “invitation URI,” which she then communicates to Bob through other means. After Bob completes the end-to-end encrypted handshake, he opens his own queue on his chosen server and sends his invitation URI as the first message (encrypted with both end-to-end and queue public keys) to Alice’s queue, locking Alice’s queue in the process. After Alice decrypts the first message, she connects to and locks Bob’s queue.
Clients can also open a “contact queue” on the server that does not allow the sender to lock it, so that other senders can send their invitation URIs to the queue (which will still be encrypted with the queue’s public key, so the server cannot know the identity of the sender). Closing the contact queue does not affect already established sessions.
The end-to-end encryption protocol of Simplex is a customized X3DH-Double Ratchet protocol, using a “secure code” similar to Signal to verify the consistency of the session.
Issues in protocol design
Server
The simplex server does not authenticate the identity of clients (it only allows private servers to use passwords to block unintended users’ connections). Therefore, malicious users can easily carry out denial-of-service attacks on public servers by opening a large number of queues and then ignoring them, consuming the server’s resources and preventing normal users from creating queues on that server.
Client
Unlike federated networks such as email, XMPP, and Matrix, Simplex lacks a global addressing mechanism, which means that two clients cannot establish a connection unless they invite each other through “out-of-band” methods. Even if a “contact queue” is used to accept invitations, this queue can be closed at any time, after which others will no longer be able to contact the user through the original queue.
Moreover, even when using the same contact queue to accept invitations, the security codes for multiple sessions obtained from the same pair of clients can be completely different. This indicates that Simplex’s “security code” does not serve to prove the user’s identity as it does in Signal, and it is likely that a separate public key is created for each session. As a result, without the pre-existing “out-of-band” methods, Simplex users have no means to verify the identities of other users.