Skip to main content
T3N implements robust encryption for both data in transit and data at rest, leveraging post-quantum cryptography, Trusted Execution Environments (TEEs), and industry-standard symmetric encryption algorithms.

Encryption in transit

Client-to-node traffic

T3N uses two layers of encryption to protect data in transit:
  1. HTTPS protects the client connection to the deployment’s public load balancer.
  2. Core Session API paths add application-layer encryption. The client and node establish a shared secret with ML-KEM-768, derive directional keys with HKDF-SHA256, and encrypt payloads with AES-256-GCM.
Once the ML-KEM public key and an expected runtime measurement obtained through a trusted, out-of-band channel have been verified, the application-layer channel limits plaintext exposure to the client and the TEE. Without that verification, the client only knows that it encrypted to the key returned by the node’s /status endpoint.
In some cases (e.g., trusted B2B integrations), session-authenticated endpoints only rely on HTTPS and trusted party’s specific authentication (e.g, HMAC, EOA signatures, and bearer tokens).

Handshake

An end-to-end encrypted channel is established using ML-KEM (FIPS 203): The shared secret K is never transmitted: the client derives it during encapsulation and the node recovers it by decapsulating inside the TEE. The handshake response itself carries only the session identifier and expiry — a lookup handle with no key material — protected by HTTPS like the rest of the exchange. The node does not contact other nodes during each client handshake to jointly decrypt the ML-KEM ciphertext. Instead:
  1. During startup, the node participates in the threshold process and reconstructs/recovers the wrapping secret key.
  2. It keeps that key inside the TEE.
  3. For each handshake, it uses the already-recovered key locally.
“Threshold” protects key provisioning/recovery at startup, but handshake decapsulation itself is fast and node-local. Both client and server derive two keys from the ML-KEM shared secret:
  • t3n-session-v1-c2s: client encrypts, server decrypts.
  • t3n-session-v1-s2c: server encrypts, client decrypts.
Using different keys for each direction prevents a sender from decrypting its own outgoing ciphertext with its receive key.
Sessions are node-affine: the node that handles the handshake stores the session state in memory, and later requests in that session must return to that node.

Requests and responses

For paths that use Session API application-layer encryption, every encryption operation:
  1. Generate a fresh random 12-byte nonce
  2. Encrypt the payload with AES-256-GCM
  3. Prepend the nonce to the ciphertext
  4. Verify the authentication tag during decryption
Changing the nonce, ciphertext, or authentication tag causes decryption to fail.

Node-to-node traffic

Node-to-node traffic first uses libp2p Noise for an encrypted, peer-authenticated channel. T3N then applies a TEE protocol upgrade in which peers:
  1. Exchange fresh challenges
  2. Bind their libp2p identity to a TEE attestation quote
  3. Verify the quote and approved TEE measurements
  4. Compare a Keccak-256 digest of the cluster configuration
A peer is rejected when its quote matches no effective trusted measurement. The effective set includes the node’s own startup measurement, even when the configured allow-list is absent or empty. Raft traffic and key-recovery messages use this attested channel.

Encryption at rest

Private ledger data

T3N stores application state in named key-value collections called maps. Every committed transaction is recorded in the replicated ledger as a set of changes to those maps. Each ledger entry separates these changes into:
  • a public domain, containing changes to maps whose names start with public:
  • a private domain, containing changes to all other maps
The private domain is encrypted using AES-256-GCM with the 32-byte ledger encryption key. Each committed entry is identified by its Raft and log index. T3N encodes this pair into the entry’s unique 12-byte encryption nonce. Conceptually,
The entry’s wire header and complete public domain are authenticated but not encrypted. They remain readable, but modifying either will cause authentication to fail when the private domain is decrypted. Public maps are intentionally stored as plaintext in the replicated ledger. They must not contain personally identifiable information or other secrets.

Private binary large objects (blobs)

Content addressable storage (CAS) can be configured for storing large binary objects:
  1. Compute a SHA-256 content identifier (CID) from the plaintext;
  2. Encrypt the blob with AES-256-GCM under the CAS content encryption key (CEK);
  3. Store the blob under the CID-derived object key; and
  4. Store a ValueRef in the KV map.
ValueRef records the CID, size, storage location, encryption status, and last-touch time. On read, T3N decrypts encrypted blobs and verifies that the plaintext hash matches the CID.

Quick reference