Architecture, animated
A message in TalX always goes through the same five steps on the device itself – and then looks for the first path that carries. The diagram shows both. Pick a delivery path above to see when it applies.
1 NearbyBluetooth + Wi-Fi Direct, no internet at all
Google Nearby Connections spans a P2P_CLUSTER mesh. Two devices within radio range exchange chunks directly – no router, no mobile network, no server. Call signalling travels this way too.
- no internet needed
- range ≈ Bluetooth/Wi-Fi Direct
- same ciphertext as everywhere
2 Local networkmDNS discovery and a direct TCP connection
On the same (W)LAN each device announces itself via mDNS/NSD and the other side connects straight over TCP. Length-prefixed frames, a 512 KB cap per frame, a HELLO purely for matching. Delivery in seconds, entirely serverless – voice and video calls included.
- serverless at home
- calls without a relay
- delivery in seconds
3 WebRTC P2PA direct internet connection between the devices
Over the internet TalX opens a WebRTC data channel directly between both devices (DTLS). The relay only brokers the connection details – and those are themselves already end-to-end encrypted. The payload takes the direct route.
- device to device
- DTLS on top of the E2E layer
- TURN only behind strict NAT
4 RelayStore-and-forward fallback when nothing else works
If the contact is offline the relay accepts the ciphertext, holds it for up to seven days and delivers it on the next connection. It only ever sees ciphertext – it can neither read nor alter anything. Optionally a contentless push signal wakes the target device.
- sees ciphertext only
- buffered max. 7 days
- self-hostable
All paths at once how TalX actually decides
TalX tries the paths in order: Nearby first, then the local network, then a direct WebRTC connection, and the relay last. The first path that carries wins – and that exact path is later shown as a small symbol on the delivered message. If nothing works, the content stays in the encrypted outbox and is retried on every new connection.
- Order: Nearby → LAN → WebRTC → relay
- Delivered means: an ACK came back, not “sent”
- The path used is readable on every message
The layer that never changes
Section titled “The layer that never changes”Whichever path is chosen, what leaves the device is already finished ciphertext. No transport holds a key, none can read anything, and none can alter anything unnoticed.
-
Plaintext is created in the app. Text, photo, video, file, voice message – all of it is bundled into one content envelope. Files sit inside it as Base64.
-
Compress, and do it first. DEFLATE runs before encryption, because ciphertext is random and cannot be packed any further. That saves 60–80 % of radio volume on text and around 25 % on media. Anything that would grow through compression is sent uncompressed and marked accordingly.
-
Derive a key. For one-to-one chats the Double Ratchet supplies a fresh message key – a new one for every single message. In groups it comes from the sender’s own sender-key chain. An ML-KEM-1024 secret is additionally mixed into the root key.
-
AES-256-GCM. Encrypt and authenticate in one pass. A single altered bit makes the check fail – the message is then discarded rather than half displayed.
-
Cut into pieces and queue. The ciphertext travels in chunks of around 18 KB – at most 8192 of them per transfer, which caps the receive buffer. The entry stays in the encrypted outbox until a confirmation comes back from the recipient.
What “delivered” actually means
Section titled “What “delivered” actually means”The tick on your own message does not appear when you send it, but only once the other device has confirmed receipt. Until then it says “waiting for delivery” – even if the bytes left the radio long ago.
In groups there is a separate queue entry per recipient. The tick arrives only once no entry is left open, meaning everyone has confirmed. That is deliberate: previously the very first confirmation from any single member set the tick – which looked like “everyone has it” and hid genuine losses.
The relay – and what it sees
Section titled “The relay – and what it sees”The relay is the last fallback. It accepts messages even when the recipient is offline, holds them for up to seven days and delivers them on the next connection. Without it both devices would have to be online at the same time.
| What the relay receives | What it can do with it |
|---|---|
| Ciphertext (AES-256-GCM) | nothing – no key, no reading, no undetected tampering |
| Sender marker in the chunk | changes per transfer – two messages from the same sender are not recognisable as related by third parties |
| Registered connection | the operator sees which identifiers communicate with each other, and when |
| Push wake-up | carries no content – the app fetches the message itself, encrypted |
The sender marker is an HMAC over the transfer identifier, computed with the shared key. Only the intended recipient can attribute it. That protects against third parties – a stranger’s device within radio range, someone reading the payload at the relay.
Against the relay operator it does not help: to receive messages at all a device has to be registered there, and every delivery is tied to that registration. Anyone who wants to rule that out too runs their own relay or uses TalX purely offline over the short-range paths.
What sits where at rest
Section titled “What sits where at rest”| Location | Protection |
|---|---|
| Messages, contacts, groups | SQLCipher (AES-256); the passphrase lives only in the Android keystore |
| Attachments in app storage | AES-256-GCM with a key of its own |
| Identity, prekeys, ML-KEM pair | derived from a hardware-wrapped master secret |
| Master secret | Android keystore, StrongBox preferred, TEE otherwise |
| Cloud backup | AES-256-GCM, key derived from the passphrase with Argon2id, second factor required to restore |
A copied data folder, a backup or a stolen switched-off device are therefore worthless: without the secure element of that specific device the master secret cannot be unwrapped – and without it, none of the others can either.
Why exactly one master secret
Section titled “Why exactly one master secret”Originally eight secrets sat individually in the hardware keystore. On StrongBox devices a single keystore operation costs roughly two seconds; the two that are unavoidable at start-up alone added up to about 4.4 seconds of a 7.8-second cold start.
Today exactly one master secret stays hardware-wrapped. All the others are derived from it via HKDF and wrapped in software – one StrongBox operation per process instead of one per secret. The hardware binding is fully preserved: anyone who could invoke the wrapping key in the keystore could already open every individual secret before.
Backwards compatibility as a promise
Section titled “Backwards compatibility as a promise”Every chunk carries its sender’s protocol version. TalX remembers the last version it saw from each contact and uses that to decide which features may be used. While the version is unknown it sends conservatively, in the oldest format.
The promise: sending and receiving stay compatible across at least ten app versions. New features are only available between devices that both know them; older counterparts automatically get the variant they can read. Unknown content types are silently ignored on receipt rather than shown as an empty message.
