A distributed, fault tolerant anonymous chat messaging system, implemented as a generic Rust library and GUI chat client.
Based upon the Raft consensus algorithm and Shamir's secret sharing scheme, this allows any pair of peers to communicate privately, without leaking information about the contents of their messages or identities to any other client or even servers, while being tolerant to omission faults/crashes.
Created as part of a distributed algorithms course at the Hebrew University of Jerusalem.
-
See this diagram which summarizes the design of the program, or the below section
-
See this file for a more detailed introduction and theoretical analysis
From previous assignments:
-
For recap of Raft implementation, see this file
-
For recap of crash tolerant anonymous, public chat service, see this file - currently not very accurate or relevant.
The project is based on several components that were implemented and tested independently, and are layered on top of each other in order to provide the required functionality of omission-tolerant, anonymous 2 way communication between clients.
-
Consensus
Implemented via Raft, consists of mostly server logic (the Raft protocol) as well as a client module allowing to submit values, as well as being notified whenever a value is committed to the state machine.
-
Anonymous public chat
On the server's side, implemented as a state machine on top of Raft, allowing client crash tolerance and server omission tolerance.
This component will be modified in this project in order to allow server omission tolerance, via the use of PKI. This means that a client submits all shares of all channels via a single message, such that each share is encrypted via the corresponding server's public key. Those shares are replicated via the Consensus module, thereby ensuring from this point on, the value will be recoverable by all valid servers. Each server decrypts the shares intended for him, and is unable to decrypt shares of other servers, thereby ensuring secrecy.
Once the secret is recovered, the servers broadcast the value to all clients.
-
Anonymous 2 way chat
This will be implemented on top of the public chat, by using encrypted messages as values. When client
X
sends a messageM
to clientY
, once it is recovered by the servers, it will be broadcast to all clients (after all, due to anonymity, they cannot tell to who it is intended, so broadcast is their only option). Every client will try to decipher it via his private key, and onlyY
will succeed.In addition to
M
, there will also beX
's identifier which allowsY
to respond to him. (If we wantX
to remain anonymous toY
, we can use a randomly generated symmetric key instead, and have that key re-generated wheneverX
wishes to start a new communication channel withY
)Note how the servers don't have any further logic beside what was described in 2, their mere role is basically forwarding messages between clients, and use secret-sharing in order to anonymize them
This project was tested on Windows & Linux, compiled via Rust 1.50 and running the client requires a graphical environment.
-
If you don't have Rust, install the latest stable version. The recommended way of installing Rust is via Rustup
-
Compile the project by running
cargo build --release
Note, there are major performance differences between the debug and release builds, and this effect is multiplied when you run multiple instances of a server. Running in debug build requires higher timeouts, otherwise there'd be no progress at all (servers wouldn't be able to process shares fast enough before having to proceed to the next round) -
Generating keys & certificates:
-
Run
cargo run --release --bin cert_gen --num_servers 5 --num_clients 50
to generate public & private key-pairs for 5 servers and 50 clients -
For TLS, run
cd certs ./gen.sh
(this requires a linux environment & an up-to-date openssh installation)
to generate a self signed CA and use it to create keys & certificates for the servers
Alternatively, you can use the
--insecure
flag in the runner & run scripts(see below) to disable TLS.
-
-
To run either a client or a server, see documentation under
cargo run --release --bin runner -- --help
(All arguments to the chat client/server appear after
runner --
, the arguments beore that belong to thecargo
program)There are also scripts for Windows & Linux which start several servers and clients :
-
On Windows, Window Terminal is required, simply compile the project and then run
./start_servers.ps1
from the project root -
On Linux, tmux is required, simply compile the project and then run
./start_servers.sh
from the project root.
-