After years and years of talking about it, I’ve finally made it. Toechat is here, and it has been made with simplicity in mind from the start. In this short blog post, I’ll explain how Toechat works under the hood. For implementation-specific details, please visit the repository.
Toechat can only do two things. Send text and send files, both wrapped in XChaCha20-Poly1305. To achieve this, the following header is used:
+-----+-----+-----+-----+-----+-----+-----+-----+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 0 | Text size | File size |
+-----+-----------+-----------------------------------+
| 1 | |
+-----+ |
| 2 | Cryptographic nonce |
+-----+ |
| 3 | |
+-----+-----------------------------------------------+
The text size must always be larger than 0. If the file size is 0, the data sent after the header is interpreted as a regular text message. If the file size is larger than 0, the text is interpreted as a file name and the received data is written to that file. In every case, the data is chunked with a maximum chunk size of 65535 bytes, followed by a 16-byte MAC. In a packet with multiple chunks, the first chunk always contains text, while the rest contain the raw data of an attached file. An 8-byte large chunk would look like this:
+-----+-----+-----+-----+-----+-----+-----+-----+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 0 | Chunk |
+-----+-----------------------------------------------+
| 1 | |
+-----+ Message authentication code |
| 2 | |
+-----+-----------------------------------------------+
And that’s pretty much it. The decryption key used on messages must be shared outside of Toechat and peers must be tagged with a name manually. This improves security by making sure a bad actor can’t impersonate a recipient. Connections to peers must also be set up manually, the protocol makes no attempt at opening connections automatically.