Threshold Encryption Toolkit — encrypt data so no single key can decrypt it. Decryption requires
tofncommittee members.
thresh is a developer-friendly toolkit for threshold encryption. Encrypt secrets so that no single person can decrypt them — you need t of n committee members to collaborate. Think of it as a cryptographic safety deposit box that requires multiple keys to open.
Use cases: database credentials, API keys, deployment secrets, legal hold data, zero-trust architectures, confidential mempools, sealed-bid auctions.
| Concern | Without thresh | With thresh |
|---|---|---|
| Single point of failure | One leaked key = total compromise | Need t of n keys to decrypt |
| Insider threat | Any admin can read secrets | No single admin can decrypt alone |
| Compliance | "Who accessed the secret?" — no audit trail | Every decryption produces verifiable transcripts |
| Key rotation | Distribute new keys everywhere | Rotate committee members without changing the public key |
| Cross-platform | Custom crypto per language | Rust core + Node.js, Python, Go bindings (coming) |
┌─────────────────────────────────────────────┐
│ USER / APPLICATION │
│ CLI (thresh) │ Node.js SDK │ Python SDK │
└──────────────────┬──────────────────────────┘
│
┌──────────────────▼───────────────────────────┐
│ thresh-core (Rust) │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Keygen │ │ Encrypt │ │ Decrypt │ │
│ │ (SSS) │ │(ElGamal) │ │ (Lagrange) │ │
│ └──────────┘ └──────────┘ └──────────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ DKG │ │ Proofs │ │ Audit │ │
│ │(Pedersen)│ │(Schnorr) │ │ (Verifier) │ │
│ └──────────┘ └──────────┘ └──────────────┘ │
└──────────────────┬───────────────────────────┘
│
┌──────────────────▼───────────────────────────┐
│ COMMITTEE NETWORK │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ Node 1 │ │ Node 2 │ │ Node N │ gRPC │
│ │(share) │ │(share) │ │(share) │ │
│ └────────┘ └────────┘ └────────┘ │
└──────────────────────────────────────────────┘
# Generate a (3-of-5) threshold keypair
thresh keygen --threshold 3 --participants 5 -o ./keys
# Encrypt a message
thresh encrypt --key keys/committee_public_key.json --message "launch codes" -o ct.json
# Each committee member produces a partial decryption share
thresh decrypt --ciphertext ct.json --share keys/shares/share_1.json -o share_1.json
thresh decrypt --ciphertext ct.json --share keys/shares/share_2.json -o share_2.json
thresh decrypt --ciphertext ct.json --share keys/shares/share_3.json -o share_3.json
# Combine 3 shares to recover plaintext
thresh combine --shares ./shares_dir --ciphertext ct.json
# DKG ceremony (no trusted dealer)
thresh dkg init --threshold 3 --participants 5 -o ./dkg_output
thresh dkg verify ./dkg_output/dkg_transcript.json
# Audit an epoch
thresh-auditor verify-epoch --ciphertext ct.json --shares ./shares_dir --public-key keys/committee_public_key.jsonnpm install @gitsynctrade/threshimport { keygen, encryptMessage, decryptShare, combineDecryptionShares } from "@gitsynctrade/thresh";
// Generate keys
const result = JSON.parse(keygen(3, 5));
const { publicKey, shares } = result;
// Encrypt
const msg = "secret data";
const ct = encryptMessage(
Buffer.from(msg).toString("hex"),
JSON.stringify(publicKey),
1
);
// Each member decrypts
const s1 = decryptShare(ct, JSON.stringify(shares[0]));
const s2 = decryptShare(ct, JSON.stringify(shares[1]));
const s3 = decryptShare(ct, JSON.stringify(shares[2]));
// Combine
const plainHex = combineDecryptionShares([s1, s2, s3], ct);
const plaintext = Buffer.from(plainHex, "hex").toString();
console.log(plaintext); // "secret data"[dependencies]
thresh-core = "0.1"use thresh_core::{keygen::generate_keypair, encrypt::encrypt, decrypt::{partial_decrypt, combine_shares}};
let committee = generate_keypair(3, 5).unwrap();
let msg = [0x42u8; 32];
let ct = encrypt(&msg, &committee.public_key, 1).unwrap();
let shares: Vec<_> = committee.shares[0..3]
.iter()
.map(|s| partial_decrypt(&ct, s).unwrap())
.collect();
let plaintext = combine_shares(&shares, &ct).unwrap();
assert_eq!(plaintext, msg);Each committee member runs a node that holds their key share and serves partial decryption requests:
# Build
cargo build --release -p thresh-node
# Run
THRESH_SHARE_PATH=./keys/shares/share_1.json \
THRESH_PORT=50051 \
THRESH_REGION=us-east-1 \
./target/release/thresh-nodeThe node exposes a gRPC endpoint. Multiple nodes collaborate to decrypt:
service Committee {
rpc PartialDecrypt(DecryptRequest) returns (DecryptResponse);
rpc Ping(PingRequest) returns (PingResponse);
rpc NodeInfo(NodeInfoRequest) returns (NodeInfoResponse);
}docker build -t thresh-node -f deployments/Dockerfile.node .
docker run -e THRESH_SHARE_PATH=/keys/share.json \
-v ./keys:/keys \
-p 50051:50051 \
thresh-node| Primitive | Algorithm | Curve |
|---|---|---|
| Secret sharing | Shamir's Secret Sharing | BLS12-381 scalar field |
| Encryption | ElGamal-style (additive homomorphic) | BLS12-381 G1 |
| DKG | Pedersen-style (each participant contributes) | BLS12-381 |
| Share proofs | Schnorr-like NIZK of correct decryption | BLS12-381 |
| Hashing | BLAKE3 | — |
- IND-CPA secure against passive adversaries who observe ciphertexts
- Threshold security: any
t-1colluding members learn nothing about the plaintext - Share unforgeability: decryption shares include NIZK proofs
- Transcript verifiability: anyone can verify decryption correctness
- DKG soundness: no participant learns the full secret key (trusted dealer variant also available for testing)
- t of n collusion: if
tor more committee members collude, they can decrypt - Denial of service: if
> n-tmembers are down, decryption halts (escape hatch: re-share) - Side-channel attacks: implementation is not hardened against timing/power analysis
- Quantum adversaries: BLS12-381 is not post-quantum secure
| Command | Description |
|---|---|
thresh keygen |
Generate (t,n)-threshold keypair (Shamir SSS) |
thresh encrypt |
Encrypt a message under the committee public key |
thresh decrypt |
Produce a partial decryption share |
thresh combine |
Combine shares to recover plaintext |
thresh dkg init |
Run a distributed key generation ceremony |
thresh dkg verify |
Verify a DKG transcript |
| Command | Description |
|---|---|
thresh-auditor verify-epoch |
Verify all shares in an epoch are correctly formed |
thresh-auditor verify-transcript |
Verify DKG transcript integrity |
thresh-auditor audit-batch |
Batch audit multiple epochs for compliance |
# deployments/docker-compose.yml
services:
node1:
build:
context: .
dockerfile: deployments/Dockerfile.node
environment:
- THRESH_SHARE_PATH=/keys/share_1.json
- THRESH_PORT=50051
ports: ["50051:50051"]
volumes: ["./keys:/keys"]
node2:
build:
context: .
dockerfile: deployments/Dockerfile.node
environment:
- THRESH_SHARE_PATH=/keys/share_2.json
- THRESH_PORT=50052
ports: ["50052:50052"]
volumes: ["./keys:/keys"]
node3:
build:
context: .
dockerfile: deployments/Dockerfile.node
environment:
- THRESH_SHARE_PATH=/keys/share_3.json
- THRESH_PORT=50053
ports: ["50053:50053"]
volumes: ["./keys:/keys"]# Build everything
cargo build --release
# Run tests
cargo test
# Run benchmarks
cargo bench -p thresh-core
# Build Node.js bindings
cd bindings/ts && npm install && npm run build
# Lint
cargo clippy -- -D warnings
# Format
cargo fmt- Shamir secret sharing keygen
- ElGamal-style threshold encryption
- Partial decryption with Schnorr proofs
- Lagrange share combination
- Pedersen DKG ceremony
- CLI (keygen, encrypt, decrypt, combine, dkg)
- gRPC committee node
- Independent auditor tool
- Node.js NAPI-RS bindings
- Python PyO3 bindings
- Go cgo bindings
- BLS12-381 production curve (arkworks)
- Proactive secret sharing (periodic re-sharing)
- Formal verification with hacspec
- Post-quantum hybrid mode
Apache 2.0 — use it anywhere, modify it, build on it.
The Private AI Trading Infrastructure for Autonomous Perpetual Markets on Base.
| 🌐 Website | gitsync.trade |
| 📱 App | app.gitsync.trade |
| 📄 Whitepaper | gitsync.trade/whitepaper |
| 📚 Docs | docs.gitsync.trade |
| 💻 GitHub | github.com/gitsynctrade |
| x.com/gitsynctrade | |
| 📢 Telegram | t.me/gitsync |
thresh powers the privacy committee in the GitSync perpetual exchange, but the toolkit is fully general-purpose with zero crypto dependencies.