In New Democratic Primary, we have ZK Signatures of every passport that participates. Those signatures include a public commitment to the associated link_auth, which is generated randomly on SIV's server just after the encrypted vote is received.
One of the goals of this election was to be able to say:
this vote is truly trustless, even the operator cannot make up votes
We can't forge passport proofs. Anyone can verify them independently for themselves.
And then with SIV Shuffle proofs, and Partial Decryption proofs, anyone could trace the passport_proofs -> shuffle_proofs -> decryption_proofs -> unlocked final results. Verifiable, yet still privacy protecting the whole way through.
But...
One hole in the "complete" independent verification.... the passport proof commits to the link_auth but not the encrypted vote content itself.
So for example, we could switch in our own fraudulent encrypted votes, but claim they're still from the link_auths that were committed to. (Not that we have any interest in doing this, of course. But even better to be able to prove that didn't happen.)
One solution: have link_auth itself be verifiably tied to the encrypted vote content.
E.g. hash the whole encrypted vote when it's received, and use that as a seed for deterministic PRNG to make link_auths.
Would still be unique, because encrypted votes are effectively unique— each selection has 1/2^256 chance of same randomizers.
Then, any subsequently auth steps are much easier to prove tied to that voter's specific vote selections.
In this case it was the passport_proof, but the same could be true for other auth, like email, sms, anything.
All it would have to do is include the link_auth, which is already pretty core to that handoff.
E.g. someone could simply tweet, "I submitted vote with id b23ab13ead". Or post on their website, or in a relevant chat room, or wherever. And then once all the final votes are posted, anyone would be able to confirm that link_auth is in there, and anyone (not just the voter themselves) would be able to run the generate_auth_from_encrypted_vote() function themselves to confirm the encrypted vote matches.
Notes:
- We could include that automated check in the client code for the election status page, so everyone visiting that page does it themselves, too.
- This solution is only relevant for link_auth votes, because with normal pre-approved auth tokens, we have to generate those before they vote, so it definitely can't be a digest of the encrypted vote that's not yet made.
- In NDP, voter verification is still fine, this is just about other people being able to independently verify all the votes.
Alternative?
We could also provide a separate encrypted_vote_digest field, to not overload the link_auth... but why? That would just be another thing to have to remember / commit to.
Secrecy implications?
Currently, encrypted votes get published immediately, but not the link_auths— we only publish their auth as pending. With this change, anyone else would be able to derive them immediately now too.
This has no negative implications for vote content secrecy. It still relies upon all the same encryption as before. Zero impact there.
But right now, we are sort of treating the link_auths as temporarily secret... we use them to let voters add their auth info after they submit their vote. If someone else learned your link_auth, they could "snipe" your encrypted vote, after you submit it but before you submit your auth info for it. With their own auth info (real or bogus) onto it instead.
Someone can already make up and submit their own new encrypted votes, to get their own new link_auths. The only benefit for why someone might want to do this is as a form of griefing, to attempt to make it harder for voters to finish their submission. But as written in the NDP case, we just accept all auth submissions, so we would get both the bad ones and the good, and can sort out what's happening after the fact.
If we implemented this generate_auth_from_encrypted_vote() approach, and these griefing attacks truly became a problem — which seems very rare for the vast majority of cases — we could still add/require other secrets:
- We could add another
auth_secret, for them to pass back when they're sending their auth followup info.
- Potentially we could use a signature based on their randomizers, since each column of the encrypted votes are effectively pub keys. (See https://docs.siv.org/authentication#zero-knowledge-proof-that-a-device-cast-a-siv-vote "Zero-Knowledge Proof That A Device Cast A SIV Vote" section at the bottom).
- The main problem there is if we're using some third-party auth (like proof_of_passport app), we wouldn't want their SIV Voter client code to send out any of their randomizers to another app, because they must remain secret to maintain vote content secrecy.
- We could have the SIV server generate them a
link_auth nonce, that also goes into the digest, but only gets published once the vote moves from pending to accepted. So they would know their link_auth immediately, but no one else would be able to derive it until later.
Similar:
In New Democratic Primary, we have ZK Signatures of every passport that participates. Those signatures include a public commitment to the associated
link_auth, which is generated randomly on SIV's server just after the encrypted vote is received.One of the goals of this election was to be able to say:
We can't forge passport proofs. Anyone can verify them independently for themselves.
And then with SIV Shuffle proofs, and Partial Decryption proofs, anyone could trace the passport_proofs -> shuffle_proofs -> decryption_proofs -> unlocked final results. Verifiable, yet still privacy protecting the whole way through.
But...
One hole in the "complete" independent verification.... the passport proof commits to the
link_authbut not the encrypted vote content itself.So for example, we could switch in our own fraudulent encrypted votes, but claim they're still from the
link_auths that were committed to. (Not that we have any interest in doing this, of course. But even better to be able to prove that didn't happen.)One solution: have
link_authitself be verifiably tied to the encrypted vote content.E.g. hash the whole encrypted vote when it's received, and use that as a seed for deterministic PRNG to make link_auths.
Would still be unique, because encrypted votes are effectively unique— each selection has 1/2^256 chance of same randomizers.
Then, any subsequently auth steps are much easier to prove tied to that voter's specific vote selections.
In this case it was the
passport_proof, but the same could be true for other auth, likeemail,sms, anything.All it would have to do is include the
link_auth, which is already pretty core to that handoff.E.g. someone could simply tweet, "I submitted vote with id
b23ab13ead". Or post on their website, or in a relevant chat room, or wherever. And then once all the final votes are posted, anyone would be able to confirm that link_auth is in there, and anyone (not just the voter themselves) would be able to run thegenerate_auth_from_encrypted_vote()function themselves to confirm the encrypted vote matches.Notes:
Alternative?
We could also provide a separate
encrypted_vote_digestfield, to not overload thelink_auth... but why? That would just be another thing to have to remember / commit to.Secrecy implications?
Currently, encrypted votes get published immediately, but not the
link_auths— we only publish their auth aspending. With this change, anyone else would be able to derive them immediately now too.This has no negative implications for vote content secrecy. It still relies upon all the same encryption as before. Zero impact there.
But right now, we are sort of treating the
link_auths as temporarily secret... we use them to let voters add their auth info after they submit their vote. If someone else learned yourlink_auth, they could "snipe" your encrypted vote, after you submit it but before you submit your auth info for it. With their own auth info (real or bogus) onto it instead.Someone can already make up and submit their own new encrypted votes, to get their own new
link_auths. The only benefit for why someone might want to do this is as a form of griefing, to attempt to make it harder for voters to finish their submission. But as written in the NDP case, we just accept all auth submissions, so we would get both the bad ones and the good, and can sort out what's happening after the fact.link_authflow, when we collect name and email, what we do if those fields were already submitted. Ideally we would store each submission, timestamped. Not overwriting or rejecting any.If we implemented this
generate_auth_from_encrypted_vote()approach, and these griefing attacks truly became a problem — which seems very rare for the vast majority of cases — we could still add/require other secrets:auth_secret, for them to pass back when they're sending their auth followup info.link_authnonce, that also goes into the digest, but only gets published once the vote moves frompendingto accepted. So they would know theirlink_authimmediately, but no one else would be able to derive it until later.Similar: