Accuracy not guaranteed. Neither is Congress's. At least we're honest about it. Always verify at Congress.gov.

Leg day: Fri → Fri (28d) Recess

VoteChain Evidence Board

Cryptographic Ceremony
Diagram Board

How the four cryptographic primitives work together to provide credential issuance, ballot encryption, vote unlinkability, and threshold trust distribution.

All Primitives Verified
Primitives
4
Curve
secp256k1
Threshold
2-of-3
Hash
SHA-256
Cipher
AES-256-GCM

Credential Issuance

Blind Schnorr Signature Protocol

Four-step interactive protocol producing an unlinkable credential. The issuer never learns which voter received which signature.

Boundary: Verification Lane

Boundary: Voter Client Lane

Boundary: Issuer Service Lane

R over HTTPS 443

c over HTTPS 443

s over HTTPS 443

unblinded signature tuple

Issuer Boundary
Issuer signing service · HTTPS 443

Nonce Generator
Random nonce service · generates R for blinded challenge

Challenge Signer
Blind-sign endpoint · signs challenge c, returns scalar s

Voter Boundary
Booth browser credential client · no open ports

Blinding Step
Voter-side nonce blinding · computes challenge via alpha and beta

Unblinding Step
Voter-side unblinding · recovers unlinkable signature R' and s'

Verification Boundary
Verifier and audit functions · local equation checks

Equation Verifier
Blind Schnorr verification · checks s'G + c'PK = R'

Domain Separator Policy
Protocol context constants · binds hash to votechain namespace

Trust Distribution

Threshold Issuance (2-of-3)

Each issuer independently signs the credential. The voter aggregates t valid blind Schnorr signatures from n issuers.

I1
Federal Issuer
Manifest authority
blindSchnorrIssuance(sk₁)
I2
State Issuer
Jurisdiction authority
blindSchnorrIssuance(sk₂)
I3
Oversight Issuer
Independent verifier
blindSchnorrIssuance(sk₃)
issuer_threshold: { t: 2, n: 3 }

Voter needs signatures from any 2 of 3 issuers. No single issuer can block or forge a credential.

Vote Unlinkability

Nullifier Derivation

Deterministic one-way binding of voter identity to election, preventing double votes without revealing who voted.

Function
computeNullifier(pk, election_id)
Hash Construction
SHA256("votechain:nullifier:v1:" ‖ pk ‖ election_id)
Output
0x-prefixed hex string (Hex0x)
Deterministic Same voter + same election always produces the same nullifier
One-way Cannot reverse the hash to recover voter identity
Unlinkable Different elections produce different nullifiers for the same voter

Ballot Secrecy

ECIES Ballot-Key Wrapping

Ephemeral ECDH key agreement followed by AES-GCM encryption protects ballot content until threshold tally.

1
Ephemeral ECDH ephSk ← random shared = pk_election · ephSk
2
KDF (Domain-Separated) SHA256("votechain:poc:ecies-wrapkey:v1:" ‖ shared ‖ election_id ‖ ballot_id)
3
AES-256-GCM Encrypt iv ← 12 random bytes suite: "poc_ecies_aesgcm_v1" AAD: { election_id, ballot_id, suite }
wrapped_ballot_key iv ‖ ciphertext (base64url)
wrapped_ballot_key_epk ephemeral public key (33 bytes, base64url)

Key Custody

Shamir Secret Sharing

The election private key is split into shares using polynomial interpolation. No single trustee holds enough to decrypt.

Split (shamirSplit)

f(x) = a₀ + a₁x + ... + at-1xt-1 mod q

where a₀ = election secret, remaining coefficients are random scalars over the secp256k1 order

Combine (shamirCombine)

secret = Σ y_i · L_i(0) mod q

Lagrange interpolation at x=0 recovers the constant term. Any t shares are sufficient; fewer reveal nothing.

TypeShamirShare { x: bigint, y: bigint }
Fieldsecp256k1 scalar field (q)
Thresholdt ≥ 2, n ≥ t