Mandated voting.
The need behind Operation D: a voter, or a mandate-holder who voted on someone's behalf, demonstrates after the fact how a ballot was cast.
Proving that a published ballot is your own without revealing your secret key, but revealing your vote: cryptoVote Operation D and the cvproof/1 envelope that carries it.
This page specifies the vote proof used by the public tools: what it establishes, who can produce it, the nonce flow, the exchanged envelope field by field, and how it is verified. It is deliberately explicit about the consequences: a proof handed over is a disclosure of the vote, checkable by anyone and impossible to take back.
Protocol v1
A published ballot carries an election-scoped key image, never an identity. The proof ties that key image to a public key, and so to whoever holds the matching secret key.
∃ x : P = x·G and I = x·B B = H_p(domain ‖ len(election_id) ‖ election_id ‖ P)
Ristretto255, Blake2b-512. B is the base the ballot derives its key image from: the same secret key yields a different key image in every election.
Producing a proof requires the voter's secret key. No one can therefore prove a voter's ballot on their behalf, or against their will.
The need behind Operation D: a voter, or a mandate-holder who voted on someone's behalf, demonstrates after the fact how a ballot was cast.
Three roles, three cryptoVote calls. The nonce is generated by whoever asks for the proof, never by the voter.
The nonce is folded into the proof's challenge: it cannot be precomputed or replayed under another nonce, which assures the requester it was produced for their request. But it stays publicly checkable: whoever holds the pair (nonce, proof) can convince anyone else. It is not a designated-verifier proof, and nothing restricts it to the requester alone.
A single UTF-8 JSON object, the only interchange format the tools produce or accept. It concerns the voter and the requester only: no server-side parser, no storage.
version
string literal
election
UUID
public_key
pk_<64 hex>_<8 hex>
key_image
ki_<64 hex>_<8 hex>
nonce
nonce_<64 hex>_<8 hex>
proof
own_<128 hex>_<8 hex>
{
"version": "cvproof/1",
"election": "1f0c9b6e-4d2a-4c8e-9b7a-3e5f6a7b8c9d",
"public_key": "pk_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef_a1b2c3d4",
"key_image": "ki_fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210_0badc0de",
"nonce": "nonce_00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff_5eed5eed",
"proof": "own_0f1e2d3c4b5a69780f1e2d3c4b5a69780f1e2d3c4b5a69780f1e2d3c4b5a69780f1e2d3c4b5a69780f1e2d3c4b5a69780f1e2d3c4b5a69780f1e2d3c4b5a6978_c0ffee00"
}
Illustrative values: exact shapes and lengths, but made-up patterns and checksums. This envelope does not verify.
The procedure for whoever receives an envelope. A valid proof alone says: this public key owns this key image. Only the register cross-check turns it into: this voter cast this published ballot.
The proof standardises a receipt that was already provable. It is not a privacy feature, and its effects are final.
The public vote-proof tools implement this specification: generate a nonce, prove my vote, verify a proof. No account, no setting, always available; in practice verification assumes a closed election with a published register, even though the cryptography does not depend on the election's lifecycle.