Skip to content

Repository files navigation

notary

libID does not implement notarization itself. It relies on TLSNotary and its upstream tlsn implementation for the notarization protocol and cryptography. This repository is a thin integration wrapper that retains completed attestations for retrieval and exposes the HTTP/WebSocket server used by browser clients, including ProxyMode support. We are grateful to the TLSNotary contributors for building and sharing the excellent protocol that makes this service possible.

The libID notary service. One binary, one signing identity, two duties:

  • Platform session notarization — the notary acts as the MPC-TLS or ProxyMode (zkTLS) verifier for a prover's HTTPS session with a platform API (X, GitHub, …) and signs what was proven: tlsn attestations, EVM-ready transcript proofs, and on-demand token / user-identity attestations whose digests on-chain verifiers recover.
  • Notarized JWKS readings — the notary co-fetches Google's OIDC signing keys (https://www.googleapis.com/oauth2/v3/certs) over MPC-TLS and signs a JwksRotationProof that a JwksOracle contract accepts, so an on-chain OIDC verifier can rotate Google's keys without trusting the submitter.

Both duties share one TCP listener: the notary verifies the MPC-TLS session first, then dispatches on the TLS-certificate-verified server name. A session with www.googleapis.com is answered with the JWKS proof shape; every other session with the platform proof shape. The notary's signature alone registers nothing — on-chain verifiers recover it against the notary public key served at /info.

Endpoints

TCP wire protocol on NOTARY_PORT (default 7047) — length-prefixed JSON after MPC-TLS, for Rust backend provers.

HTTP / WebSocket on NOTARY_WS_PORT (default 7048) — tlsn-js compatible:

Route What it does
GET /info {version, publicKey} — compressed SEC1 notary public key, hex
POST /session Create a session → {sessionId} (503 above NOTARY_MAX_SESSIONS)
WS /notarize-proxy?sessionId= ProxyMode (zkTLS) verifier session — the primary browser path
WS /notarize?sessionId= MPC-TLS verifier session (tlsn-js fallback path)
GET /evm-proof/{sessionId} Long-poll the finished session's NotaryResponse
GET /zk/proxy/attestation/{sessionId}?session_type=token|me&… On-demand signed token / user-identity attestation
WS /proxy?token=<host> Raw WS↔TCP relay for the tlsn-js MPC path
WS /notary Legacy TCP-over-WS path

Sessions live at most 30 minutes; a background sweep evicts anything older, fetched or not.

Configuration

Flags or environment variables:

Flag Env Default Meaning
--host NOTARY_HOST 127.0.0.1 Bind address
--port NOTARY_PORT 7047 TCP wire port
--ws-port NOTARY_WS_PORT 7048 HTTP/WS port (0 disables)
--signing-key SIGNING_KEY Hex secp256k1 key, or kms:<key-id-or-alias> for AWS KMS
--chain-id CHAIN_ID 31337 Chain the attestations target (digest domain separator)
--x-zk-verifier-address X_ZK_VERIFIER_ADDRESS ZK verifier contract recovering token/me attestations
--verifying-contract VERIFYING_CONTRACT_ADDRESS zero address Contract recovering the MPC-TLS digest (Registry, or GitHubIdentityVerifier in identity deployments). Legacy alias: --registry-contract-address / REGISTRY_CONTRACT_ADDRESS
--platform-name NOTARY_PLATFORM_NAME api.x.com TLS server identity ProxyMode sessions must present
--max-sessions NOTARY_MAX_SESSIONS 1024 Concurrent-session cap
--jwks-enabled NOTARY_JWKS_ENABLED true Serve JWKS notarization sessions on the TCP listener

With a KMS key the private material never enters the process: every signature is a kms:Sign call, including tlsn attestations (the sign step is lifted out of tlsn and applied asynchronously, byte-identical to tlsn's own signer).

Docker

Released images are published to GitHub Container Registry:

docker run --rm \
  -p 7047:7047 -p 7048:7048 \
  -e NOTARY_HOST=0.0.0.0 \
  -e SIGNING_KEY=<hex-or-kms:…> \
  -e CHAIN_ID=1 \
  -e X_ZK_VERIFIER_ADDRESS=0x… \
  -e VERIFYING_CONTRACT_ADDRESS=0x… \
  ghcr.io/libid-org/notary:latest

Tags: <version> and latest on every release; custom-<suffix> images can be built from any ref via the Custom Docker image workflow (inputs: ref, tag-suffix).

Browser wasm bundle

Each release also ships tlsn-wasm-<version>.tar.gz as a release asset: tlsn_wasm.js, tlsn_wasm_bg.wasm and spawn.js, built from upstream TLSNotary's crates/wasm at the exact tlsn revision this server pins — prover and notary can never drift onto different protocol versions. Serve the three files side by side (with a rewrite of /:path+/spawn.js to the root copy) and the bundle is a drop-in for tlsn-js-style workers; unlike the npm tlsn-js build it includes set_progress_callback.

To build locally: ./scripts/build-tlsn-wasm.sh --out <dir> (needs rustup, wasm-pack 0.15.0, and a clang with a wasm32 backend — the script explains exactly what is missing if something is).

Library use

The crate also builds as a library. notary::jwks exposes the prover-side helpers a backend rotation listener needs:

  • jwks::prover::notarize_jwks(socket) — run the MPC-TLS JWKS prover against a notary's TCP port and get back the signed JwksRotationProof.
  • jwks::mock::MockProver — build a structurally identical proof without MPC (zeroed handshake fields, real signature) for contract testing.

Shared primitives (digests, wire protocol, transcript math, signers) come from libID-rs.

License

MIT or Apache-2.0, at your option. See LICENSE-MIT and LICENSE-APACHE.

About

The notary binary and zkTLS helpers.

Resources

Contributing

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages