How TanMesh works

A high-level walk-through of identity, Tor routing, session setup, and message protection inside TanMesh — without exposing any internal code.

Identity

Static X25519 identity & node_id

When you first start TanMesh on a device, it creates a long-term X25519 keypair that belongs only to that device. From this keypair TanMesh derives a compact identifier called your node_id.

The node_id is:

  • Stable across restarts on the same machine.
  • Tied cryptographically to your long-term public key.
  • Used to verify that you are really talking to the expected contact, not an impersonator.

A few important points about identity in TanMesh:

  • Local only: Identity is stored locally in TanMesh’s private app directory on your machine.
  • No central registry: TanMesh does not phone home or register your identity with any server.
  • Integrity checks: On each launch, TanMesh re-derives and checks the identity information to detect tampering.
  • Share only what you want: You choose which friends or contacts see your node_id and onion address.

Transport

Tor v3 onion services as a transport layer

TanMesh is designed to work as a Tor-routed messenger by default. Instead of exposing your IP address to other peers, it uses a Tor v3 onion service to receive incoming connections.

On start, TanMesh:

  • Sets up a private Tor data directory for this node.
  • Starts a local SOCKS proxy that only TanMesh uses.
  • Creates an onion address that forwards traffic to the TanMesh listening port on 127.0.0.1.

Once Tor has bootstrapped:

  • Your unique onion address (for example nz6kflcryrmhd…onion) becomes your rendezvous point on the network.
  • Friends connect to you through this address; neither side sees the other’s real IP.
  • You can optionally turn off the embedded Tor and tell TanMesh to use a system-level or gateway Tor instance via environment variables, if you prefer a custom setup.

Crypto engine

Session setup & shared secrets

When two TanMesh peers connect (over Tor or, if you choose, directly), they build a fresh encrypted session between their long-term identities.

At a high level:

  1. Each side creates a temporary X25519 keypair just for this session (ephemeral keys).
  2. They exchange a small handshake that includes:
    • their node_id,
    • display name,
    • long-term public key,
    • and ephemeral public key.
  3. Using the long-term and ephemeral keys on both sides, TanMesh performs several Diffie–Hellman operations to create a pool of shared secret material.
  4. This material is passed through HKDF (HMAC-based Key Derivation Function) to derive:
    • a root key for the session, and
    • two separate chain keys — one for each direction of communication.

Directionality is important: TanMesh makes sure that what you send and what you receive are protected by different keys. This prevents subtle attacks that exploit symmetric reuse of keys in both directions.

Session rekeying is supported too. At any time, either side can trigger a refresh of the ephemeral keys. The existing root key is then used as input to derive a completely new set of chain keys, giving you forward secrecy across the lifetime of the conversation.

Messages

Per-message keys, padding & framing

Once a session is established, every message you send is encrypted with its own fresh key derived from the appropriate chain key.

For each outgoing message, TanMesh:

  • Advances the chain key using HKDF.
  • Derives a unique message key from that updated chain key.
  • Collects the message content and metadata into a small JSON payload.
  • Prefixes the payload with its length and pads the result to a fixed boundary so attackers cannot easily estimate the true size of the message.

The padded message is encrypted using AES-GCM with:

  • a random 96-bit nonce,
  • the per-message key derived from the chain, and
  • the message counter used as associated data to bind the ciphertext to its position in the stream.

The receiver keeps its own counter and chain key. If a frame arrives out of order, TanMesh can detect this and refuse to process it, tightening the protocol’s attack surface.

Architecture

One engine, multiple frontends

TanMesh keeps the cryptography and networking in a single, audited engine and lets you interact with it either via CLI or a modern desktop UI.

  • Engine: An asynchronous core handles Tor integration, peer discovery, secure handshakes, and message encryption/decryption.
  • Event bridge: A lightweight, thread-safe event queue forwards high-level events (like “peer connected” or “new message received”) from the engine to whichever frontend you are using.
  • Frontends: You can run TanMesh in a terminal-first CLI mode, or use the Qt GUI that presents peers, chats and contacts in a polished desktop interface.

This separation has a few advantages:

  • Security: All sensitive crypto and network logic stays concentrated in one place rather than being scattered across UI code.
  • Portability: The same engine can power new frontends in the future (for example, mobile or web shells) without rewriting core security logic.
  • Reliability: The engine can continue running even if a UI component misbehaves, and vice versa.

In short: TanMesh behaves like a small, dedicated secure messaging engine that you can drive from different user experiences, without ever exposing the underlying implementation details to casual onlookers.