Jami and Tox both exist to answer a specific question: what does calling someone look like when there is no account, no phone number, and no company in the middle? Both generate a cryptographic identity locally, both find peers through distributed discovery, and neither has a registration service that could be subpoenaed.
That architectural choice is the whole point. Signal requires a phone number, which means the service operator knows every user's number and can be compelled to produce it. Jami and Tox have no such record to produce, because no server ever learns the mapping between your identity and your identity document.
The cost is usability and reliability. Both are peer-to-peer, which means calling requires the other party to be reachable — no server queues calls for a recipient who is offline. NAT traversal adds friction, and group calling is limited by the weakest participant's connection.
1. How the Protocol Protects You
Jami and Tox solve the same problem differently, and which one suits you depends on how you use it.
| Aspect | Jami | Tox |
|---|---|---|
| Identity | 40-char hex URI from a key pair | 76-char hex Tox ID from key pair |
| Discovery | Distributed hash table (OpenDHT) | Mainline DHT (BitTorrent-based) |
| Calling | Direct SIP-over-P2P to the URI | Direct audio/video between Tox IDs |
| NAT traversal | STUN/TURN where available | UDP hole punching; struggles with symmetric NAT |
| Transfer | Direct socket | Direct socket, no size limit |
| Group call | Supported for small groups | Depends on the client; limited |
| Mobile reliability | Better; handles push notifications | Poor — DHT requires an always-on client |
The mobile row is the deciding factor for most people. Tox's DHT model assumes a client that stays connected; on Android and iOS the OS suspends background apps aggressively, so calls only arrive when the app is open. Jami handles this better with push notification relays, though there is a tradeoff — a push relay learns that a call is arriving, even if not who is calling.
2. Setup Walkthrough
The verification that matters is confirming the identity is locally generated and that nothing was registered. Both are checkable from the command line.
# Jami on Linux (Debian/Ubuntu)
$ sudo apt install jami
$ jami-cli account list
# Tox - pick a client; toxcore-cli is the reference
$ sudo apt install toxcore-utils
$ tox_cli profile show
# Confirm the private key never left the machine
$ ls -la ~/.local/share/jami/*/privateKey
# Expect: -rw------- owned by your user, not world-readable
# Confirm no registration request went out during setup
$ sudo nethogs -t -c 5 2>/dev/null | grep -iE 'jami|tox'
If the private key file is group- or world-readable, fix it before doing anything else: chmod 600 privateKey. A P2P identity whose key is readable by other local users is not a private identity.
3. Configuration That Actually Matters
Both systems use self-authenticating identifiers — the URI contains the public key. That means no directory lookup exists, and it also means the exchange has to happen over a channel that cannot be tampered with.
# Compare the full identifier out of band, not just a screenshot of the QR.
# The URI's last block IS the public key fingerprint:
# jami: 8f3a9c21 b4e7d056 2a1c9f8b 3d4e5a6f 7c8b9d0e 1f2a3b4c 0d1e2f3a 4b5c6d7e
# ^^^^^^^^^ -- compare at least the first two blocks verbally
# Tox ID = public key (64 hex) + nospam (8 hex) + checksum (4 hex)
# The first 64 characters are the identity that cannot be forged.
# Practical rules:
# 1. Exchange by voice or in person when the contact matters.
# 2. The QR code is fine for convenience; verify the fingerprint once.
# 3. A Tox ID pasted into a chat app can be altered in transit - the UI
# shows a short checksum for exactly this reason. Check it.
The checksum embedded in a Tox ID is the mechanism designed for this: if a single character is altered in transit, the client rejects the ID rather than silently connecting you to an attacker's endpoint.
4. Limitations & Known Leak Paths
Both clients will happily use any available relay. Constrain that, and remove the features that reintroduce an account.
# Jami - review settings that create external dependencies
# - Disable the default TURN/STUN if you run your own or accept
# direct-connection-only calls
# - Do not link an account to a "Jami username" (the name
# registration service reintroduces a central directory)
# - Do not enable the backup account - it uploads your account
# archive so you can restore on another device
# Tox - verify no proxy is being used unless you set one
$ grep -i proxy ~/.config/tox/*.json 2>/dev/null
# Confirm no central server is contacted at startup
$ sudo ss -tunp | grep -E 'jami|tox' | grep -v '127.0.0.1'
# Android: restrict background data for the app to limit
# discovery traffic leaking to the mobile carrier
The Jami username registration feature is the one to avoid. It maps a human-readable name to your URI through a registration server, which is precisely the central directory the rest of the design avoids. Use the raw URI instead.
Frequently Asked Questions
Can Jami or Tox replace my phone number?
For voice calls with people who also run the client, yes. For reaching anyone with a regular telephone, no — neither interconnects with the PSTN. They replace a calling app, not a phone line.
Why do Tox calls fail on mobile networks?
Carrier-grade NAT on mobile networks frequently uses symmetric NAT, which UDP hole punching cannot traverse without a relay. The DHT model also assumes a persistently connected client, and mobile operating systems suspend background apps. Jami handles both better.
Is Jami's username feature really a problem?
It is a privacy tradeoff rather than a flaw. Registering a name makes you findable and requires a server holding the name-to-URI mapping — the same centralisation the protocol otherwise avoids. If convenience matters more than that, use it knowingly; if it does not, share the URI.
Sources & References
- Jami Project: jami.net — architecture and the OpenDHT discovery model
- Jami Technical Overview: docs.jami.net — account model, key generation, and call setup
- Tox Project: tox.chat — protocol and client list
- Tox Protocol Specification: toktok.ltd/spec.html — the Tox ID format and checksum
- RFC 5389 — STUN: datatracker.ietf.org/doc/html/rfc5389 — NAT traversal used by both
This VoIP client audit guide reflects what we actually observed on our test box — expect small differences with other releases, and run the verification section before considering the work finished.