Skip to content

Repository files navigation

Tessera

Open-source zero-knowledge identity: an OPAQUE asymmetric PAKE core plus a client-encrypted vault. Your password never reaches the server — not even hashed — and the key that encrypts your account data is derived on your device and never leaves it.

This repository (ciphera-net/tessera) is the Rust core: the OPAQUE cipher suite, the tessera-sidecar binary that runs the server side of the handshake, the cross-language conformance kit, and the specification & audit documents. It powers Ciphera ID, and it is built to be self-hosted and adopted by anyone.

Note

Security status: self-reviewed; not yet independently audited. Tessera has had a rigorous internal self-audit (see docs/SELF-AUDIT.md). Read docs/SPEC.md and docs/THREAT-MODEL.md, and review the code, before relying on it for anything critical.

What it provides

  • OPAQUE authentication — the password is never sent to the server in any form. Login is a cryptographic proof of knowledge; the server stores only an opaque registration record.
  • Client-encrypted vault — account data (e.g. email, profile) is sealed on the device under a Vault Master Key (VMK) the server never holds; the server stores only ciphertext.
  • Recovery & re-key — VMK-wrap envelopes (password, recovery phrase, passkey/PRF) let users recover or rotate credentials without the server ever seeing key material.
  • Blind index — accounts are looked up by an irreversible keyed hash of the email, so the server can find an account without storing the address.
  • Sealed login state — the in-flight server state for a login is handed back to the caller as ciphertext, so any process holding the same ServerSetup can finish a login another one started. The sidecar stays stateless and needs no database of its own.

Cryptographic suite (v1, suite byte 0x01)

Component Choice
OPAQUE RFC 9807 configuration #1
OPRF ristretto255-SHA-512
Key exchange 3DH (TripleDH)
KSF (key-stretching) Argon2id, v0x13, m = 64 MiB, t = 3, p = 1 (pinned, client-side)
Vault / VMK-wrap AES-256-GCM with HKDF-SHA-256, AAD-bound to a version + context

Parameters are pinned (not library defaults) and verified byte-for-byte across the Rust, Go, and TypeScript implementations by the conformance kit. All primitives are delegated to vetted libraries (opaque-ke, curve25519-dalek, argon2, sha2); the crate is #![forbid(unsafe_code)] and contains no hand-rolled cryptography.

The Tessera repos

Repo What
ciphera-net/tessera (this repo) Rust OPAQUE core + tessera-sidecar + conformance kit + docs
ciphera-net/tessera-go Go server SDK
ciphera-net/tessera-ts (@ciphera-net/tessera) Browser SDK (WASM OPAQUE + WebCrypto vault)

Add it to your project

Published on crates.io:

cargo add ciphera-tessera

The library is exposed as the tessera crate (use tessera::…); the server-side handshake binary is tessera-sidecar. To build from source instead, see below.

Build & test

cargo build --release          # builds the library + the tessera-sidecar binary
cargo test                     # unit + integration (real-socket round-trip) tests
cargo fmt --check && cargo clippy --all-targets

Running the sidecar

tessera-sidecar answers the server side of the OPAQUE handshake over a Unix socket. It requires a ServerSetup (the long-term OPRF secret), which you generate once per deployment and provide at startup from your own secrets manager:

# Generate once; store the output in your secrets manager. Keep it 0400 and OFF the repo.
tessera-sidecar gen-setup /path/to/server-setup.bin

# Run the socket server: serve <socket> <setup-path>
tessera-sidecar serve /run/tessera/tessera.sock /path/to/server-setup.bin

Optional tuning via env vars: TESSERA_FRAME_DEADLINE_MS, TESSERA_LOGIN_TTL_MS, TESSERA_MAX_CONNECTIONS.

Running more than one sidecar

A login is two requests — login_start and login_finish — and the server state between them has to live somewhere. Historically it lived in the sidecar's memory, which quietly made those two requests inseparable from one process: a second replica could not finish a login the first one started, and a restart killed everything in flight.

login_start now also returns state_b64, that state sealed with XChaCha20-Poly1305 under a key derived (HKDF-SHA512) from your ServerSetup. Store it wherever you already store the login_id, and pass it back to login_finish:

login_start  -> { login_id, response_b64, state_b64 }
                  store (login_id -> state_b64) in your datastore
login_finish <- { login_id, finalization_b64, state_b64 }

Your datastore holds ciphertext it cannot open, and every replica that loads the same ServerSetup derives the same key — so any of them can finish any login. This is the only supported way to run more than one replica. Omitting state_b64 selects the legacy in-memory path, which is deprecated and only works against the process that served login_start.

Sealed state expires after TESSERA_LOGIN_TTL_MS (default 60s) and is bound to its login_id, so it cannot be replayed against a different login. It is not single-use on its own — consume your own login_id record exactly once (e.g. a Redis GETDEL) to prevent replay.

An expired, tampered-with, or mismatched state all return the same unknown_login error code, deliberately without distinguishing which. Treat that code as "this ceremony is over, start a new one" — not as a failed password. Counting it as a credential failure means a correct password can accrue account lockouts.

The ServerSetup is the only long-term server secret. It must never be committed to source control — .gitignore excludes *.bin / server-setup* as a guard. Treat its loss/exposure the way you would any root key.

Documentation

See docs/: SPEC, THREAT-MODEL, SELF-AUDIT, PARITY, DEPENDENCIES, AUDIT-SCOPE, and SECURITY.

Security

Please report vulnerabilities per docs/SECURITY.md (responsible disclosure to security@ciphera.net). Do not open public issues for security reports.

License

Licensed under the Apache License, Version 2.0. You may self-host, modify, and redistribute it, including in proprietary products, subject to the license terms.

Export notice

This distribution includes cryptographic software (OPAQUE / ristretto255 / Argon2id / AES-256-GCM). It is published as open-source, publicly-available software. Under EU Regulation (EU) 2021/821 (the dual-use recast), software that is "in the public domain" / publicly available is generally outside the scope of export controls. Your own local laws may still apply to your use.

About

Tessera — open-source zero-knowledge identity (OPAQUE) SDK

Topics

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages