stonecoldpat / anonymousvoting

Anonymous voting on Ethereum without a tally authority. Protocol from this paper http://homepages.cs.ncl.ac.uk/feng.hao/files/OpenVote_IET.pdf
340 stars 88 forks source link

Question: Is there something special about voters[1]? #9

Closed SilentCicero closed 7 years ago

SilentCicero commented 7 years ago

I'm trying to understand the reconstruction step, when voters register, why is account 1 being used in the way you specified here:

https://github.com/stonecoldpat/anonymousvoting/blob/master/AnonymousVoting.sol#L842

I'm having trouble on my end with your system. I'm using my JS conversion of the Java file and I'm trying to determine if there is something wrong with my JS version or if I'm not understanding accounts right.

What is odd is that all other voters (0, 2, 3) work fine (their ZKP is created and verified successfully, and they can create either the yes or no ZKP, and they verify out as well... accept account/voter[1]. The ZKP proof gets created and verified as normal, but when I try to create the 1 of 2 ZKP yes or no, I create it, it looks normal, but on the verify 1 of 2 step, I get in an invalid reading.

Any thoughts on this?

I'm sure its my JS or something..

stonecoldpat commented 7 years ago

Hi,

Let me explain what is going on first before talking about that code.

screen shot 2017-06-23 at 09 38 50

It is worth highlighting that on the ellipitic curve... multiplication is addition, exponentiations is multiplication and division is subtraction. So when I say "add" on the elliptic curve... it is multiplication in the above picture and when I say "subtraction" then it is division in the above picture. Also, g^{x} is the voting key, and g^{y} is the reconstructed key.

lets pretend we are computing the reconstructed key for voter 3 (i.e. the robot).

We add the voting keys for Voter 1 and Voter 2 together (i.e. PK{12}, and we add the voting keys for voter 4 and voter 5 together (PK{45}).

Next, to compute the reconstructed key for voter 3.... we simply subtract both of the sums ReconstructedKey{3} = PK{12} - PK_{45}

Now.... there are two edge cases for both the first and last voter.

For the first voter (voter 0) - no subtraction/division is required... their reconstructed key is simply the sum of all voting keys 1,...,n. This is what we see in the below code:

      // Step 1 is to compute the index 1 reconstructed key
      afteri[0] = voters[1].registeredkey[0];
      afteri[1] = voters[1].registeredkey[1];
      afteri[2] = 1;

      for(uint i=2; i<totalregistered; i++) {
         Secp256k1._addMixedM(afteri, voters[i].registeredkey);
      }

      ECCMath.toZ1(afteri,pp);
      voters[0].reconstructedkey[0] = afteri[0];
      voters[0].reconstructedkey[1] = pp - afteri[1];

Here, we initialise the variable afteri with the voting key of voter 1.... and then add each voter's voting key after that..... so it is the sum of all voting keys 1 to n.

I'm not too sure about the problem with voter 1.... If it is accepting the first zkp for the voting key, then their reconstructed key should be correctly computed by Ethereum.

I'd say it is worth checking two things:

  1. The correct reconstructed key is fetched from Ethereum.
  2. The correct private key that corresponds to their voting key g^{x} (this is what the first zkp proves knowledge about) is being used as well.

It is likely just a bug in the JS code. Stuff like this can be really tricky.

If you want - it might be easier to ask me on skype about this stuff. skype: podgey-kins

p.s. I have some slides here that might explain the protocol step by step as well: https://www.dropbox.com/s/kubf6b9c1d73xx5/Purdue.pptx?dl=0

SilentCicero commented 7 years ago

Side note, everyday I learn more about Sepc256k1/elliptic curve I am every more astonished humans have discovered/can use it's power.

--

I've managed to track down through debugging that Secp256k1.isPubKey(reconstructedkey) does not compute as a valid public key, thus causing the verify 1 of 2 to return false for account/voter[1].

So potentially the outputted reconstructed key for account[1] is not valid/public key.. even though it "looks" like the other keys, i.e. the formatting is the same.

Also, the other keys are also now not public keys (y ... b2), probably due to an invalid reconstructed public key being used in the create 1 of 2 step.

--

Could this still have something to do with the Affine points Java produces vs the x/y points I used @stonecoldpat ?

--

I've tried the values generated through the Java, they produce an identical error to the keys generated with my JS implementation of your Java file. So I don't believe my JS file is producing invalid keys/random numbers.

I'm now onto the reconstruction method/1of2 ZKP creation to see if that could be the issue, remembering I have re-built your method for testing to be stateless also.

I still believe it is my JS, somewhere along the line.. but I cant see the issue yet. Perhaps trying to build the reconstruct process for voter[1] can yeild some information.

--

Found the problem, I have fixed the key reconstruction issue, everything verifies out now. Now the tally is registering as invalid, so working on that. I'm hitting the very bottom logic, where the vote is tallied invalid. I'm using the keys generated from the Java file, so I doubt it is the codes/keys.

The ZKP/verify step completes successfully. The 1of2 votes/1of2 verify step completes successfully. Just into the tally now, checking inputs.

SilentCicero commented 7 years ago

Got it! Just had a few bugs in my JS code. Thanks so much! Lets chat soon.