View Javadoc
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  				// taken from the right
52  				fromMix = leftMix;
53  				toMix = rightMix;
54  				fromIndex = i;
55  				toIndex = mer.getMapping();
56  			} else {
57  				// taken from the left
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  }