aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/gnunet/voting/simulation/Authority.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/gnunet/voting/simulation/Authority.java')
-rw-r--r--src/main/java/org/gnunet/voting/simulation/Authority.java266
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 @@
1package org.gnunet.voting.simulation;
2
3import com.google.common.collect.Lists;
4import com.google.common.collect.Maps;
5
6import java.math.BigInteger;
7import java.util.List;
8import java.util.Map;
9
10/**
11 * ...
12 *
13 * @author Florian Dold
14 */
15public 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}