piech.dev

Back to Projects github.com/Tenemo/threshold-elgamal

threshold-elgamal

npm version npm downloads


CI Tests coverage Documentation build


Node version License


threshold-elgamal is a browser-native TypeScript library for verifiable score-voting research prototypes. The shipped 1.0.0-beta line centers on additive ElGamal over ristretto255, threshold decryption, typed protocol payloads, authenticated share transport, and log-driven GJKR DKG.

The library is intentionally library-only. It stays pure, deterministic, synchronous, and Worker-safe. WebSockets, retries, persistence, bulletin-board storage, and application orchestration remain outside the package.

The cryptographic backend uses @noble/curves and @noble/hashes where appropriate, plus Web Crypto for randomness, signatures, key agreement, and AES-GCM envelopes.

This library is a hardened research prototype. It has not been audited.

The current beta line supports:

Start with these guides:

What the library includes

Installation

pnpm add threshold-elgamal

Runtime requirements

Performance model

Quickstart

import {
    addEncryptedValues,
    decryptAdditive,
    deriveH,
    encryptAdditive,
    generateParameters,
} from "threshold-elgamal";

const { publicKey, privateKey } = generateParameters();
const messageBound = 10n;
const tallyBound = 20n;

const left = encryptAdditive(6n, publicKey, messageBound);
const right = encryptAdditive(7n, publicKey, messageBound);
const sum = addEncryptedValues(left, right);

console.log(decryptAdditive(sum, privateKey, tallyBound)); // 13n
console.log(deriveH().length); // 64 hex chars

The shipped canonical suite is implicit and fixed to ristretto255.

Choosing additive bounds

For the shipped voting path, each score is in 1..10. If you tally 50 ballots, encrypt each ballot with 10n and decrypt the final sum with 500n.

Protocol defaults

For end-to-end verification, the root package exposes verifyElectionCeremonyDetailed(...). It verifies the manifest, registrations, acceptances, DKG transcript, local joint-key derivation, ballot proofs, locally recomputed per-option aggregates, decryption shares, tally publications, and board-consistency digests in one pass.

Documentation

Beta-line notes

The current beta line intentionally standardizes the shipped workflow on Ristretto255, additive-only tallying, fixed 1..10 score voting semantics, and the renamed manifest fields reconstructionThreshold and minimumPublishedVoterCount.

That means the current beta API and wire format should be treated as a reset relative to earlier finite-field beta fixtures and examples. Regenerate vectors and re-sign manifests when moving old experiments onto this line.

Development

pnpm install
pnpm run ci

DKG benchmark

For the recommended default regression benchmark, run:

pnpm run bench:dkg -- --group=ristretto255 --transport=X25519 --options=3 10

Benchmark results depend heavily on device class and browser/runtime overhead. Treat the current all-to-all DKG path as a readiness spot check for 10 participants, not as evidence that the symmetric all-equal flow is suitable for large ceremonies.

License

This project is licensed under MPL-2.0. See LICENSE.