Every participant is identified by their Ethereum address. A contract is used to store simple and small events on blockchain. All data that is transferred between clients is stored on Swarm.
Alice and Bob want to communicate. Bob generates his Signal pre keys and stores them on Swarm Feed, under predefined topic (step 1).
Alice uses one of Bob's pre keys to initiate Signal session (step 2). She encrypts her message and uploads it to Swarm (step 3). She takes Swarm hash of her message, encrypts with the same key, that she encrypted her message and posts it on Ethereum contract as event (step 4).
To make it clear: data posted on Ethereum is an encrypted checksum of encrypted message. The encryption key is unique for every message. The only thing publicly known is who sent it (Ethereum address) and when.
Bob watches for new events on Ethereum contract. He tries to decrypt every one of them with all keys he has (step 5). He knows if decryption was successful by using HMAC code (it's posted on Ethereum contract together with encrypted Swarm hash). With decrypted Swarm hash, he downloads his message and decrypts it (step 6).
At any moment anyone can publish an event telling that their key is invalidated. TigerMail will refuse to send to and receive messages from such address.
In code
Everything described above is implemented in
Client
class. It has extremly simple API and it doesn't care about messages format or
content.