1 package civitas.common.mix.revelation;
2
3 import java.math.BigInteger;
4 import java.util.Arrays;
5
6 import org.springframework.beans.factory.annotation.Autowired;
7 import org.springframework.stereotype.Controller;
8
9 import civitas.common.mix.VoterMix;
10 import civitas.common.mix.elementrevelation.MixElementRevelation;
11 import civitas.common.mix.elementrevelation.VerifyMixElementRevelation;
12 import civitas.crypto.messagedigest.CryptoHash;
13 import civitas.crypto.publickey.ElGamalPublicKey;
14
15 @Controller
16 public class VerifyMixRevelation {
17 @Autowired
18 VerifyMixElementRevelation verifyMixElementRevelation;
19
20 @Autowired
21 CryptoHash cryptoHash;
22
23 public boolean apply(
24 final MixRevelation that,
25 final ElGamalPublicKey key,
26 final VoterMix initialMix,
27 final VoterMix leftMix,
28 final VoterMix rightMix,
29 final boolean[] revelationDirections) {
30 if (revelationDirections == null
31 || that.revelations.length != revelationDirections.length
32 || that.revelations.length != that.indicators.length) {
33 return false;
34 }
35
36 for (int i = 0; i < that.revelations.length; i++) {
37 if (revelationDirections[i] != that.indicators[i]) {
38 return false;
39 }
40
41 MixElementRevelation mer = that.revelations[i];
42 if (mer == null) {
43 return false;
44 }
45 int fromIndex = -1;
46 int toIndex = -1;
47 VoterMix fromMix = null;
48 VoterMix toMix = null;
49
50 if (revelationDirections[i]) {
51
52 fromMix = leftMix;
53 toMix = rightMix;
54 fromIndex = i;
55 toIndex = mer.getMapping();
56 } else {
57
58 fromMix = initialMix;
59 toMix = leftMix;
60 fromIndex = mer.getMapping();
61 toIndex = i;
62 }
63 byte[] commitment = toMix.getCommitments()[toIndex].clone();
64 byte[] mappingBytes = BigInteger.valueOf(mer.getMapping()).toByteArray();
65 byte[] hash = cryptoHash.apply(mer.getNonce(), mappingBytes);
66 if (!Arrays.equals(commitment, hash)
67 || !verifyMixElementRevelation.apply(mer, key, fromIndex, toIndex, fromMix, toMix)) {
68 return false;
69 }
70 }
71
72 return true;
73 }
74 }