Skip to content

Repository files navigation

zktally.github.io

The ZKTally demo site: an interactive explainer that runs a real election in the browser using zktally, showing the actual cryptographic objects at every step.

ZKTally is unaudited academic software implementing a protocol from a student research paper. It has not been reviewed by professional cryptographers and must not be used for any binding election.

The one rule

Every number on screen is real. When the site shows a ciphertext, it is the ciphertext encrypt() just produced; when it shows the homomorphic product, aggregate() computed it. A visitor can export the board, run zktally audit on it in Python, and get the same answer.

That constraint is what gives the site its value. An explainer animating plausible-looking numbers would teach the shape of the protocol while proving nothing.

Develop

pnpm install
pnpm dev
pnpm test          # unit + honesty checks
pnpm test:e2e      # Playwright, against the built site
pnpm build         # typecheck, build, and the bundle-size gate

zktally is linked from the sibling zktally-js/ checkout. Build that package first — the site consumes its dist/.

Structure

src/
├── lib/zk.ts        The single entry point into the crypto library, and the worker pool
├── lib/db.ts        IndexedDB persistence
├── lib/format.ts    Display helpers for values that are far too big to show whole
├── stores/          Pinia: the live election
├── components/      Shared UI, including the adversary panel
└── views/           One per route

Routing uses hash history because GitHub Pages has no rewrite rules — a deep link under history mode would 404 on reload.

Honesty requirements, enforced by tests

test/honesty.test.ts asserts the constraints that matter:

  • The standing disclaimer is rendered by the app shell, so it appears on every page, and prominently on the landing hero.
  • No page claims "secure e-voting" unqualified, and nothing affirms receipt-freeness.
  • The walkthrough covers what ZKTally does not protect against, and demonstrates the receipt — the visitor reconstructs their own ballot from (vote, randomness) — rather than describing it.
  • Single-authority elections carry a persistent warning that the key holder can decrypt any individual ballot, and the tally view reports such a total as asserted rather than proved.
  • Verdicts never rely on colour alone: icon and word, always.

These are tests rather than intentions because this project exists partly to correct an earlier version whose documentation claimed four security properties it did not have.

Adversary mode

The election sandbox lets a visitor attack the election and watch it fail. Each attack is one that worked against the research prototype: double voting, a forged key image, a self-made ring, a poisoned ciphertext, vote copying, and an out-of-range vote. The ballots are genuinely malicious and the rejections come from the real verifier.

Deviations from the specification

  • No gen:params script. That step exists because threshold keygen needs safe primes and cannot run in a browser, so the walkthrough would need bundled parameters. This walkthrough runs in single-authority mode at 2048 bits, which is viable live — and generating it in front of the visitor supports the "nothing is pre-computed" claim better than shipping a fixture. The UI states plainly that the mode is weaker than the protocol allows and that the resulting total is unproved. Threshold mode is exercised in the Python package's test suite.
  • No GitHub Actions workflow. Removed at the maintainer's request. pnpm check runs the same gates locally.

Privacy

No backend, no analytics, no external fonts, no CDN, no network requests of any kind after load. Elections are stored in IndexedDB and nothing is written until a visitor starts one; /about has a control that clears everything.

License

MIT. See LICENSE.

About

Interactive browser demo of the ZKTally privacy-preserving e-voting protocol, powered by zktally-js

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages