diff options
Diffstat (limited to 'src/main/java/org/gnunet/voting/simulation/Authority.java')
-rw-r--r-- | src/main/java/org/gnunet/voting/simulation/Authority.java | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/src/main/java/org/gnunet/voting/simulation/Authority.java b/src/main/java/org/gnunet/voting/simulation/Authority.java new file mode 100644 index 0000000..792dbbd --- /dev/null +++ b/src/main/java/org/gnunet/voting/simulation/Authority.java | |||
@@ -0,0 +1,266 @@ | |||
1 | package org.gnunet.voting.simulation; | ||
2 | |||
3 | import com.google.common.collect.Lists; | ||
4 | import com.google.common.collect.Maps; | ||
5 | |||
6 | import java.math.BigInteger; | ||
7 | import java.util.List; | ||
8 | import java.util.Map; | ||
9 | |||
10 | /** | ||
11 | * ... | ||
12 | * | ||
13 | * @author Florian Dold | ||
14 | */ | ||
15 | public class Authority { | ||
16 | private BigInteger privateKeyShare; | ||
17 | private BigInteger[] secretPolynomial; | ||
18 | private TransmitShareVerification shareVerification; | ||
19 | |||
20 | private int authorityId; | ||
21 | |||
22 | private BigInteger receivedShare = BigInteger.ZERO; | ||
23 | |||
24 | private VotingParameters parameters; | ||
25 | private List<Authority> participatingAuthorities; | ||
26 | |||
27 | private List<Ballot> ballots = Lists.newLinkedList(); | ||
28 | |||
29 | private Map<Integer, TallyKeyShare> specializedKeyShares = Maps.newTreeMap(); | ||
30 | |||
31 | private Cyphertext encryptedTally; | ||
32 | private BigInteger tallyBaseG; | ||
33 | |||
34 | |||
35 | /** | ||
36 | * The commitments of each authority to it's share of the group secret. | ||
37 | */ | ||
38 | Map<Integer, BigInteger> shareCommitments = Maps.newTreeMap(); | ||
39 | |||
40 | private GroupPublicKey groupPublicKey; | ||
41 | |||
42 | |||
43 | public Authority() { | ||
44 | } | ||
45 | |||
46 | public BigInteger getPublicKeyShare() { | ||
47 | return parameters.g.modPow(privateKeyShare, parameters.p); | ||
48 | } | ||
49 | |||
50 | public BigInteger createShareForAuthority(int j) { | ||
51 | return CryptoUtil.evaluatePolynomial(secretPolynomial, BigInteger.valueOf(j), parameters.q); | ||
52 | } | ||
53 | |||
54 | public void verifyShare(BigInteger distributionShare, TransmitShareVerification senderVerification) { | ||
55 | BigInteger v = parameters.g.modPow(distributionShare, parameters.p); | ||
56 | BigInteger prod = BigInteger.ONE; | ||
57 | for (int l = 0; l < parameters.authorityThreshold; ++l) { | ||
58 | BigInteger exp = BigInteger.valueOf(this.getId()).pow(l); | ||
59 | BigInteger coeff = senderVerification.coeffs[l]; | ||
60 | prod = prod.multiply(coeff.modPow(exp, parameters.p)).mod(parameters.p); | ||
61 | } | ||
62 | if (!v.equals(prod)) { | ||
63 | throw new AssertionError("verification of transmitted shared failed"); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | public void acceptShareFromAuthority(BigInteger distributionShare, TransmitShareVerification senderVerification, Authority sender) { | ||
68 | verifyShare(distributionShare, senderVerification); | ||
69 | receivedShare = receivedShare.add(distributionShare); | ||
70 | } | ||
71 | |||
72 | public int getId() { | ||
73 | return authorityId; | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * Supervisor -> Authority | ||
78 | * | ||
79 | * @param authorityId | ||
80 | * @param parameters | ||
81 | * @return | ||
82 | */ | ||
83 | public BigInteger inviteAuthority(int authorityId, VotingParameters parameters) { | ||
84 | this.authorityId = authorityId; | ||
85 | this.parameters = parameters; | ||
86 | |||
87 | this.privateKeyShare = parameters.generateZq(); | ||
88 | this.secretPolynomial = new BigInteger[parameters.authorityThreshold]; | ||
89 | |||
90 | this.secretPolynomial[0] = privateKeyShare; | ||
91 | for (int i = 1; i < parameters.authorityThreshold; ++i) { | ||
92 | secretPolynomial[i] = parameters.generateZq(); | ||
93 | } | ||
94 | |||
95 | shareVerification = new TransmitShareVerification(secretPolynomial, parameters); | ||
96 | |||
97 | return getPublicKeyShare(); | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * Supervisor -> Authority. | ||
102 | * | ||
103 | * @param participatingAuthorities | ||
104 | */ | ||
105 | public void generateKeyWithAuthorities(List<Authority> participatingAuthorities) { | ||
106 | this.participatingAuthorities = participatingAuthorities; | ||
107 | |||
108 | for (Authority otherAuthority : participatingAuthorities) { | ||
109 | otherAuthority.acceptShareFromAuthority(createShareForAuthority(otherAuthority.getId()), shareVerification, this); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | public void acceptBallot(Ballot ballot) { | ||
114 | verifyBallot(ballot); | ||
115 | // todo: check duplicates | ||
116 | ballots.add(ballot); | ||
117 | |||
118 | } | ||
119 | |||
120 | public void acceptGroupPublicKey(GroupPublicKey key) { | ||
121 | groupPublicKey = key; | ||
122 | } | ||
123 | |||
124 | public void acceptSpecializedKeyShare(TallyKeyShare share, Authority sender) { | ||
125 | specializedKeyShares.put(sender.getId(), share); | ||
126 | verifyTallyKeyShare(share); | ||
127 | } | ||
128 | |||
129 | public void distributeTallyKey() { | ||
130 | computeEncryptedTally(); | ||
131 | |||
132 | for (Authority other : participatingAuthorities) { | ||
133 | TallyKeyShare tallyKeyShare = new TallyKeyShare(encryptedTally.c1, receivedShare, parameters); | ||
134 | other.acceptSpecializedKeyShare(tallyKeyShare, this); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | private void computeEncryptedTally() { | ||
139 | BigInteger votesX = BigInteger.ONE; | ||
140 | BigInteger votesY = BigInteger.ONE; | ||
141 | for (Ballot ballot : ballots) { | ||
142 | votesX = votesX.multiply(ballot.x).mod(parameters.p); | ||
143 | votesY = votesY.multiply(ballot.y).mod(parameters.p); | ||
144 | } | ||
145 | |||
146 | encryptedTally = new Cyphertext(votesX, votesY); | ||
147 | } | ||
148 | |||
149 | private void decryptTallyToBaseG() { | ||
150 | Map<Integer, BigInteger> lagrangeCoefficients = Maps.newTreeMap(); | ||
151 | for (int j : specializedKeyShares.keySet()) { | ||
152 | BigInteger n = BigInteger.ONE; | ||
153 | BigInteger d = BigInteger.ONE; | ||
154 | for (int l : specializedKeyShares.keySet()) { | ||
155 | if (l != j) { | ||
156 | n = n.multiply(BigInteger.valueOf(l)); | ||
157 | d = d.multiply(BigInteger.valueOf(l).subtract(BigInteger.valueOf(j))); | ||
158 | } | ||
159 | } | ||
160 | lagrangeCoefficients.put(j, n.multiply(d.modInverse(parameters.q)).mod(parameters.q)); | ||
161 | } | ||
162 | |||
163 | BigInteger prod = BigInteger.ONE; | ||
164 | for (int authorityIndex : specializedKeyShares.keySet()) { | ||
165 | BigInteger wp = specializedKeyShares.get(authorityIndex).w.modPow(lagrangeCoefficients.get(authorityIndex), parameters.p); | ||
166 | prod = prod.multiply(wp).mod(parameters.p); | ||
167 | } | ||
168 | |||
169 | tallyBaseG = encryptedTally.c2.multiply(prod.modInverse(parameters.p)).mod(parameters.p); | ||
170 | } | ||
171 | |||
172 | public int decryptTally() { | ||
173 | decryptTallyToBaseG(); | ||
174 | |||
175 | int resultRestored = 0; | ||
176 | boolean success = false; | ||
177 | |||
178 | for (int l = -ballots.size(); l <= ballots.size(); ++l) { | ||
179 | if (tallyBaseG.equals(parameters.g.modPow(BigInteger.valueOf(l), parameters.p))) { | ||
180 | success = true; | ||
181 | resultRestored = l; | ||
182 | break; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | if (!success) { | ||
187 | throw new AssertionError(); | ||
188 | } | ||
189 | return resultRestored; | ||
190 | } | ||
191 | |||
192 | /* | ||
193 | * Sigma is the the authority's commitment to its share | ||
194 | */ | ||
195 | public void verifyTallyKeyShare(TallyKeyShare share) { | ||
196 | BigInteger p = parameters.p; | ||
197 | BigInteger g = parameters.g; | ||
198 | |||
199 | BigInteger c1 = share.c1; | ||
200 | BigInteger a = share.a; | ||
201 | BigInteger r = share.r; | ||
202 | BigInteger b = share.b; | ||
203 | BigInteger c = share.c; | ||
204 | |||
205 | // verifier | ||
206 | BigInteger expected1 = g.modPow(r, p); | ||
207 | BigInteger received1 = a.multiply(share.sigma.modPow(c, p)).mod(p); | ||
208 | |||
209 | BigInteger expected2 = c1.modPow(r, p); | ||
210 | BigInteger received2 = b.multiply(share.w.modPow(c, p)).mod(p); | ||
211 | |||
212 | if ((!expected1.equals(received1)) || (!expected2.equals(received2))) { | ||
213 | System.err.println(expected1); | ||
214 | System.err.println(received1); | ||
215 | throw new AssertionError("zero knowledge proof for decryption failed"); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | |||
220 | |||
221 | public void verifyBallot(Ballot ballot) { | ||
222 | BigInteger g = parameters.g; | ||
223 | BigInteger p = parameters.p; | ||
224 | BigInteger h = groupPublicKey.getKey(); | ||
225 | // verifier | ||
226 | |||
227 | BigInteger voterId = ballot.voterId; | ||
228 | BigInteger x = ballot.x; | ||
229 | BigInteger y = ballot.y; | ||
230 | BigInteger a_1 = ballot.a_1; | ||
231 | BigInteger a_2 = ballot.a_2; | ||
232 | BigInteger b_1 = ballot.b_1; | ||
233 | BigInteger b_2 = ballot.b_2; | ||
234 | BigInteger c = ballot.c; | ||
235 | BigInteger d_1 = ballot.d_1; | ||
236 | BigInteger d_2 = ballot.d_2; | ||
237 | BigInteger r_1 = ballot.r_1; | ||
238 | BigInteger r_2 = ballot.r_2; | ||
239 | |||
240 | |||
241 | // todo: we should blame someone here, not throw exceptions | ||
242 | |||
243 | |||
244 | if (!c.equals(CryptoUtil.hash(voterId, x, y, a_1, b_1, a_2, b_2).mod(parameters.q))) { | ||
245 | throw new AssertionError(); | ||
246 | } | ||
247 | |||
248 | if (!c.equals(d_1.add(d_2).mod(p))) { | ||
249 | throw new AssertionError(); | ||
250 | } | ||
251 | if (!a_1.equals(g.modPow(r_1, p).multiply(x.modPow(d_1, p)).mod(p))) { | ||
252 | throw new AssertionError(); | ||
253 | } | ||
254 | if (!b_1.equals(h.modPow(r_1, p).multiply(y.multiply(g).modPow(d_1, p)).mod(p))) { | ||
255 | throw new AssertionError(); | ||
256 | } | ||
257 | |||
258 | if (!a_2.equals(g.modPow(r_2, p).multiply(x.modPow(d_2, p)).mod(p))) { | ||
259 | throw new AssertionError(); | ||
260 | } | ||
261 | |||
262 | if (!b_2.equals(h.modPow(r_2, p).multiply(y.multiply(g.modInverse(p)).modPow(d_2, p)).mod(p))) { | ||
263 | throw new AssertionError(); | ||
264 | } | ||
265 | } | ||
266 | } | ||