Just a toy proof of concept, lacking some key features the ultimate answer would probably want:
- Choose some sufficiently long key.
- Each voter is assigned some chunk of a key (and an index so we know where that chunk goes).
- The assignments are encrypted by this same key.
- The encrypted assignments shared publicly.
- As votes come in, they are signed by a key chunk.
As key chunks come in, knowledge of the key increases, approaching the point where the mapping of keys to people could be brute forced.
You could only calibrate the moment when the keylist would become public by some very generous assumptions, and large elections might make the key size impractical.
Unless... you could declare that the key is the XOR of r known rows, and each row is divided into c
chunks. Voters get a chunk with an index (you don't even need to give them a row index). Then no one would have any information about the key until at least one column was complete, so at least r
votes would have to be in. But you couldn't guarantee you had any information until at least (r * c) - (c - 1)
votes were in... a lot of unpredictability.
Maybe this can be tuned, though, by assigning chunks as the votes are cast. You assign the chunks to an ordinal, 1st voter gets (index = 0, chunk = "a9 68 c7 ... ")
, second voter gets (index = 0, chunk = "66 93 b9 ... ")
, third voter gets (index = 0, ... )
. They leave with a slip that includes their key chunk, they sign a sheet saying they were they Xth voter.
So if you want votes to be revealed at 60 percent, and you have 100 voters, then your 55th voter gets (index = 1, chunk = "de ...")
, 56th gets (index = 2, chunk = "be ...")
You move laterally only once you get near your target. (In fact, you don't need a bunch of full rows, you just need a bunch of redundant chunks for the first column, before you start moving laterally.)
Ok, so this involves a trusted administrator so far, but maybe it could be patched for distributed administration...
UPDATE
Wasn't a finished answer (didn't even address the distributed requirement!) I should have held off, apologies. But for anyone interested in a toy proof of concept, here's a better version.
Each party can encrypt their vote (providing signatures, commitments) and then distribute portions of key information among the other potential voters. As the voters lodge a vote, they publish the key information they have, such that once a certain number of voters have lodged a vote, all prior votes can be decrypted.
This relies on a primitive where some message is divided into a number of pieces such that it can be recovered after (and only after) some percentage of the pieces have been revealed, but remains cryptologically secure before that threshold.
I provided an ugly way to do that in the comments, just generate a number of suitably random unique masks equal to the number of voters required for revelation. The voter distributes these randomly among all other voters (some redundancy will be required). Have the pool of voters reveal this information during the voting process.
If a voter reveals previously revealed key information, here's the especially ugly bit, a call goes out to the other voters to supply a new piece of key information, or as voters see the key information they received published when they haven't yet voted, they can check their piece of key information back in with the voter who owns that key and request a random piece of key information from that voter that has not yet been revealed.
Would appreciate a better version of the primitive though. Not sure if error correcting codes might provide something here or not...