aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2014-03-30 21:41:58 +0000
committerFlorian Dold <florian.dold@gmail.com>2014-03-30 21:41:58 +0000
commit9f10abfdc35d8f189a8e0a77a389799ca6b7f9e5 (patch)
tree39d855abacebeaa45752e4abc5b4a660d2603d70 /src/main/java/org
parent1fbef203844b19f8141bddcba20a977de34b211e (diff)
downloadgnunet-java-9f10abfdc35d8f189a8e0a77a389799ca6b7f9e5.tar.gz
gnunet-java-9f10abfdc35d8f189a8e0a77a389799ca6b7f9e5.zip
- fix election crypto
- multi-way elections - high-level signature containers - fix bug in mesh test case - fix bug in Strings.java - ivy repo
Diffstat (limited to 'src/main/java/org')
-rw-r--r--src/main/java/org/gnunet/construct/parsers/IntegerUtil.java6
-rw-r--r--src/main/java/org/gnunet/core/Core.java2
-rw-r--r--src/main/java/org/gnunet/mesh/ConnectHandler.java2
-rw-r--r--src/main/java/org/gnunet/mesh/DisconnectHandler.java12
-rw-r--r--src/main/java/org/gnunet/mesh/InboundChannelHandler.java12
-rw-r--r--src/main/java/org/gnunet/mesh/InboundTunnelHandler.java12
-rw-r--r--src/main/java/org/gnunet/mesh/Mesh.java86
-rw-r--r--src/main/java/org/gnunet/mesh/MeshRunabout.java6
-rw-r--r--src/main/java/org/gnunet/mesh/TunnelEndHandler.java10
-rw-r--r--src/main/java/org/gnunet/mesh/TunnelNotificationMessage.java22
-rw-r--r--src/main/java/org/gnunet/mesh/package-info.java2
-rw-r--r--src/main/java/org/gnunet/mq/MessageQueue.java49
-rw-r--r--src/main/java/org/gnunet/secretsharing/Ciphertext.java21
-rw-r--r--src/main/java/org/gnunet/secretsharing/Parameters.java27
-rw-r--r--src/main/java/org/gnunet/secretsharing/Plaintext.java60
-rw-r--r--src/main/java/org/gnunet/statistics/SetRequest.java50
-rw-r--r--src/main/java/org/gnunet/util/BigIntegers.java6
-rw-r--r--src/main/java/org/gnunet/util/Connection.java1
-rw-r--r--src/main/java/org/gnunet/util/Strings.java43
-rw-r--r--src/main/java/org/gnunet/util/crypto/ContentWithPurposeMessage.java17
-rw-r--r--src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java39
-rw-r--r--src/main/java/org/gnunet/util/crypto/EcdsaSignature.java30
-rw-r--r--src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java49
-rw-r--r--src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java31
-rw-r--r--src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java4
-rw-r--r--src/main/java/org/gnunet/util/crypto/EddsaSignature.java21
-rw-r--r--src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java63
-rw-r--r--src/main/java/org/gnunet/util/crypto/SignedContentMessage.java8
-rw-r--r--src/main/java/org/gnunet/voting/Ballot.java40
-rw-r--r--src/main/java/org/gnunet/voting/BallotTool.java38
-rw-r--r--src/main/java/org/gnunet/voting/ChaumPedersenZkp.java75
-rw-r--r--src/main/java/org/gnunet/voting/DisjunctionZkp.java64
-rw-r--r--src/main/java/org/gnunet/voting/EncryptedVote.java159
-rw-r--r--src/main/java/org/gnunet/voting/GroupCert.java2
-rw-r--r--src/main/java/org/gnunet/voting/SignedEncryptedVote.java8
-rw-r--r--src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java27
-rw-r--r--src/main/java/org/gnunet/voting/messages/SubmitMessage.java1
-rw-r--r--src/main/java/org/gnunet/voting/simulation/Ballot.java3
-rw-r--r--src/main/java/org/gnunet/voting/simulation/VotingParameters.java30
39 files changed, 803 insertions, 335 deletions
diff --git a/src/main/java/org/gnunet/construct/parsers/IntegerUtil.java b/src/main/java/org/gnunet/construct/parsers/IntegerUtil.java
index 83391de..d791f39 100644
--- a/src/main/java/org/gnunet/construct/parsers/IntegerUtil.java
+++ b/src/main/java/org/gnunet/construct/parsers/IntegerUtil.java
@@ -47,7 +47,7 @@ public class IntegerUtil {
47 val |= s; 47 val |= s;
48 48
49 if (isSigned) { 49 if (isSigned) {
50 // explicitly OR sign bit to the right place if the source buffer is 50 // explicitly OR signRaw bit to the right place if the source buffer is
51 // too large 51 // too large
52 long sign = (srcBuf.get(first) & 0x80); 52 long sign = (srcBuf.get(first) & 0x80);
53 val |= (sign << 7); 53 val |= (sign << 7);
@@ -69,9 +69,9 @@ public class IntegerUtil {
69 } 69 }
70 70
71 if (isSigned) { 71 if (isSigned) {
72 // a long has 8 bytes, shift by 7 bytes (non-arithmetically) to get the sign 72 // a long has 8 bytes, shift by 7 bytes (non-arithmetically) to get the signRaw
73 byte sign = (byte) ((val >>> (7*8)) & 0x80); 73 byte sign = (byte) ((val >>> (7*8)) & 0x80);
74 // remove the sign bit from the buffer 74 // remove the signRaw bit from the buffer
75 dstBuf.put(dstBuf.position() + byteSize - 1, (byte) (dstBuf.get(dstBuf.position() + byteSize - 1) & ~sign)); 75 dstBuf.put(dstBuf.position() + byteSize - 1, (byte) (dstBuf.get(dstBuf.position() + byteSize - 1) & ~sign));
76 // ... and put it in the right place (lowest byte) 76 // ... and put it in the right place (lowest byte)
77 dstBuf.put(dstBuf.position(), (byte) (dstBuf.get(dstBuf.position()) | sign)); 77 dstBuf.put(dstBuf.position(), (byte) (dstBuf.get(dstBuf.position()) | sign));
diff --git a/src/main/java/org/gnunet/core/Core.java b/src/main/java/org/gnunet/core/Core.java
index 307b9a2..a4adb32 100644
--- a/src/main/java/org/gnunet/core/Core.java
+++ b/src/main/java/org/gnunet/core/Core.java
@@ -267,7 +267,7 @@ public class Core {
267 for (int i : interested) { 267 for (int i : interested) {
268 logger.debug("we are interested in " + i); 268 logger.debug("we are interested in " + i);
269 } 269 }
270 client.sendPrefered(initMessage); 270 client.sendPreferred(initMessage);
271 } 271 }
272 272
273 /** 273 /**
diff --git a/src/main/java/org/gnunet/mesh/ConnectHandler.java b/src/main/java/org/gnunet/mesh/ConnectHandler.java
index 62275b0..8583df2 100644
--- a/src/main/java/org/gnunet/mesh/ConnectHandler.java
+++ b/src/main/java/org/gnunet/mesh/ConnectHandler.java
@@ -8,5 +8,5 @@ import org.gnunet.util.PeerIdentity;
8 * @author Florian Dold 8 * @author Florian Dold
9 */ 9 */
10public interface ConnectHandler { 10public interface ConnectHandler {
11 public void onConnect(Mesh.Tunnel tunnel, PeerIdentity peer); 11 public void onConnect(Mesh.Channel channel, PeerIdentity peer);
12} 12}
diff --git a/src/main/java/org/gnunet/mesh/DisconnectHandler.java b/src/main/java/org/gnunet/mesh/DisconnectHandler.java
deleted file mode 100644
index 8fd6428..0000000
--- a/src/main/java/org/gnunet/mesh/DisconnectHandler.java
+++ /dev/null
@@ -1,12 +0,0 @@
1package org.gnunet.mesh;
2
3import org.gnunet.util.PeerIdentity;
4
5/**
6 * ...
7 *
8 * @author Florian Dold
9 */
10public interface DisconnectHandler {
11 void onDisconnect(PeerIdentity peer);
12}
diff --git a/src/main/java/org/gnunet/mesh/InboundChannelHandler.java b/src/main/java/org/gnunet/mesh/InboundChannelHandler.java
new file mode 100644
index 0000000..a8cb6b7
--- /dev/null
+++ b/src/main/java/org/gnunet/mesh/InboundChannelHandler.java
@@ -0,0 +1,12 @@
1package org.gnunet.mesh;
2
3import org.gnunet.util.PeerIdentity;
4
5/**
6 * ...
7 *
8 * @author Florian Dold
9 */
10public interface InboundChannelHandler {
11 void onInboundTunnel(Mesh.Channel channel, PeerIdentity initiator);
12}
diff --git a/src/main/java/org/gnunet/mesh/InboundTunnelHandler.java b/src/main/java/org/gnunet/mesh/InboundTunnelHandler.java
deleted file mode 100644
index ebcf225..0000000
--- a/src/main/java/org/gnunet/mesh/InboundTunnelHandler.java
+++ /dev/null
@@ -1,12 +0,0 @@
1package org.gnunet.mesh;
2
3import org.gnunet.util.PeerIdentity;
4
5/**
6 * ...
7 *
8 * @author Florian Dold
9 */
10public interface InboundTunnelHandler {
11 void onInboundTunnel(Mesh.Tunnel tunnel, PeerIdentity initiator);
12}
diff --git a/src/main/java/org/gnunet/mesh/Mesh.java b/src/main/java/org/gnunet/mesh/Mesh.java
index 0a7369b..aedfd6a 100644
--- a/src/main/java/org/gnunet/mesh/Mesh.java
+++ b/src/main/java/org/gnunet/mesh/Mesh.java
@@ -50,7 +50,7 @@ public class Mesh {
50 private static final long TUNNEL_ID_CLI = 0x80000000L; 50 private static final long TUNNEL_ID_CLI = 0x80000000L;
51 51
52 /** 52 /**
53 * For tunnels created by the server, the bit in this 53 * For tunnels created by the service, the bit in this
54 * mask is always set. 54 * mask is always set.
55 */ 55 */
56 private static final long TUNNEL_ID_SERV = 0xB0000000L; 56 private static final long TUNNEL_ID_SERV = 0xB0000000L;
@@ -91,12 +91,12 @@ public class Mesh {
91 /** 91 /**
92 * Handler for inbound tunnels. 92 * Handler for inbound tunnels.
93 */ 93 */
94 private InboundTunnelHandler inboundTunnelHandler; 94 private InboundChannelHandler inboundChannelHandler;
95 95
96 /** 96 /**
97 * Mapping from the tunnel's ID to the tunnel object. 97 * Mapping from the tunnel's ID to the tunnel object.
98 */ 98 */
99 private Map<Long,Tunnel> tunnelMap = new HashMap<Long,Tunnel>(); 99 private Map<Long,Channel> tunnelMap = new HashMap<Long,Channel>();
100 100
101 /** 101 /**
102 * Counter for generating fresh tunnel ID's 102 * Counter for generating fresh tunnel ID's
@@ -108,7 +108,7 @@ public class Mesh {
108 * A tunnel to a remote peer. 108 * A tunnel to a remote peer.
109 * @param <T> type of context data for the tunnel 109 * @param <T> type of context data for the tunnel
110 */ 110 */
111 public class Tunnel<T> extends MessageQueue { 111 public class Channel<T> extends MessageQueue {
112 private T context; 112 private T context;
113 private final int opt; 113 private final int opt;
114 final PeerIdentity peer; 114 final PeerIdentity peer;
@@ -133,7 +133,7 @@ public class Mesh {
133 * @param nobuffer Flag for disabling buffering on relay nodes. 133 * @param nobuffer Flag for disabling buffering on relay nodes.
134 * @param reliable Flag for end-to-end reliability. 134 * @param reliable Flag for end-to-end reliability.
135 */ 135 */
136 public Tunnel(PeerIdentity peer, int port, boolean nobuffer, boolean reliable, T context) { 136 public Channel(PeerIdentity peer, int port, boolean nobuffer, boolean reliable, T context) {
137 this(peer, 0, port, nobuffer, reliable); 137 this(peer, 0, port, nobuffer, reliable);
138 TunnelCreateMessage tcm = new TunnelCreateMessage(); 138 TunnelCreateMessage tcm = new TunnelCreateMessage();
139 tcm.otherEnd = peer; 139 tcm.otherEnd = peer;
@@ -154,7 +154,7 @@ public class Mesh {
154 * @param nobuffer 154 * @param nobuffer
155 * @param reliable 155 * @param reliable
156 */ 156 */
157 public Tunnel(PeerIdentity peer, long tunnelId, int port, boolean nobuffer, boolean reliable) { 157 public Channel(PeerIdentity peer, long tunnelId, int port, boolean nobuffer, boolean reliable) {
158 int myOpt = 0; 158 int myOpt = 0;
159 if (reliable) 159 if (reliable)
160 myOpt |= OPTION_RELIABLE; 160 myOpt |= OPTION_RELIABLE;
@@ -242,16 +242,16 @@ public class Mesh {
242 242
243 private class MeshMessageReceiver extends RunaboutMessageReceiver { 243 private class MeshMessageReceiver extends RunaboutMessageReceiver {
244 public void visit(TunnelCreateMessage m) { 244 public void visit(TunnelCreateMessage m) {
245 Tunnel t = new Tunnel(m.otherEnd, m.tunnelId, m.port, 245 Channel t = new Channel(m.otherEnd, m.tunnelId, m.port,
246 (m.opt & OPTION_NOBUFFER) != 0, (m.opt & OPTION_NOBUFFER) != 0); 246 (m.opt & OPTION_NOBUFFER) != 0, (m.opt & OPTION_NOBUFFER) != 0);
247 logger.debug("inbound tunnel {}", m.tunnelId); 247 logger.debug("inbound tunnel {}", m.tunnelId);
248 if (inboundTunnelHandler != null) { 248 if (inboundChannelHandler != null) {
249 inboundTunnelHandler.onInboundTunnel(t, m.otherEnd); 249 inboundChannelHandler.onInboundTunnel(t, m.otherEnd);
250 } 250 }
251 } 251 }
252 252
253 public void visit(DataMessage m) { 253 public void visit(DataMessage m) {
254 Tunnel t = tunnelMap.get(m.tid); 254 Channel t = tunnelMap.get(m.tid);
255 if (t != null) 255 if (t != null)
256 { 256 {
257 if (t.receiveDoneExpected) 257 if (t.receiveDoneExpected)
@@ -268,7 +268,7 @@ public class Mesh {
268 268
269 public void visit(LocalAckMessage m) { 269 public void visit(LocalAckMessage m) {
270 logger.debug("got LocalAckMessage for {}", m.tid); 270 logger.debug("got LocalAckMessage for {}", m.tid);
271 Tunnel t = tunnelMap.get(m.tid); 271 Channel t = tunnelMap.get(m.tid);
272 if (t != null) { 272 if (t != null) {
273 t.handleAck(); 273 t.handleAck();
274 } else { 274 } else {
@@ -277,38 +277,36 @@ public class Mesh {
277 } 277 }
278 278
279 public void visit(TunnelDestroyMessage m) { 279 public void visit(TunnelDestroyMessage m) {
280 Tunnel t = tunnelMap.get(m.tunnelId); 280 Channel t = tunnelMap.get(m.tunnelId);
281 if (null == t) { 281 if (null == t) {
282 logger.warn("server got confused with tunnel IDs on destroy, ignoring message"); 282 logger.warn("server got confused with tunnel IDs on destroy, ignoring message");
283 return; 283 return;
284 } 284 }
285 t.destroyedByService = true; 285 t.destroyedByService = true;
286 logger.debug("tunnel destroyed by service");
286 t.destroy(); 287 t.destroy();
287 if (null != tunnelEndHandler) { 288 tunnelEndHandler.onChannelEnd(t);
288 tunnelEndHandler.onTunnelEnd(t);
289 }
290 } 289 }
291 290
292 public void visit(RejectMessage m) { 291 public void visit(RejectMessage m) {
293 // FIXME: C code indicates that the nack/reject message might change ... 292 // FIXME: C code indicates that the nack/reject message might change ...
294 Tunnel t = tunnelMap.get(m.tunnelId); 293 Channel t = tunnelMap.get(m.tunnelId);
295 if (null == t) { 294 if (null == t) {
296 logger.warn("server got confused with tunnel IDs on destroy, ignoring message"); 295 logger.warn("server got confused with tunnel IDs on destroy, ignoring message");
297 return; 296 return;
298 } 297 }
299 t.destroyedByService = true; 298 t.destroyedByService = true;
299 logger.debug("tunnel destroyed by service (nack/reject)");
300 t.destroy(); 300 t.destroy();
301 if (null != tunnelEndHandler) { 301 tunnelEndHandler.onChannelEnd(t);
302 tunnelEndHandler.onTunnelEnd(t);
303 }
304 } 302 }
305 303
306 @Override 304 @Override
307 public void handleError() { 305 public void handleError() {
308 logger.warn("lost connection to mesh service, reconnecting"); 306 logger.warn("lost connection to mesh service, reconnecting");
309 if (null != tunnelEndHandler) { 307 if (null != tunnelEndHandler) {
310 for (Tunnel t : tunnelMap.values()) { 308 for (Channel t : tunnelMap.values()) {
311 tunnelEndHandler.onTunnelEnd(t); 309 tunnelEndHandler.onChannelEnd(t);
312 } 310 }
313 } 311 }
314 tunnelMap.clear(); 312 tunnelMap.clear();
@@ -322,21 +320,22 @@ public class Mesh {
322 /** 320 /**
323 * Connect to the mesh service, listening to the given ports. 321 * Connect to the mesh service, listening to the given ports.
324 * 322 *
325 * @param cfg configuration to use 323 * @param cfg configuration to use
326 * @param inboundTunnelHandler function called when an *inbound* tunnel is created 324 * @param inboundChannelHandler called when an inbound channel is established
327 * @param tunnelEndHandler function called when an *inbound* tunnel is destroyed by the 325 * @param tunnelEndHandler called when a tunnel is destroyed (either by the client calling Tunnel.destroy(),
328 * remote peer, it is *not* called if Tunnel.destroy 326 * or by the service)
329 * is called on the tunnel
330 * @param messageReceiver runabout for messages we are interested in 327 * @param messageReceiver runabout for messages we are interested in
331 * @param ports ports to listen on 328 * @param ports ports to listen on
332 */ 329 */
333 public Mesh(Configuration cfg, InboundTunnelHandler inboundTunnelHandler, 330 public Mesh(Configuration cfg, InboundChannelHandler inboundChannelHandler,
334 TunnelEndHandler tunnelEndHandler, MeshRunabout messageReceiver, int... ports) { 331 TunnelEndHandler tunnelEndHandler, MeshRunabout messageReceiver, int... ports) {
332 if (null == tunnelEndHandler) {
333 throw new AssertionError("tunnel end handler may not be null");
334 }
335 this.tunnelEndHandler = tunnelEndHandler; 335 this.tunnelEndHandler = tunnelEndHandler;
336 this.messageReceiver = messageReceiver; 336 this.messageReceiver = messageReceiver;
337 this.ports = ports; 337 this.ports = ports;
338 this.inboundTunnelHandler = inboundTunnelHandler; 338 this.inboundChannelHandler = inboundChannelHandler;
339
340 client = new Client("mesh", cfg); 339 client = new Client("mesh", cfg);
341 client.installReceiver(new MeshMessageReceiver()); 340 client.installReceiver(new MeshMessageReceiver());
342 ClientConnectMessage ccm = new ClientConnectMessage(); 341 ClientConnectMessage ccm = new ClientConnectMessage();
@@ -351,24 +350,35 @@ public class Mesh {
351 } 350 }
352 351
353 /** 352 /**
354 * Connect to the mesh service. 353 * Connect to the mesh service. Use this constructor if you are not interested in inbound tunnels.
355 * 354 *
356 * @param cfg configuration to use 355 * @param cfg configuration to use
357 * @param tunnelEndHandler function called when an *inbound* tunnel is destroyed by the 356 * @param tunnelEndHandler called when a tunnel is destroyed (either by the client calling Tunnel.destroy(),
358 * remote peer, it is *not* called if Tunnel.destroy 357 * or by the service)
359 * is called on the tunnel
360 */ 358 */
361 public Mesh(Configuration cfg, TunnelEndHandler tunnelEndHandler, MeshRunabout messageReceiver) { 359 public Mesh(Configuration cfg, TunnelEndHandler tunnelEndHandler, MeshRunabout messageReceiver) {
362 this(cfg, null, tunnelEndHandler, messageReceiver); 360 this(cfg, null, tunnelEndHandler, messageReceiver);
363 } 361 }
364 362
365 public <T> Tunnel<T> createTunnel(PeerIdentity peer, int port, boolean nobuffer, boolean reliable, T initialContext) { 363 /**
366 return new Tunnel<T>(peer, port, nobuffer, reliable, initialContext); 364 * Connect to the mesh service. Use this constructor if you are not interested in inbound tunnels
365 * and don't want to receive messages.
366 *
367 * @param cfg configuration to use
368 * @param tunnelEndHandler called when a tunnel is destroyed (either by the client calling Tunnel.destroy(),
369 * or by the service)
370 */
371 public Mesh(Configuration cfg, TunnelEndHandler tunnelEndHandler) {
372 this(cfg, null, tunnelEndHandler, null);
373 }
374
375 public <T> Channel<T> createTunnel(PeerIdentity peer, int port, boolean nobuffer, boolean reliable, T initialContext) {
376 return new Channel<T>(peer, port, nobuffer, reliable, initialContext);
367 } 377 }
368 378
369 public <T> Tunnel<T> createTunnel(PeerIdentity peer, int port, boolean nobuffer, boolean reliable) { 379 public <T> Channel<T> createTunnel(PeerIdentity peer, int port, boolean nobuffer, boolean reliable) {
370 logger.debug("creating tunnel to peer {} over port {}", peer.toString(), port); 380 logger.debug("creating tunnel to peer {} over port {}", peer.toString(), port);
371 return new Tunnel<T>(peer, port, nobuffer, reliable, null); 381 return new Channel<T>(peer, port, nobuffer, reliable, null);
372 } 382 }
373 383
374 /** 384 /**
diff --git a/src/main/java/org/gnunet/mesh/MeshRunabout.java b/src/main/java/org/gnunet/mesh/MeshRunabout.java
index 50dbe09..577a6cd 100644
--- a/src/main/java/org/gnunet/mesh/MeshRunabout.java
+++ b/src/main/java/org/gnunet/mesh/MeshRunabout.java
@@ -8,11 +8,11 @@ import org.grothoff.Runabout;
8 * @author Florian Dold 8 * @author Florian Dold
9 */ 9 */
10public class MeshRunabout extends Runabout { 10public class MeshRunabout extends Runabout {
11 private Mesh.Tunnel sender; 11 private Mesh.Channel sender;
12 /* package private */ void setSender(Mesh.Tunnel sender) { 12 /* package private */ void setSender(Mesh.Channel sender) {
13 this.sender = sender; 13 this.sender = sender;
14 } 14 }
15 public Mesh.Tunnel getSender() { 15 public Mesh.Channel getSender() {
16 return sender; 16 return sender;
17 } 17 }
18} 18}
diff --git a/src/main/java/org/gnunet/mesh/TunnelEndHandler.java b/src/main/java/org/gnunet/mesh/TunnelEndHandler.java
index 2a492ce..5b89a2f 100644
--- a/src/main/java/org/gnunet/mesh/TunnelEndHandler.java
+++ b/src/main/java/org/gnunet/mesh/TunnelEndHandler.java
@@ -7,11 +7,11 @@ package org.gnunet.mesh;
7 */ 7 */
8public interface TunnelEndHandler { 8public interface TunnelEndHandler {
9 /** 9 /**
10 * Called once a tunnel has been destroyed. 10 * Called once a channel has been destroyed.
11 * The given tunnel can not be used anymore, and is only provided 11 * The given channel can not be used anymore, and is only provided
12 * to identify the tunnel that has been destroyed. 12 * to identify the channel that has been destroyed.
13 * 13 *
14 * @param tunnel tunnel that has been destroyed 14 * @param channel channel that has been destroyed
15 */ 15 */
16 void onTunnelEnd(Mesh.Tunnel tunnel); 16 void onChannelEnd(Mesh.Channel channel);
17} 17}
diff --git a/src/main/java/org/gnunet/mesh/TunnelNotificationMessage.java b/src/main/java/org/gnunet/mesh/TunnelNotificationMessage.java
deleted file mode 100644
index e6fb724..0000000
--- a/src/main/java/org/gnunet/mesh/TunnelNotificationMessage.java
+++ /dev/null
@@ -1,22 +0,0 @@
1package org.gnunet.mesh;
2
3import org.gnunet.construct.NestedMessage;
4import org.gnunet.construct.UInt32;
5import org.gnunet.util.GnunetMessage;
6import org.gnunet.util.PeerIdentity;
7
8/**
9 * ...
10 *
11 * @author Florian Dold
12 */
13public class TunnelNotificationMessage implements GnunetMessage.Body {
14 @UInt32
15 public int tunnelId;
16 /**
17 * Peer at the other end, if any
18 * TODO: ask bart what 'if any' means here
19 */
20 @NestedMessage
21 public PeerIdentity peer;
22}
diff --git a/src/main/java/org/gnunet/mesh/package-info.java b/src/main/java/org/gnunet/mesh/package-info.java
index fb5a8a4..2a60cc0 100644
--- a/src/main/java/org/gnunet/mesh/package-info.java
+++ b/src/main/java/org/gnunet/mesh/package-info.java
@@ -20,6 +20,6 @@
20 20
21 21
22/** 22/**
23 * Create tunnels for packet-based communication to distant peers. 23 * Create channels for packet-based communication to distant peers.
24 */ 24 */
25package org.gnunet.mesh; 25package org.gnunet.mesh;
diff --git a/src/main/java/org/gnunet/mq/MessageQueue.java b/src/main/java/org/gnunet/mq/MessageQueue.java
index d7ecce7..8306c4c 100644
--- a/src/main/java/org/gnunet/mq/MessageQueue.java
+++ b/src/main/java/org/gnunet/mq/MessageQueue.java
@@ -2,6 +2,8 @@ package org.gnunet.mq;
2 2
3 3
4import org.gnunet.util.GnunetMessage; 4import org.gnunet.util.GnunetMessage;
5import org.slf4j.Logger;
6import org.slf4j.LoggerFactory;
5 7
6import java.util.LinkedList; 8import java.util.LinkedList;
7 9
@@ -9,9 +11,31 @@ import java.util.LinkedList;
9 * General-purpose message queue 11 * General-purpose message queue
10 */ 12 */
11public abstract class MessageQueue { 13public abstract class MessageQueue {
14 /**
15 * Class logger.
16 */
17 private static final Logger logger = LoggerFactory
18 .getLogger(MessageQueue.class);
19 /**
20 * Envelopes queued for sending.
21 */
12 private LinkedList<Envelope> queuedEnvelopes = new LinkedList<Envelope>(); 22 private LinkedList<Envelope> queuedEnvelopes = new LinkedList<Envelope>();
13 private LinkedList<Envelope> preferedQueuedEnvelopes = new LinkedList<Envelope>(); 23 /**
24 * Envelopes queued for sending. The preferred envelopes will always be sent before
25 * the envelopes in 'queuedEnvelopes'.
26 */
27 private LinkedList<Envelope> preferredQueuedEnvelopes = new LinkedList<Envelope>();
28 /**
29 * Envelope we are currently in the process of submitting.
30 * While the 'currentEnvelope' is not null, no other envelope
31 * can be transmitted.
32 */
14 protected Envelope currentEnvelope; 33 protected Envelope currentEnvelope;
34
35 /**
36 * Are we ready to submit messages, or should we wait and queue further submit
37 * requests?
38 */
15 private boolean readyForSubmit; 39 private boolean readyForSubmit;
16 40
17 /** 41 /**
@@ -30,23 +54,25 @@ public abstract class MessageQueue {
30 send(new Envelope(body)); 54 send(new Envelope(body));
31 } 55 }
32 56
33 public void sendPrefered(GnunetMessage.Body body) { 57 public void sendPreferred(GnunetMessage.Body body) {
34 sendPrefered(new Envelope(body)); 58 sendPreferred(new Envelope(body));
35 } 59 }
36 60
37 public void send(Envelope ev) { 61 public void send(Envelope ev) {
62 logger.debug("message queue {}: queueing message", this.getClass().getName());
38 queuedEnvelopes.addLast(ev); 63 queuedEnvelopes.addLast(ev);
39 trySubmitNext(); 64 trySubmitNext();
40 } 65 }
41 66
42 public void sendPrefered(Envelope ev) { 67 public void sendPreferred(Envelope ev) {
43 preferedQueuedEnvelopes.addLast(ev); 68 logger.debug("message queue {}: queueing preferred message", this.getClass().getName());
69 preferredQueuedEnvelopes.addLast(ev);
44 trySubmitNext(); 70 trySubmitNext();
45 } 71 }
46 72
47 private Envelope pollNextEnvelope() { 73 private Envelope pollNextEnvelope() {
48 if (!preferedQueuedEnvelopes.isEmpty()) 74 if (!preferredQueuedEnvelopes.isEmpty())
49 return preferedQueuedEnvelopes.removeFirst(); 75 return preferredQueuedEnvelopes.removeFirst();
50 if (!queuedEnvelopes.isEmpty()) 76 if (!queuedEnvelopes.isEmpty())
51 return queuedEnvelopes.removeFirst(); 77 return queuedEnvelopes.removeFirst();
52 return null; 78 return null;
@@ -54,10 +80,12 @@ public abstract class MessageQueue {
54 80
55 protected void trySubmitNext() { 81 protected void trySubmitNext() {
56 if (currentEnvelope != null || !readyForSubmit) { 82 if (currentEnvelope != null || !readyForSubmit) {
83 logger.debug("message queue {}: not submitting (not ready)", this.getClass().getName());
57 return; 84 return;
58 } 85 }
59 Envelope ev = pollNextEnvelope(); 86 Envelope ev = pollNextEnvelope();
60 if (ev == null) { 87 if (ev == null) {
88 logger.debug("message queue {}: not submitting (nothing to send)", this.getClass().getName());
61 return; 89 return;
62 } 90 }
63 currentEnvelope = ev; 91 currentEnvelope = ev;
@@ -69,6 +97,7 @@ public abstract class MessageQueue {
69 if (readyForSubmit) { 97 if (readyForSubmit) {
70 throw new AssertionError("message queue reported 'ready for submit' twice"); 98 throw new AssertionError("message queue reported 'ready for submit' twice");
71 } 99 }
100 logger.debug("message queue {} ready for submit", this.getClass().getName());
72 readyForSubmit = true; 101 readyForSubmit = true;
73 trySubmitNext(); 102 trySubmitNext();
74 } 103 }
@@ -90,15 +119,13 @@ public abstract class MessageQueue {
90 * 119 *
91 * @param ev the envelope to onCancel 120 * @param ev the envelope to onCancel
92 */ 121 */
93 /* pkg-private */ void cancelEnvelope(Envelope ev) { 122 void cancelEnvelope(Envelope ev) {
94 if (null == currentEnvelope)
95 throw new AssertionError();
96 if (ev == currentEnvelope) { 123 if (ev == currentEnvelope) {
97 retract(); 124 retract();
98 trySubmitNext(); 125 trySubmitNext();
99 } else { 126 } else {
100 queuedEnvelopes.remove(ev); 127 queuedEnvelopes.remove(ev);
101 preferedQueuedEnvelopes.remove(ev); 128 preferredQueuedEnvelopes.remove(ev);
102 } 129 }
103 } 130 }
104} 131}
diff --git a/src/main/java/org/gnunet/secretsharing/Ciphertext.java b/src/main/java/org/gnunet/secretsharing/Ciphertext.java
index d60e8ce..10b056e 100644
--- a/src/main/java/org/gnunet/secretsharing/Ciphertext.java
+++ b/src/main/java/org/gnunet/secretsharing/Ciphertext.java
@@ -26,6 +26,7 @@ import org.gnunet.util.BigIntegers;
26import org.gnunet.util.Strings; 26import org.gnunet.util.Strings;
27 27
28import java.math.BigInteger; 28import java.math.BigInteger;
29import java.util.Arrays;
29 30
30/** 31/**
31 * ElGamal ciphertext. 32 * ElGamal ciphertext.
@@ -37,6 +38,26 @@ public class Ciphertext implements Message {
37 @FixedSizeIntegerArray(signed = true, bitSize = 8, length = Parameters.elgamalBits / 8) 38 @FixedSizeIntegerArray(signed = true, bitSize = 8, length = Parameters.elgamalBits / 8)
38 public byte[] c_2; 39 public byte[] c_2;
39 40
41 @Override
42 public boolean equals(Object o) {
43 if (this == o) return true;
44 if (o == null || getClass() != o.getClass()) return false;
45
46 Ciphertext that = (Ciphertext) o;
47
48 if (!Arrays.equals(c_1, that.c_1)) return false;
49 if (!Arrays.equals(c_2, that.c_2)) return false;
50
51 return true;
52 }
53
54 @Override
55 public int hashCode() {
56 int result = c_1 != null ? Arrays.hashCode(c_1) : 0;
57 result = 31 * result + (c_2 != null ? Arrays.hashCode(c_2) : 0);
58 return result;
59 }
60
40 /** 61 /**
41 * Allocate the ciphertext with zeros. 62 * Allocate the ciphertext with zeros.
42 */ 63 */
diff --git a/src/main/java/org/gnunet/secretsharing/Parameters.java b/src/main/java/org/gnunet/secretsharing/Parameters.java
index cd0e5de..f5a9750 100644
--- a/src/main/java/org/gnunet/secretsharing/Parameters.java
+++ b/src/main/java/org/gnunet/secretsharing/Parameters.java
@@ -20,12 +20,15 @@
20 20
21package org.gnunet.secretsharing; 21package org.gnunet.secretsharing;
22 22
23import org.gnunet.voting.simulation.VotingParameters;
24
23import java.math.BigInteger; 25import java.math.BigInteger;
26import java.security.SecureRandom;
24 27
25/** 28/**
26 * Constants used by the crypto of the secretsharing API. 29 * Constants used by the crypto of the secretsharing API.
27 */ 30 */
28public interface Parameters { 31public abstract class Parameters {
29 /** 32 /**
30 * Size of the key. 33 * Size of the key.
31 */ 34 */
@@ -66,4 +69,26 @@ public interface Parameters {
66 "9cfd9f953674fab5d511e1c078fc72d72b34086f" + 69 "9cfd9f953674fab5d511e1c078fc72d72b34086f" +
67 "c82b4b951989eb85325cb203ff98df76bc366bba" + 70 "c82b4b951989eb85325cb203ff98df76bc366bba" +
68 "1d7024c3650f60d0da", 16); 71 "1d7024c3650f60d0da", 16);
72
73 public static BigInteger randomQ() {
74 SecureRandom r = new SecureRandom();
75 BigInteger y;
76 do {
77 y = new BigInteger(Parameters.elgamalBits - 1, r);
78 } while (y.compareTo(BigInteger.ONE) == 0 || y.compareTo(Parameters.elgamalQ) >= 0);
79 return y;
80 }
81
82 public static BigInteger modPowG(BigInteger exp) {
83 return elgamalG.modPow(exp, elgamalP);
84 }
85
86 public static BigInteger[] generateGenerators(int i) {
87 BigInteger[] generators = new BigInteger[i];
88 for (int j = 0; j < i; j++) {
89 // FIXME: this violates proper layering of the modules
90 generators[j] = VotingParameters.selectSubgroupGenerator(elgamalP, elgamalQ);
91 }
92 return generators;
93 }
69} 94}
diff --git a/src/main/java/org/gnunet/secretsharing/Plaintext.java b/src/main/java/org/gnunet/secretsharing/Plaintext.java
index fc4ac14..a3d87c8 100644
--- a/src/main/java/org/gnunet/secretsharing/Plaintext.java
+++ b/src/main/java/org/gnunet/secretsharing/Plaintext.java
@@ -26,6 +26,7 @@ import org.gnunet.util.BigIntegers;
26 26
27import java.math.BigInteger; 27import java.math.BigInteger;
28import java.security.SecureRandom; 28import java.security.SecureRandom;
29import java.util.Arrays;
29 30
30public class Plaintext implements Message { 31public class Plaintext implements Message {
31 @FixedSizeIntegerArray(signed = true, bitSize = 8, length = Parameters.elgamalBits / 8) 32 @FixedSizeIntegerArray(signed = true, bitSize = 8, length = Parameters.elgamalBits / 8)
@@ -39,17 +40,55 @@ public class Plaintext implements Message {
39 return plaintext; 40 return plaintext;
40 } 41 }
41 42
42 public long bruteForceDiscreteLog(final long l) { 43 /**
44 * Try all products of length l of the given generators.
45 *
46 * @param l number of factors
47 * @param generators different factors to chose from
48 * @return null if no solution was found, or an array of coefficients
49 */
50 public long[] bruteForceDiscreteLog(final long l, BigInteger[] generators) {
43 BigInteger needle = new BigInteger(1, bits); 51 BigInteger needle = new BigInteger(1, bits);
44 for (long i = -l; i <= l; i++) { 52 if (l == 0) {
45 BigInteger val; 53 if (needle.equals(BigInteger.ONE))
46 val = Parameters.elgamalG.modPow(BigInteger.valueOf(l), Parameters.elgamalP); 54 return new long[0];
47 if (val.equals(needle)) 55 return null;
48 return i;
49 } 56 }
50 throw new ArithmeticException(String.format("discrete log has no solution in range [%s, %s]", -l, l)); 57 long[] combo = new long[generators.length];
58 boolean success = bruteForceDiscreteLog(l, combo, needle, BigInteger.ONE, generators, 0);
59 if (success) {
60 return combo;
61 }
62 return null;
63 }
64
65 private static boolean bruteForceDiscreteLog(final long l, long[] combo,
66 final BigInteger needle, final BigInteger haystack,
67 BigInteger[] generators, final int genIdx) {
68 if (l == 0) {
69 combo[genIdx] = 0;
70 return haystack.equals(needle);
71 }
72 if (genIdx == generators.length - 1) {
73 combo[genIdx] = l;
74 BigInteger myHay = haystack.multiply(generators[genIdx].modPow(BigInteger.valueOf(l), Parameters.elgamalP)).mod(Parameters.elgamalP);
75 return myHay.equals(needle);
76 } else {
77 BigInteger myHay = haystack;
78 for (int i = 0; i <= l; i++) {
79 combo[genIdx] = i;
80 boolean success = bruteForceDiscreteLog(l - i, combo, needle, myHay, generators, genIdx + 1);
81 if (success) {
82 return true;
83 }
84 myHay = myHay.multiply(generators[genIdx]).mod(Parameters.elgamalP);
85 }
86 }
87 return false;
51 } 88 }
52 89
90
91
53 public Ciphertext encrypt(ThresholdPublicKey publicKey) { 92 public Ciphertext encrypt(ThresholdPublicKey publicKey) {
54 SecureRandom secureRandom = new SecureRandom(); 93 SecureRandom secureRandom = new SecureRandom();
55 BigInteger c_1; 94 BigInteger c_1;
@@ -74,4 +113,11 @@ public class Plaintext implements Message {
74 113
75 return ciphertext; 114 return ciphertext;
76 } 115 }
116
117 @Override
118 public String toString() {
119 return "Plaintext{" +
120 "bits=" + Arrays.toString(bits) +
121 '}';
122 }
77} 123}
diff --git a/src/main/java/org/gnunet/statistics/SetRequest.java b/src/main/java/org/gnunet/statistics/SetRequest.java
deleted file mode 100644
index c5fff66..0000000
--- a/src/main/java/org/gnunet/statistics/SetRequest.java
+++ /dev/null
@@ -1,50 +0,0 @@
1package org.gnunet.statistics;
2
3import org.gnunet.mq.Envelope;
4import org.gnunet.mq.MessageQueue;
5import org.gnunet.requests.Request;
6import org.gnunet.requests.RequestContainer;
7import org.gnunet.statistics.messages.SetMessage;
8import org.gnunet.util.RelativeTime;
9
10
11public class SetRequest extends Request {
12 /**
13 * Time after we give up on setting values in statistics
14 */
15 private static final RelativeTime SET_TIMEOUT = RelativeTime.SECOND.multiply(10);
16
17 private final static int SETFLAG_RELATIVE = 1;
18 private final static int SETFLAG_PERSIST = 2;
19 private final String subsystem;
20 private final String name;
21 private final boolean persist;
22 private final long value;
23 private final boolean relative;
24
25 public SetRequest(String subsystem, String name, long value, boolean relative, boolean persist) {
26 this.subsystem = subsystem;
27 this.name = name;
28 this.persist = persist;
29 this.value = value;
30 this.relative = relative;
31
32 }
33
34 @Override
35 public Envelope assembleRequest() {
36 SetMessage m = new SetMessage();
37 m.statisticName = name;
38 m.subsystemName = subsystem;
39 m.value = value;
40 if (relative)
41 m.flags |= SETFLAG_RELATIVE;
42 if (persist)
43 m.flags |= SETFLAG_PERSIST;
44 return new Envelope(m);
45 }
46
47 public void cancel() {
48 //To change body of implemented methods use File | Settings | File Templates.
49 }
50}
diff --git a/src/main/java/org/gnunet/util/BigIntegers.java b/src/main/java/org/gnunet/util/BigIntegers.java
index 473534f..f3f9fa7 100644
--- a/src/main/java/org/gnunet/util/BigIntegers.java
+++ b/src/main/java/org/gnunet/util/BigIntegers.java
@@ -31,18 +31,18 @@ public class BigIntegers {
31 31
32 /** 32 /**
33 * Serialize a BigInteger, but do not add an extra bit for a 33 * Serialize a BigInteger, but do not add an extra bit for a
34 * sign. 34 * signRaw.
35 * 35 *
36 * @param bigInteger big integer to serialize 36 * @param bigInteger big integer to serialize
37 * @param bits how many bits should the binary representation have? 37 * @param bits how many bits should the binary representation have?
38 * rounded up to the next multiple of 8. 38 * rounded up to the next multiple of 8.
39 * @return big endian representation of the given BigInteger, without a sign bit 39 * @return big endian representation of the given BigInteger, without a signRaw bit
40 */ 40 */
41 public static byte[] serializeUnsigned(BigInteger bigInteger, int bits) { 41 public static byte[] serializeUnsigned(BigInteger bigInteger, int bits) {
42 byte[] bytes = bigInteger.toByteArray(); 42 byte[] bytes = bigInteger.toByteArray();
43 int start; 43 int start;
44 Preconditions.checkArgument(bigInteger.bitCount() <= bits); 44 Preconditions.checkArgument(bigInteger.bitCount() <= bits);
45 // skip byte that was only added to fit the sign 45 // skip byte that was only added to fit the signRaw
46 if (bytes[0] == 0) { 46 if (bytes[0] == 0) {
47 start = 1; 47 start = 1;
48 } else { 48 } else {
diff --git a/src/main/java/org/gnunet/util/Connection.java b/src/main/java/org/gnunet/util/Connection.java
index cce32a4..d735b27 100644
--- a/src/main/java/org/gnunet/util/Connection.java
+++ b/src/main/java/org/gnunet/util/Connection.java
@@ -200,6 +200,7 @@ public class Connection {
200 return; 200 return;
201 } 201 }
202 } catch (IOException e) { 202 } catch (IOException e) {
203 logger.debug("got IOException ({}, {})", e.getClass().getName(), e.getMessage());
203 error(); 204 error();
204 return; 205 return;
205 } 206 }
diff --git a/src/main/java/org/gnunet/util/Strings.java b/src/main/java/org/gnunet/util/Strings.java
index c1c84f5..8de30ab 100644
--- a/src/main/java/org/gnunet/util/Strings.java
+++ b/src/main/java/org/gnunet/util/Strings.java
@@ -48,7 +48,7 @@ public class Strings {
48 while ((rpos < size) || (vbit > 0)) { 48 while ((rpos < size) || (vbit > 0)) {
49 if ((rpos < size) && (vbit < 5)) { 49 if ((rpos < size) && (vbit < 5)) {
50 byte b = data[(int) rpos++]; 50 byte b = data[(int) rpos++];
51 // convert (possibly negative) byte to int without sign extension 51 // convert (possibly negative) byte to int without signRaw extension
52 int s = b >= 0 ? b : (256 + b); 52 int s = b >= 0 ? b : (256 + b);
53 // eat 8 more bits 53 // eat 8 more bits
54 bits = (bits << 8) | s; 54 bits = (bits << 8) | s;
@@ -62,6 +62,8 @@ public class Strings {
62 sb.append(encTable.charAt((int) (bits >>> (vbit - 5)) & 31)); 62 sb.append(encTable.charAt((int) (bits >>> (vbit - 5)) & 31));
63 vbit -= 5; 63 vbit -= 5;
64 } 64 }
65 if (sb.length() != getEncodedStringLength(data.length))
66 throw new AssertionError();
65 return sb.toString(); 67 return sb.toString();
66 } 68 }
67 69
@@ -74,34 +76,44 @@ public class Strings {
74 * @return was the encoding successful? 76 * @return was the encoding successful?
75 */ 77 */
76 public static boolean stringToData(String string, byte[] outData) { 78 public static boolean stringToData(String string, byte[] outData) {
77 long rpos; 79 long rpos; // read position
78 long wpos; 80 long wpos; // write position
79 long bits; 81 long bits; // bits to write next
80 long vbit; 82 long vbit;
81 long ret; 83 long ret;
82 long shift; 84 long shift;
83 int enclen = string.length(); 85 int enclen = string.length();
84 int encodedLen = outData.length * 8; 86 int encodedLen = outData.length * 8;
87
88 if (0 == enclen) {
89 if (0 == outData.length)
90 return true;
91 return false;
92 }
93
94 wpos = outData.length;
95 rpos = enclen;
96
85 if (encodedLen % 5 > 0) { 97 if (encodedLen % 5 > 0) {
86 // padding! 98 // padding!
87 vbit = encodedLen % 5; 99 vbit = encodedLen % 5;
88 shift = 5 - vbit; 100 shift = 5 - vbit;
101 bits = (ret = getValue(string.charAt((int) (--rpos)))) >>> (5 - (encodedLen % 5));
89 } else { 102 } else {
90 vbit = 0; 103 vbit = 5;
91 shift = 0; 104 shift = 0;
105 bits = (ret = getValue(string.charAt((int) (--rpos))));
92 } 106 }
93 if ((encodedLen + shift) / 5 != enclen) { 107 if ((encodedLen + shift) / 5 != enclen) {
94 return false; 108 return false;
95 } 109 }
96
97 wpos = outData.length;
98 rpos = enclen;
99 bits = (ret = getValue(string.charAt((int) (--rpos)))) >> (5 - encodedLen % 5);
100 if (-1 == ret) { 110 if (-1 == ret) {
101 return false; 111 return false;
102 } 112 }
103 while (wpos > 0) { 113 while (wpos > 0) {
104 assert rpos > 0; 114 if (0 == rpos) {
115 throw new AssertionError("rpos=0, but wpos " + wpos);
116 }
105 bits = ((ret = getValue(string.charAt((int) (--rpos)))) << vbit) | bits; 117 bits = ((ret = getValue(string.charAt((int) (--rpos)))) << vbit) | bits;
106 if (-1 == ret) { 118 if (-1 == ret) {
107 return false; 119 return false;
@@ -109,12 +121,13 @@ public class Strings {
109 vbit += 5; 121 vbit += 5;
110 if (vbit >= 8) { 122 if (vbit >= 8) {
111 outData[(int)--wpos] = (byte)((char) bits); 123 outData[(int)--wpos] = (byte)((char) bits);
112 bits >>= 8; 124 bits >>>= 8;
113 vbit -= 8; 125 vbit -= 8;
114 } 126 }
115 } 127 }
116 assert(rpos == 0); 128 if (rpos != 0 || vbit != 0) {
117 assert(vbit == 0); 129 return false;
130 }
118 return true; 131 return true;
119 } 132 }
120 133
@@ -165,4 +178,8 @@ public class Strings {
165 } 178 }
166 return -1; 179 return -1;
167 } 180 }
181
182 public static byte[] stringToData(String s) {
183 return stringToData(s, getDecodedDataLength(s.length()));
184 }
168} 185}
diff --git a/src/main/java/org/gnunet/util/crypto/ContentWithPurposeMessage.java b/src/main/java/org/gnunet/util/crypto/ContentWithPurposeMessage.java
new file mode 100644
index 0000000..9aa09ef
--- /dev/null
+++ b/src/main/java/org/gnunet/util/crypto/ContentWithPurposeMessage.java
@@ -0,0 +1,17 @@
1package org.gnunet.util.crypto;
2
3import org.gnunet.construct.Message;
4import org.gnunet.construct.UInt32;
5import org.gnunet.construct.Union;
6
7/**
8 * Purpose header fields, together with content union.
9 */
10public class ContentWithPurposeMessage<M extends SignedContentMessage> implements Message {
11 @UInt32
12 public int size;
13 @UInt32
14 public int purpose;
15 @Union(tag = "purpose")
16 public M m;
17}
diff --git a/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java b/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java
index ce68525..46476d4 100644
--- a/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java
+++ b/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java
@@ -24,6 +24,10 @@ import org.gnunet.construct.FixedSizeIntegerArray;
24import org.gnunet.construct.Message; 24import org.gnunet.construct.Message;
25import org.gnunet.util.HashCode; 25import org.gnunet.util.HashCode;
26 26
27import java.io.ByteArrayOutputStream;
28import java.io.DataOutputStream;
29import java.io.IOError;
30import java.io.IOException;
27import java.math.BigInteger; 31import java.math.BigInteger;
28import java.security.SecureRandom; 32import java.security.SecureRandom;
29 33
@@ -56,29 +60,42 @@ public class EcdsaPrivateKey implements Message {
56 return privateKey; 60 return privateKey;
57 } 61 }
58 62
63 public EcdsaSignature sign(byte[] data, int purpose) {
64 return sign(data, purpose, getPublicKey());
65 }
66
67 public EcdsaSignature sign(byte[] data, int purpose, EcdsaPublicKey publicKey) {
68 ByteArrayOutputStream os = new ByteArrayOutputStream(data.length + 8);
69 DataOutputStream dos = new DataOutputStream(os);
70 try {
71 dos.writeInt(data.length);
72 dos.writeInt(purpose);
73 dos.write(data);
74 } catch (IOException e) {
75 throw new IOError(e);
76 }
77 return signRaw(publicKey, os.toByteArray());
78 }
79
59 /** 80 /**
60 * Sign the given data with this private key. Must include a purpose to mitigate 81 * Sign the given data with this private key.
61 * replay / copy and paste attacks.
62 * 82 *
63 * @param purpose purpose for the signature 83 * @param data data to signRaw
64 * @param data data to sign
65 * @return the signature over both the data and the purpose 84 * @return the signature over both the data and the purpose
66 */ 85 */
67 public EcdsaSignature sign(int purpose, byte[] data) { 86 public EcdsaSignature signRaw(byte[] data) {
68 return sign(getPublicKey(), purpose, data); 87 return signRaw(getPublicKey(), data);
69 } 88 }
70 89
71 /** 90 /**
72 * Sign the given data with this private key. Must include a purpose to mitigate 91 * Sign the given data with this private key.
73 * replay / copy and paste attacks.
74 * 92 *
75 * @param publicKey public key corresponding to this private key, supplying this parameter 93 * @param publicKey public key corresponding to this private key, supplying this parameter
76 * leads to better performance as the public key does not have to be derived 94 * leads to better performance as the public key does not have to be derived
77 * @param purpose purpose for the signature 95 * @param data data to signRaw
78 * @param data data to sign
79 * @return the signature over both the data and the purpose 96 * @return the signature over both the data and the purpose
80 */ 97 */
81 public EcdsaSignature sign(EcdsaPublicKey publicKey, int purpose, byte[] data) { 98 public EcdsaSignature signRaw(EcdsaPublicKey publicKey, byte[] data) {
82 EcdsaSignature signature = new EcdsaSignature(); 99 EcdsaSignature signature = new EcdsaSignature();
83 DsaPrng prng = new DsaPrng(d, data); 100 DsaPrng prng = new DsaPrng(d, data);
84 HashCode h = HashCode.hash(data); 101 HashCode h = HashCode.hash(data);
diff --git a/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java b/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java
index e02191d..9e01a6f 100644
--- a/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java
+++ b/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java
@@ -26,6 +26,10 @@ import org.gnunet.construct.Message;
26import org.gnunet.util.HashCode; 26import org.gnunet.util.HashCode;
27import org.gnunet.util.Strings; 27import org.gnunet.util.Strings;
28 28
29import java.io.ByteArrayOutputStream;
30import java.io.DataOutputStream;
31import java.io.IOError;
32import java.io.IOException;
29import java.math.BigInteger; 33import java.math.BigInteger;
30import java.security.SecureRandom; 34import java.security.SecureRandom;
31 35
@@ -57,11 +61,10 @@ public class EcdsaSignature implements Message {
57 * given data and purpose. 61 * given data and purpose.
58 * 62 *
59 * @param m message that was signed 63 * @param m message that was signed
60 * @param purpose purpose of the signature
61 * @param publicKey public key to check for 64 * @param publicKey public key to check for
62 * @return whether the signature is valid 65 * @return whether the signature is valid
63 */ 66 */
64 public boolean verify(byte[] m, int purpose, EcdsaPublicKey publicKey) { 67 public boolean verifyRaw(byte[] m, EcdsaPublicKey publicKey) {
65 if (publicKey.asPoint().isIdentity()) { 68 if (publicKey.asPoint().isIdentity()) {
66 throw new AssertionError(); 69 throw new AssertionError();
67 } 70 }
@@ -75,16 +78,6 @@ public class EcdsaSignature implements Message {
75 } 78 }
76 79
77 HashCode h = HashCode.hash(m); 80 HashCode h = HashCode.hash(m);
78 /*
79 byte[] zPart = new byte[32];
80 System.arraycopy(h.data, 0, zPart, 0, 32);
81 for (int i = 0; i < 16; i++) {
82 byte tmp = zPart[i];
83 zPart[i] = zPart[31-i];
84 zPart[31 - i] = tmp;
85 }
86 BigInteger z = new BigInteger(1, zPart);
87 */
88 BigInteger z = new BigInteger(1, h.data); 81 BigInteger z = new BigInteger(1, h.data);
89 BigInteger sCoeff = Ed25519.decodeScalar(s); 82 BigInteger sCoeff = Ed25519.decodeScalar(s);
90 BigInteger rCoeff = Ed25519.decodeScalar(r); 83 BigInteger rCoeff = Ed25519.decodeScalar(r);
@@ -98,6 +91,19 @@ public class EcdsaSignature implements Message {
98 return P.P0.mod(Ed25519.l).equals(rCoeff); 91 return P.P0.mod(Ed25519.l).equals(rCoeff);
99 } 92 }
100 93
94 public boolean verify(byte[] data, int purpose, EcdsaPublicKey publicKey) {
95 ByteArrayOutputStream os = new ByteArrayOutputStream(data.length + 8);
96 DataOutputStream dos = new DataOutputStream(os);
97 try {
98 dos.writeInt(data.length);
99 dos.writeInt(purpose);
100 dos.write(data);
101 } catch (IOException e) {
102 throw new IOError(e);
103 }
104 return verifyRaw(os.toByteArray(), publicKey);
105 }
106
101 /** 107 /**
102 * Load a signature from a string. 108 * Load a signature from a string.
103 * 109 *
diff --git a/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java b/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java
index bfc3fe4..0d9e218 100644
--- a/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java
+++ b/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java
@@ -20,41 +20,48 @@
20 20
21package org.gnunet.util.crypto; 21package org.gnunet.util.crypto;
22 22
23import org.gnunet.construct.Construct; 23import org.gnunet.construct.*;
24import org.gnunet.construct.Message;
25import org.gnunet.construct.NestedMessage;
26import org.gnunet.construct.UInt32;
27 24
28/** 25/**
29 * A message together with a signature on the message and its purpose. 26 * A message together with a signature on the message and its purpose.
30 */ 27 */
31public class EcdsaSignedMessage<M extends Message> implements Message { 28public class EcdsaSignedMessage<M extends SignedContentMessage> implements Message {
32 @NestedMessage 29 @NestedMessage
33 public EcdsaSignature signature; 30 public EcdsaSignature signature;
34 @UInt32 31
35 public int purpose; 32 @NestedMessage(newFrame = true)
36 @NestedMessage 33 public ContentWithPurposeMessage<M> cpm;
37 public M innerMessage; 34
38 35
39 public EcdsaSignedMessage() { 36 public EcdsaSignedMessage() {
40 // empty constructor required by org.gnunet.construct 37 // empty constructor required by org.gnunet.construct
41 } 38 }
42 39
43 public boolean verify(EcdsaPublicKey signerPublicKey) { 40 public boolean verify(EcdsaPublicKey signerPublicKey, Class<? extends SignedContentMessage> expectedClass) {
44 return signature.verify(Construct.toBinary(innerMessage), purpose, signerPublicKey); 41 if (!expectedClass.isInstance(cpm.m)) {
42 return false;
43 }
44 System.out.println("right class");
45 byte[] data = Construct.toBinary(cpm);
46 return signature.verifyRaw(data, signerPublicKey);
45 } 47 }
46 48
47 public static <T extends Message> EcdsaSignedMessage<T> signMessage(T innerMessage, int purpose, 49 public EcdsaSignedMessage(M message, EcdsaPrivateKey privateKey,
48 EcdsaPrivateKey privateKey, EcdsaPublicKey publicKey) { 50 EcdsaPublicKey publicKey) {
49 EcdsaSignedMessage<T> esm = new EcdsaSignedMessage<T>(); 51 cpm = new ContentWithPurposeMessage();
50 esm.purpose = purpose; 52 cpm.m = message;
51 esm.innerMessage = innerMessage; 53 Construct.patch(cpm);
52 esm.signature = privateKey.sign(purpose, Construct.toBinary(innerMessage)); 54 byte[] data = Construct.toBinary(cpm);
53 return esm; 55 signature = privateKey.signRaw(publicKey, data);
54 } 56 }
55 57
56 public static <T extends Message> EcdsaSignedMessage<T> signMessage(T innerMessage, int purpose, 58 public EcdsaSignedMessage(M message, EcdsaPrivateKey privateKey) {
57 EcdsaPrivateKey privateKey) { 59 this(message, privateKey, privateKey.getPublicKey());
58 return signMessage(innerMessage, purpose, privateKey, privateKey.getPublicKey());
59 } 60 }
61
62 public M get() {
63 return cpm.m;
64 }
65
60} 66}
67
diff --git a/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java b/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java
index 8424dc6..921d625 100644
--- a/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java
+++ b/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java
@@ -22,6 +22,10 @@ package org.gnunet.util.crypto;
22import org.gnunet.construct.FixedSizeIntegerArray; 22import org.gnunet.construct.FixedSizeIntegerArray;
23import org.gnunet.construct.Message; 23import org.gnunet.construct.Message;
24 24
25import java.io.ByteArrayOutputStream;
26import java.io.DataOutputStream;
27import java.io.IOError;
28import java.io.IOException;
25import java.math.BigInteger; 29import java.math.BigInteger;
26import java.nio.ByteBuffer; 30import java.nio.ByteBuffer;
27import java.security.MessageDigest; 31import java.security.MessageDigest;
@@ -32,8 +36,8 @@ public class EddsaPrivateKey implements Message {
32 @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32) 36 @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
33 public byte[] d; 37 public byte[] d;
34 38
35 public EddsaSignature sign(int purpose, byte[] m) { 39 public EddsaSignature signRaw(byte[] m) {
36 return sign(getPublicKey(), purpose, m); 40 return signRaw(getPublicKey(), m);
37 } 41 }
38 42
39 /** 43 /**
@@ -42,11 +46,10 @@ public class EddsaPrivateKey implements Message {
42 * 46 *
43 * @param publicKey public key corresponding to this private key, supplying this parameter 47 * @param publicKey public key corresponding to this private key, supplying this parameter
44 * leads to better performance as the public key does not have to be derived 48 * leads to better performance as the public key does not have to be derived
45 * @param purpose purpose for the signature 49 * @param m data to signRaw
46 * @param m data to sign
47 * @return the signature over both the data and the purpose 50 * @return the signature over both the data and the purpose
48 */ 51 */
49 public EddsaSignature sign(EddsaPublicKey publicKey, int purpose, byte[] m) { 52 public EddsaSignature signRaw(EddsaPublicKey publicKey, byte[] m) {
50 if (!publicKey.asPoint().isOnCurve()) { 53 if (!publicKey.asPoint().isOnCurve()) {
51 throw new AssertionError(); 54 throw new AssertionError();
52 } 55 }
@@ -115,6 +118,24 @@ public class EddsaPrivateKey implements Message {
115 return a; 118 return a;
116 } 119 }
117 120
121 public EddsaSignature sign(byte[] data, int purpose) {
122 return sign(data, purpose, getPublicKey());
123 }
124
125 public EddsaSignature sign(byte[] data, int purpose, EddsaPublicKey publicKey) {
126 ByteArrayOutputStream os = new ByteArrayOutputStream(data.length + 8);
127 DataOutputStream dos = new DataOutputStream(os);
128 try {
129 dos.writeInt(data.length);
130 dos.writeInt(purpose);
131 dos.write(data);
132 } catch (IOException e) {
133 throw new IOError(e);
134 }
135 return signRaw(publicKey, os.toByteArray());
136 }
137
138
118 /** 139 /**
119 * Get the public key for this private key. 140 * Get the public key for this private key.
120 * 141 *
diff --git a/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java b/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java
index aa43a0b..be5a0f8 100644
--- a/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java
+++ b/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java
@@ -24,6 +24,10 @@ import org.gnunet.construct.FixedSizeIntegerArray;
24import org.gnunet.construct.Message; 24import org.gnunet.construct.Message;
25import org.gnunet.util.Strings; 25import org.gnunet.util.Strings;
26 26
27import java.io.ByteArrayOutputStream;
28import java.io.DataOutputStream;
29import java.io.IOError;
30import java.io.IOException;
27import java.security.SecureRandom; 31import java.security.SecureRandom;
28import java.util.Arrays; 32import java.util.Arrays;
29 33
diff --git a/src/main/java/org/gnunet/util/crypto/EddsaSignature.java b/src/main/java/org/gnunet/util/crypto/EddsaSignature.java
index 56b5995..ff78908 100644
--- a/src/main/java/org/gnunet/util/crypto/EddsaSignature.java
+++ b/src/main/java/org/gnunet/util/crypto/EddsaSignature.java
@@ -25,6 +25,10 @@ import org.gnunet.construct.FixedSizeIntegerArray;
25import org.gnunet.construct.Message; 25import org.gnunet.construct.Message;
26import org.gnunet.util.Strings; 26import org.gnunet.util.Strings;
27 27
28import java.io.ByteArrayOutputStream;
29import java.io.DataOutputStream;
30import java.io.IOError;
31import java.io.IOException;
28import java.math.BigInteger; 32import java.math.BigInteger;
29import java.nio.ByteBuffer; 33import java.nio.ByteBuffer;
30import java.security.SecureRandom; 34import java.security.SecureRandom;
@@ -58,11 +62,10 @@ public class EddsaSignature implements Message {
58 * Verify the signature on a message with given purpose. 62 * Verify the signature on a message with given purpose.
59 * 63 *
60 * @param m 64 * @param m
61 * @param purpose
62 * @param publicKey 65 * @param publicKey
63 * @return 66 * @return
64 */ 67 */
65 public boolean verify(byte[] m, int purpose, EddsaPublicKey publicKey) { 68 public boolean verifyRaw(byte[] m, EddsaPublicKey publicKey) {
66 Ed25519 R = Ed25519.decode(r); 69 Ed25519 R = Ed25519.decode(r);
67 if (!R.isOnCurve()) 70 if (!R.isOnCurve())
68 return false; 71 return false;
@@ -99,6 +102,20 @@ public class EddsaSignature implements Message {
99 return sig; 102 return sig;
100 } 103 }
101 104
105
106 public boolean verify(byte[] data, int purpose, EddsaPublicKey publicKey) {
107 ByteArrayOutputStream os = new ByteArrayOutputStream(data.length + 8);
108 DataOutputStream dos = new DataOutputStream(os);
109 try {
110 dos.writeInt(data.length);
111 dos.writeInt(purpose);
112 dos.write(data);
113 } catch (IOException e) {
114 throw new IOError(e);
115 }
116 return verifyRaw(os.toByteArray(), publicKey);
117 }
118
102 /** 119 /**
103 * Return a signature that is invalid with very, very high probability. 120 * Return a signature that is invalid with very, very high probability.
104 * 121 *
diff --git a/src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java b/src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java
new file mode 100644
index 0000000..04a2965
--- /dev/null
+++ b/src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java
@@ -0,0 +1,63 @@
1/*
2 This file is part of GNUnet.
3 (C) 2012, 2013 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.util.crypto;
22
23import org.gnunet.construct.Construct;
24import org.gnunet.construct.Message;
25import org.gnunet.construct.NestedMessage;
26
27/**
28 * A message together with a signature on the message and its purpose.
29 */
30public class EddsaSignedMessage implements Message {
31 @NestedMessage
32 public EddsaSignature signature;
33
34 @NestedMessage(newFrame = true)
35 public ContentWithPurposeMessage cpm;
36
37
38 public EddsaSignedMessage() {
39 // empty constructor required by org.gnunet.construct
40 }
41
42 public boolean verify(EddsaPublicKey signerPublicKey, Class<? extends SignedContentMessage> expectedClass) {
43 if (!expectedClass.isInstance(cpm.m)) {
44 return false;
45 }
46 byte[] data = Construct.toBinary(cpm);
47 return signature.verifyRaw(data, signerPublicKey);
48 }
49
50 public EddsaSignedMessage(SignedContentMessage message, EddsaPrivateKey privateKey,
51 EddsaPublicKey publicKey) {
52 cpm = new ContentWithPurposeMessage();
53 cpm.m = message;
54 Construct.patch(cpm);
55 byte[] data = Construct.toBinary(cpm);
56 signature = privateKey.signRaw(publicKey, data);
57 }
58
59 public EddsaSignedMessage(SignedContentMessage message, EddsaPrivateKey privateKey) {
60 this(message, privateKey, privateKey.getPublicKey());
61 }
62
63}
diff --git a/src/main/java/org/gnunet/util/crypto/SignedContentMessage.java b/src/main/java/org/gnunet/util/crypto/SignedContentMessage.java
new file mode 100644
index 0000000..77dd300
--- /dev/null
+++ b/src/main/java/org/gnunet/util/crypto/SignedContentMessage.java
@@ -0,0 +1,8 @@
1package org.gnunet.util.crypto;
2
3
4import org.gnunet.construct.MessageUnion;
5
6public interface SignedContentMessage extends MessageUnion {
7 // empty, this is a tag interface
8}
diff --git a/src/main/java/org/gnunet/voting/Ballot.java b/src/main/java/org/gnunet/voting/Ballot.java
index 92ec7da..a470ac0 100644
--- a/src/main/java/org/gnunet/voting/Ballot.java
+++ b/src/main/java/org/gnunet/voting/Ballot.java
@@ -27,6 +27,7 @@ import com.google.common.collect.BiMap;
27import com.google.common.collect.HashBiMap; 27import com.google.common.collect.HashBiMap;
28import com.google.common.collect.Maps; 28import com.google.common.collect.Maps;
29import com.google.common.primitives.Longs; 29import com.google.common.primitives.Longs;
30import org.gnunet.secretsharing.Parameters;
30import org.gnunet.secretsharing.ThresholdPublicKey; 31import org.gnunet.secretsharing.ThresholdPublicKey;
31import org.gnunet.util.AbsoluteTime; 32import org.gnunet.util.AbsoluteTime;
32import org.gnunet.util.Configuration; 33import org.gnunet.util.Configuration;
@@ -37,7 +38,10 @@ import org.gnunet.util.crypto.EcdsaPublicKey;
37import org.gnunet.util.crypto.EcdsaSignature; 38import org.gnunet.util.crypto.EcdsaSignature;
38import org.gnunet.util.crypto.EddsaSignature; 39import org.gnunet.util.crypto.EddsaSignature;
39import org.gnunet.voting.messages.KeyQueryResponseMessage; 40import org.gnunet.voting.messages.KeyQueryResponseMessage;
41import org.gnunet.voting.simulation.VotingParameters;
42import org.omg.CORBA.DynAnyPackage.Invalid;
40 43
44import java.math.BigInteger;
41import java.security.MessageDigest; 45import java.security.MessageDigest;
42import java.security.NoSuchAlgorithmException; 46import java.security.NoSuchAlgorithmException;
43import java.util.*; 47import java.util.*;
@@ -129,6 +133,11 @@ public class Ballot {
129 SortedMap<String,KeyQueryResponseMessage> thresholdPublicKeys; 133 SortedMap<String,KeyQueryResponseMessage> thresholdPublicKeys;
130 134
131 /** 135 /**
136 * Generators, one for each choice.
137 */
138 BigInteger generators[];
139
140 /**
132 * Threshold for the election. 141 * Threshold for the election.
133 */ 142 */
134 public int threshold; 143 public int threshold;
@@ -310,6 +319,19 @@ public class Ballot {
310 m.signedGuidKey.publicKey = ThresholdPublicKey.fromString(e.getValue()); 319 m.signedGuidKey.publicKey = ThresholdPublicKey.fromString(e.getValue());
311 thresholdPublicKeys.put(alias, m); 320 thresholdPublicKeys.put(alias, m);
312 } 321 }
322 // If there's one generator, the others have to be there, too.
323 if (cfg.haveValue("generators", "g0")) {
324 generators = new BigInteger[choices.size()];
325 for (int i = 0; i < choices.size(); i++) {
326 Optional<String> optG = cfg.getValueString("generators", "g"+i);
327 if (!optG.isPresent()) {
328 throw new InvalidBallotException(
329 String.format("Generator %s is missing. Please issue the ballot correctlly", i));
330 }
331 generators[i] = new BigInteger(optG.get(), 16);
332 }
333 }
334
313 } 335 }
314 336
315 /** 337 /**
@@ -387,6 +409,9 @@ public class Ballot {
387 */ 409 */
388 public void encodeChoice(String choice, ThresholdPublicKey thresholdPublicKey, 410 public void encodeChoice(String choice, ThresholdPublicKey thresholdPublicKey,
389 EcdsaPrivateKey voterPrivateKey) { 411 EcdsaPrivateKey voterPrivateKey) {
412 if (null == generators || generators.length != choices.size()) {
413 throw new InvalidBallotException("Can't encrypt vote without valid generators.");
414 }
390 int choiceId = -1; 415 int choiceId = -1;
391 int i = 0; 416 int i = 0;
392 for (String possibleChoice : choices) { 417 for (String possibleChoice : choices) {
@@ -396,7 +421,8 @@ public class Ballot {
396 i++; 421 i++;
397 } 422 }
398 voterPub = voterPrivateKey.getPublicKey(); 423 voterPub = voterPrivateKey.getPublicKey();
399 encryptedVote = EncryptedVote.fromChoice(choiceId, thresholdPublicKey, voterPrivateKey, voterPub); 424 encryptedVote = EncryptedVote.fromChoice(choiceId, thresholdPublicKey, voterPrivateKey, voterPub,
425 generators);
400 System.out.println("voter encrypted vote, ciphertext: " + encryptedVote.v.toString()); 426 System.out.println("voter encrypted vote, ciphertext: " + encryptedVote.v.toString());
401 System.out.println("threshold key (of voter): " + thresholdPublicKey.toString()); 427 System.out.println("threshold key (of voter): " + thresholdPublicKey.toString());
402 } 428 }
@@ -452,6 +478,11 @@ public class Ballot {
452 cfg.setValueString("threshold-pubkey-sigs", e.getKey(), 478 cfg.setValueString("threshold-pubkey-sigs", e.getKey(),
453 e.getValue().signature.toString()); 479 e.getValue().signature.toString());
454 } 480 }
481 if (generators != null) {
482 for (int i = 0; i < generators.length; i++) {
483 cfg.setValueString("generators", "g"+i, generators[i].toString(16));
484 }
485 }
455 return cfg; 486 return cfg;
456 } 487 }
457 488
@@ -606,13 +637,18 @@ public class Ballot {
606 637
607 /** 638 /**
608 * Add the issuer to the ballot, and sign the election information in the ballot. 639 * Add the issuer to the ballot, and sign the election information in the ballot.
640 * Also selects the generators for every choice.
609 * 641 *
610 * @param privateKey private key of the issuer 642 * @param privateKey private key of the issuer
611 */ 643 */
612 public void issue(EcdsaPrivateKey privateKey) { 644 public void issue(EcdsaPrivateKey privateKey) {
645 generators = new BigInteger[choices.size()];
646 for (int i = 0; i < choices.size(); i++) {
647 generators[i] = VotingParameters.selectSubgroupGenerator(Parameters.elgamalP, Parameters.elgamalQ);
648 }
613 issuerPub = privateKey.getPublicKey(); 649 issuerPub = privateKey.getPublicKey();
614 // FIXME: purpose 650 // FIXME: purpose
615 issuerSig = privateKey.sign(0, getBallotGuid().data); 651 issuerSig = privateKey.sign(getBallotGuid().data, 0);
616 } 652 }
617 653
618 /** 654 /**
diff --git a/src/main/java/org/gnunet/voting/BallotTool.java b/src/main/java/org/gnunet/voting/BallotTool.java
index d03e0ea..c65c361 100644
--- a/src/main/java/org/gnunet/voting/BallotTool.java
+++ b/src/main/java/org/gnunet/voting/BallotTool.java
@@ -146,9 +146,9 @@ public class BallotTool extends Program {
146 private Mesh mesh; 146 private Mesh mesh;
147 147
148 /** 148 /**
149 * A tunnel to 'currentAuthority' or null. 149 * A channel to 'currentAuthority' or null.
150 */ 150 */
151 private Mesh.Tunnel tunnel; 151 private Mesh.Channel channel;
152 152
153 /** 153 /**
154 * The authority we are currently communicating with. 154 * The authority we are currently communicating with.
@@ -156,7 +156,7 @@ public class BallotTool extends Program {
156 private PeerIdentity currentAuthority; 156 private PeerIdentity currentAuthority;
157 157
158 /** 158 /**
159 * Are we finished with communicating over the mesh tunnel and don't need to worry about 159 * Are we finished with communicating over the mesh channel and don't need to worry about
160 * disconnection? 160 * disconnection?
161 */ 161 */
162 private boolean tunnelCommunicationFinished; 162 private boolean tunnelCommunicationFinished;
@@ -165,11 +165,11 @@ public class BallotTool extends Program {
165 165
166 public class BallotTunnelEndHandler implements TunnelEndHandler { 166 public class BallotTunnelEndHandler implements TunnelEndHandler {
167 @Override 167 @Override
168 public void onTunnelEnd(final Mesh.Tunnel tunnel) { 168 public void onChannelEnd(final Mesh.Channel channel) {
169 // FIXME: just re-running 'doCommands' is a bit of a hack 169 // FIXME: just re-running 'doCommands' is a bit of a hack
170 BallotTool.this.tunnel = null; 170 BallotTool.this.channel = null;
171 if (!tunnelCommunicationFinished) { 171 if (!tunnelCommunicationFinished) {
172 logger.warn("mesh tunnel disconnected, but operation not finished"); 172 logger.warn("mesh channel disconnected, but operation not finished");
173 Scheduler.addDelayed(tunnelReconnectBackoff, new Scheduler.Task() { 173 Scheduler.addDelayed(tunnelReconnectBackoff, new Scheduler.Task() {
174 @Override 174 @Override
175 public void run(Scheduler.RunContext ctx) { 175 public void run(Scheduler.RunContext ctx) {
@@ -182,14 +182,14 @@ public class BallotTool extends Program {
182 } 182 }
183 183
184 /** 184 /**
185 * Destroy the tunnel to the authority as well 185 * Destroy the channel to the authority as well
186 * as the mesh handle. 186 * as the mesh handle.
187 */ 187 */
188 private void endMesh() { 188 private void endMesh() {
189 tunnelCommunicationFinished = true; 189 tunnelCommunicationFinished = true;
190 if (null != tunnel) { 190 if (null != channel) {
191 tunnel.destroy(); 191 channel.destroy();
192 tunnel = null; 192 channel = null;
193 } 193 }
194 if (null != mesh) { 194 if (null != mesh) {
195 mesh.destroy(); 195 mesh.destroy();
@@ -260,7 +260,7 @@ public class BallotTool extends Program {
260 public void visit(SubmitFailureMessage m) { 260 public void visit(SubmitFailureMessage m) {
261 System.out.println("vote not submitted: " + m.reason); 261 System.out.println("vote not submitted: " + m.reason);
262 if (m.signedAuthorityTime != null) { 262 if (m.signedAuthorityTime != null) {
263 // FIXME: verify 263 // FIXME: verifyRaw
264 System.out.println("authority time: " + 264 System.out.println("authority time: " +
265 AbsoluteTime.fromNetwork(m.signedAuthorityTime.time).toFancyString()); 265 AbsoluteTime.fromNetwork(m.signedAuthorityTime.time).toFancyString());
266 } 266 }
@@ -323,11 +323,11 @@ public class BallotTool extends Program {
323 currentAuthority = remainingAuthorities.get(r.nextInt(remainingAuthorities.size())); 323 currentAuthority = remainingAuthorities.get(r.nextInt(remainingAuthorities.size()));
324 System.out.println("registering ballot with authority " + currentAuthority.toString()); 324 System.out.println("registering ballot with authority " + currentAuthority.toString());
325 mesh = new Mesh(getConfiguration(), new BallotTunnelEndHandler(), new BallotRegisterReceiver()); 325 mesh = new Mesh(getConfiguration(), new BallotTunnelEndHandler(), new BallotRegisterReceiver());
326 tunnel = mesh.createTunnel(currentAuthority, TallyAuthorityDaemon.MESH_PORT, true, true); 326 channel = mesh.createTunnel(currentAuthority, TallyAuthorityDaemon.MESH_PORT, true, true);
327 BallotRegisterRequestMessage m = new BallotRegisterRequestMessage(); 327 BallotRegisterRequestMessage m = new BallotRegisterRequestMessage();
328 CompressedConfig ccfg = new CompressedConfig(ballot.toConfiguration()); 328 CompressedConfig ccfg = new CompressedConfig(ballot.toConfiguration());
329 m.compressedBallotConfig = ccfg.compressedData; 329 m.compressedBallotConfig = ccfg.compressedData;
330 tunnel.send(m); 330 channel.send(m);
331 return; 331 return;
332 } 332 }
333 if (issue) { 333 if (issue) {
@@ -368,7 +368,7 @@ public class BallotTool extends Program {
368 System.out.println("submitting to authority " + authority.toString()); 368 System.out.println("submitting to authority " + authority.toString());
369 currentAuthority = authority; 369 currentAuthority = authority;
370 mesh = new Mesh(cfg, new BallotTunnelEndHandler(), new SubmitReceiver()); 370 mesh = new Mesh(cfg, new BallotTunnelEndHandler(), new SubmitReceiver());
371 tunnel = mesh.createTunnel(authority, TallyAuthorityDaemon.MESH_PORT, true, true, null); 371 channel = mesh.createTunnel(authority, TallyAuthorityDaemon.MESH_PORT, true, true, null);
372 SubmitMessage m = new SubmitMessage(); 372 SubmitMessage m = new SubmitMessage();
373 if (ballot.voterPub == null) { 373 if (ballot.voterPub == null) {
374 throw new InvalidBallotException("no voter in ballot"); 374 throw new InvalidBallotException("no voter in ballot");
@@ -384,7 +384,7 @@ public class BallotTool extends Program {
384 throw new InvalidBallotException("no encrypted vote in ballot"); 384 throw new InvalidBallotException("no encrypted vote in ballot");
385 } 385 }
386 m.encryptedVote = ballot.encryptedVote; 386 m.encryptedVote = ballot.encryptedVote;
387 tunnel.send(m); 387 channel.send(m);
388 return; 388 return;
389 } 389 }
390 if (verify) { 390 if (verify) {
@@ -402,10 +402,10 @@ public class BallotTool extends Program {
402 currentAuthority = remainingAuthorities.get(r.nextInt(remainingAuthorities.size())); 402 currentAuthority = remainingAuthorities.get(r.nextInt(remainingAuthorities.size()));
403 System.out.println("querying authority " + currentAuthority.toString()); 403 System.out.println("querying authority " + currentAuthority.toString());
404 mesh = new Mesh(cfg, new BallotTunnelEndHandler(), new QueryReceiver()); 404 mesh = new Mesh(cfg, new BallotTunnelEndHandler(), new QueryReceiver());
405 tunnel = mesh.createTunnel(currentAuthority, TallyAuthorityDaemon.MESH_PORT, true, true, null); 405 channel = mesh.createTunnel(currentAuthority, TallyAuthorityDaemon.MESH_PORT, true, true, null);
406 ResultQueryMessage m = new ResultQueryMessage(); 406 ResultQueryMessage m = new ResultQueryMessage();
407 m.ballotGuid = ballot.getBallotGuid(); 407 m.ballotGuid = ballot.getBallotGuid();
408 tunnel.send(m); 408 channel.send(m);
409 return; 409 return;
410 } 410 }
411 if (requestKey) { 411 if (requestKey) {
@@ -418,10 +418,10 @@ public class BallotTool extends Program {
418 currentAuthority = remainingAuthorities.get(r.nextInt(remainingAuthorities.size())); 418 currentAuthority = remainingAuthorities.get(r.nextInt(remainingAuthorities.size()));
419 System.out.println("asking authority for key " + currentAuthority.toString()); 419 System.out.println("asking authority for key " + currentAuthority.toString());
420 mesh = new Mesh(cfg, new BallotTunnelEndHandler(), new PublicKeyReceiver()); 420 mesh = new Mesh(cfg, new BallotTunnelEndHandler(), new PublicKeyReceiver());
421 tunnel = mesh.createTunnel(currentAuthority, TallyAuthorityDaemon.MESH_PORT, true, true, null); 421 channel = mesh.createTunnel(currentAuthority, TallyAuthorityDaemon.MESH_PORT, true, true, null);
422 KeyQueryMessage m = new KeyQueryMessage(); 422 KeyQueryMessage m = new KeyQueryMessage();
423 m.ballotGuid = ballot.getBallotGuid(); 423 m.ballotGuid = ballot.getBallotGuid();
424 tunnel.send(m); 424 channel.send(m);
425 return; 425 return;
426 } 426 }
427 setReturnValue(1); 427 setReturnValue(1);
diff --git a/src/main/java/org/gnunet/voting/ChaumPedersenZkp.java b/src/main/java/org/gnunet/voting/ChaumPedersenZkp.java
new file mode 100644
index 0000000..dcfb60a
--- /dev/null
+++ b/src/main/java/org/gnunet/voting/ChaumPedersenZkp.java
@@ -0,0 +1,75 @@
1/*
2 This file is part of GNUnet.
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.voting;
22
23import org.gnunet.construct.FixedSizeIntegerArray;
24import org.gnunet.construct.Message;
25import org.gnunet.secretsharing.Parameters;
26
27import java.math.BigInteger;
28
29/**
30 * Proof in zero knowledge of dlog equality.
31 * Proves log_g(x) = log_h(y) = alpha
32 * FIXME: get the details right, the Cramers voting paper uses a proof that is a
33 * FIXME: bit different from the plain chaum pedersen proof
34 */
35public class ChaumPedersenZkp implements Message {
36 @FixedSizeIntegerArray(signed = true, bitSize = 8, length = Parameters.elgamalBits / 8)
37 public byte[] commit_a;
38 @FixedSizeIntegerArray(signed = true, bitSize = 8, length = Parameters.elgamalBits / 8)
39 public byte[] commit_b;
40
41 @FixedSizeIntegerArray(signed = true, bitSize = 8, length = Parameters.elgamalBits / 8)
42 public byte[] challenge_d;
43
44 @FixedSizeIntegerArray(signed = true, bitSize = 8, length = Parameters.elgamalBits / 8)
45 public byte[] response_r;
46
47
48 /**
49 * Verify the simulated proof. That is, don't check
50 * if the challenge was actually computed correctly from the commits.
51 */
52 public boolean verifySim(BigInteger x, BigInteger y, BigInteger coeffG, BigInteger h) {
53 BigInteger a = new BigInteger(1, commit_a);
54 BigInteger b = new BigInteger(1, commit_b);
55 BigInteger d = new BigInteger(1, challenge_d);
56 BigInteger r = new BigInteger(1, response_r);
57 BigInteger g = Parameters.elgamalG;
58 BigInteger p = Parameters.elgamalP;
59
60 if (!b.equals(h.modPow(r, p).multiply(y.multiply(coeffG.modInverse(p)).modPow(d, p)).mod(p))) {
61 System.out.println("b not equal");
62 return false;
63 }
64
65 if (!a.equals(g.modPow(r, p).multiply(x.modPow(d, p)).mod(p))) {
66 System.out.println("a not equal");
67 return false;
68 }
69
70
71 return true;
72 }
73}
74
75
diff --git a/src/main/java/org/gnunet/voting/DisjunctionZkp.java b/src/main/java/org/gnunet/voting/DisjunctionZkp.java
new file mode 100644
index 0000000..cfa823c
--- /dev/null
+++ b/src/main/java/org/gnunet/voting/DisjunctionZkp.java
@@ -0,0 +1,64 @@
1/*
2 This file is part of GNUnet.
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21package org.gnunet.voting;
22
23import org.gnunet.construct.*;
24import org.gnunet.secretsharing.Parameters;
25
26import java.math.BigInteger;
27import java.security.MessageDigest;
28import java.security.NoSuchAlgorithmException;
29
30/**
31 * Disjunction of Chaum Pedersen ZKPs.
32 */
33public class DisjunctionZkp implements Message {
34 @UInt64
35 public int numProofs;
36 @FixedSizeIntegerArray(signed = true, bitSize = 8, length = Parameters.elgamalBits / 8)
37 public byte[] challenge_c;
38 @VariableSizeArray(lengthField = "numProofs")
39 public ChaumPedersenZkp[] chaumPedersenZkps;
40
41 public boolean verifyChallenge() {
42 BigInteger c_actual = new BigInteger(1, challenge_c);
43 BigInteger c_expected = BigInteger.ZERO;
44 for (ChaumPedersenZkp chaumPedersenZkp : chaumPedersenZkps) {
45 BigInteger d = new BigInteger(1, chaumPedersenZkp.challenge_d);
46 c_expected = c_expected.add(d).mod(Parameters.elgamalQ);
47 }
48 return c_actual.equals(c_expected) && computeChallengeFromCommits().equals(c_actual);
49 }
50
51 public BigInteger computeChallengeFromCommits() {
52 MessageDigest digest;
53 try {
54 digest = MessageDigest.getInstance("SHA-512");
55 } catch (NoSuchAlgorithmException e) {
56 throw new RuntimeException("crypto algorithm 'SHA-512' required but not provided");
57 }
58 for (ChaumPedersenZkp chaumPedersenZkp : chaumPedersenZkps) {
59 digest.update(chaumPedersenZkp.commit_a);
60 digest.update(chaumPedersenZkp.commit_b);
61 }
62 return (new BigInteger(digest.digest())).mod(Parameters.elgamalQ);
63 }
64}
diff --git a/src/main/java/org/gnunet/voting/EncryptedVote.java b/src/main/java/org/gnunet/voting/EncryptedVote.java
index 6fa0d1f..aab4e2b 100644
--- a/src/main/java/org/gnunet/voting/EncryptedVote.java
+++ b/src/main/java/org/gnunet/voting/EncryptedVote.java
@@ -22,49 +22,33 @@ package org.gnunet.voting;
22 22
23 23
24import com.google.common.base.Optional; 24import com.google.common.base.Optional;
25import org.gnunet.construct.Construct;
25import org.gnunet.construct.Message; 26import org.gnunet.construct.Message;
26import org.gnunet.construct.NestedMessage; 27import org.gnunet.construct.NestedMessage;
27import org.gnunet.secretsharing.Ciphertext; 28import org.gnunet.secretsharing.Ciphertext;
28import org.gnunet.secretsharing.Plaintext; 29import org.gnunet.secretsharing.Parameters;
29import org.gnunet.secretsharing.ThresholdPublicKey; 30import org.gnunet.secretsharing.ThresholdPublicKey;
31import org.gnunet.util.BigIntegers;
30import org.gnunet.util.Configuration; 32import org.gnunet.util.Configuration;
33import org.gnunet.util.Strings;
31import org.gnunet.util.crypto.EcdsaPrivateKey; 34import org.gnunet.util.crypto.EcdsaPrivateKey;
32import org.gnunet.util.crypto.EcdsaPublicKey; 35import org.gnunet.util.crypto.EcdsaPublicKey;
33import org.gnunet.voting.simulation.Voter; 36import org.gnunet.util.crypto.SignedContentMessage;
34import org.omg.CORBA.DynAnyPackage.Invalid; 37import org.gnunet.voting.simulation.CryptoUtil;
35 38
36import java.math.BigInteger; 39import java.math.BigInteger;
40import java.util.Arrays;
37 41
38public class EncryptedVote implements Message { 42public class EncryptedVote implements Message, SignedContentMessage {
39 @NestedMessage 43 @NestedMessage
40 public Ciphertext v; 44 public Ciphertext v;
41 45
46 @NestedMessage
47 public DisjunctionZkp disjunctionZkp;
42 48
43 @NestedMessage 49 @NestedMessage
44 public EcdsaPublicKey voterPublicKey; 50 public EcdsaPublicKey voterPublicKey;
45 51
46 @Override
47 public boolean equals(Object o) {
48 if (this == o) return true;
49 if (o == null || getClass() != o.getClass()) return false;
50
51 EncryptedVote that = (EncryptedVote) o;
52
53 if (v != null ? !v.equals(that.v) : that.v != null) return false;
54 if (voterPublicKey != null ? !voterPublicKey.equals(that.voterPublicKey) : that.voterPublicKey != null)
55 return false;
56
57 return true;
58 }
59
60 @Override
61 public int hashCode() {
62 int result = v != null ? v.hashCode() : 0;
63 result = 31 * result + (voterPublicKey != null ? voterPublicKey.hashCode() : 0);
64 return result;
65 }
66
67
68 /** 52 /**
69 * Construct an EncryptedVote by parsing it from the configuration. 53 * Construct an EncryptedVote by parsing it from the configuration.
70 * The voter public key must be passed separately. 54 * The voter public key must be passed separately.
@@ -78,30 +62,127 @@ public class EncryptedVote implements Message {
78 if (!optVal.isPresent()) { 62 if (!optVal.isPresent()) {
79 return null; 63 return null;
80 } 64 }
65 Optional<String> optZkp = cfg.getValueString("vote", "ZKP");
66 if (!optZkp.isPresent()) {
67 return null;
68 }
81 EncryptedVote encryptedVote = new EncryptedVote(); 69 EncryptedVote encryptedVote = new EncryptedVote();
82 encryptedVote.voterPublicKey = voterPublicKey; 70 encryptedVote.voterPublicKey = voterPublicKey;
83 encryptedVote.v = Ciphertext.fromString(optVal.get()); 71 encryptedVote.v = Ciphertext.fromString(optVal.get());
72 System.out.println("reading, string size " + optZkp.get().length());
73 byte[] zkpData = Strings.stringToData(optZkp.get());
74 if (null == zkpData) {
75 throw new InvalidBallotException("could not read ZKP from ballot");
76 }
77 encryptedVote.disjunctionZkp = Construct.parseAs(zkpData, DisjunctionZkp.class);
84 return encryptedVote; 78 return encryptedVote;
85 } 79 }
86 // TODO: zero knowledge proof 80
87 // TODO: signature 81 public static EncryptedVote fromChoice(int choiceId, ThresholdPublicKey thresholdPublicKey, EcdsaPublicKey voterPublicKey,
88 82 BigInteger[] generators) {
89 public static EncryptedVote fromChoice(int choiceId, ThresholdPublicKey thresholdPublicKey, 83
90 EcdsaPrivateKey voterPrivateKey, EcdsaPublicKey voterPublicKey) {
91 // for now, we only support one choice!
92 if (choiceId < 0 || choiceId > 1) {
93 throw new InvalidBallotException(String.format("choice '%s' not valid", choiceId));
94 }
95 int choiceExp = (choiceId == 1) ? 1 : -1;
96 // FIXME: can we use 'g', or should we use another generator?
97 Plaintext p = Plaintext.generate(BigInteger.valueOf(choiceExp));
98 EncryptedVote encryptedVote = new EncryptedVote(); 84 EncryptedVote encryptedVote = new EncryptedVote();
99 encryptedVote.v = p.encrypt(thresholdPublicKey); 85 encryptedVote.v = new Ciphertext();
100 encryptedVote.voterPublicKey = voterPublicKey; 86 encryptedVote.voterPublicKey = voterPublicKey;
87 encryptedVote.disjunctionZkp = new DisjunctionZkp();
88
89 encryptedVote.disjunctionZkp.chaumPedersenZkps = new ChaumPedersenZkp[generators.length];
90 encryptedVote.disjunctionZkp.numProofs = generators.length;
91
92 // the discrete logarithm
93 BigInteger alpha = Parameters.randomQ();
94 // the secret for the ZKP
95 BigInteger w = Parameters.randomQ();
96
97 BigInteger h = new BigInteger(1, thresholdPublicKey.bits);
98 BigInteger g = Parameters.elgamalG;
99 BigInteger p = Parameters.elgamalP;
100 BigInteger q = Parameters.elgamalQ;
101
102 BigInteger x = Parameters.modPowG(alpha);
103 BigInteger y = h.modPow(alpha, p).multiply(generators[choiceId]).mod(p);
104
105 encryptedVote.v.c_1 = BigIntegers.serializeUnsigned(x, Parameters.elgamalBits);
106 encryptedVote.v.c_2 = BigIntegers.serializeUnsigned(y, Parameters.elgamalBits);
107
108 // sum of all the simulation challenges
109 BigInteger d_sim_sum = BigInteger.ZERO;
110
111 // generate simulated proofs
112 for (int i = 0; i < generators.length; i++) {
113 if (i == choiceId) {
114 continue;
115 }
116 BigInteger r = Parameters.randomQ();
117 BigInteger d = Parameters.randomQ();
118 BigInteger a = g.modPow(r, p).multiply(x.modPow(d, p)).mod(p);
119 BigInteger b = h.modPow(r, p).multiply(y.multiply(generators[i].modInverse(p)).modPow(d, p)).mod(p);
120
121 d_sim_sum = d_sim_sum.add(d);
122
123 ChaumPedersenZkp zkp = new ChaumPedersenZkp();
124 zkp.challenge_d = BigIntegers.serializeUnsigned(d, Parameters.elgamalBits);
125 zkp.response_r = BigIntegers.serializeUnsigned(r, Parameters.elgamalBits);
126 zkp.commit_a = BigIntegers.serializeUnsigned(a, Parameters.elgamalBits);
127 zkp.commit_b = BigIntegers.serializeUnsigned(b, Parameters.elgamalBits);
128
129 if (!zkp.verifySim(x, y, generators[i], h)) {
130 throw new AssertionError("crypto not working");
131 }
132
133 encryptedVote.disjunctionZkp.chaumPedersenZkps[i] = zkp;
134 }
135
136 ChaumPedersenZkp zkp = new ChaumPedersenZkp();
137 encryptedVote.disjunctionZkp.chaumPedersenZkps[choiceId] = zkp;
138 BigInteger a = g.modPow(w, p);
139 BigInteger b = h.modPow(w, p);
140 zkp.commit_a = BigIntegers.serializeUnsigned(a, Parameters.elgamalBits);
141 zkp.commit_b = BigIntegers.serializeUnsigned(b, Parameters.elgamalBits);
142
143
144 BigInteger c = encryptedVote.disjunctionZkp.computeChallengeFromCommits();
145
146 BigInteger d = c.subtract(d_sim_sum).mod(q);
147 BigInteger r = w.subtract(alpha.multiply(d)).mod(q);
148
149
150 zkp.challenge_d = BigIntegers.serializeUnsigned(d, Parameters.elgamalBits);
151 zkp.response_r = BigIntegers.serializeUnsigned(r, Parameters.elgamalBits);
152
153
154 if (!zkp.verifySim(x,y,generators[choiceId], h)) {
155 throw new AssertionError("crypto (2) not working");
156 }
157
158 encryptedVote.disjunctionZkp.challenge_c = BigIntegers.serializeUnsigned(c, Parameters.elgamalBits);
159
160 if (!encryptedVote.disjunctionZkp.verifyChallenge()) {
161 throw new AssertionError("crypto not working (3)");
162 }
163
101 return encryptedVote; 164 return encryptedVote;
102 } 165 }
103 166
104 public void writeToConfiguration(Configuration cfg) { 167 public void writeToConfiguration(Configuration cfg) {
105 cfg.setValueString("vote", "ENCRYPTED_VOTE_VAL", v.toString()); 168 cfg.setValueString("vote", "ENCRYPTED_VOTE_VAL", v.toString());
169 byte[] zkpData = Construct.toBinary(disjunctionZkp);
170 String zkpString = Strings.dataToString(zkpData);
171 if (zkpString.length() != Strings.getEncodedStringLength(zkpData.length))
172 throw new AssertionError("fail");
173 if (zkpData.length != Strings.getDecodedDataLength(zkpString.length()))
174 throw new AssertionError("fail, got " + zkpData.length + " expected " +
175 Strings.getDecodedDataLength(zkpString.length()) + "for string length" + zkpString.length());
176 System.out.println("everyting ok, size binary size" + zkpData.length +" str size " + zkpString.length());
177 byte[] zkpData2 = Strings.stringToData(zkpString);
178 if (!Arrays.equals(zkpData, zkpData2)) {
179 throw new AssertionError("something wrong");
180 }
181 System.out.println("everyting ok, size binary size" + zkpData.length +" str size " + zkpString.length());
182 cfg.setValueString("vote", "ZKP", zkpString);
183 }
184
185 public boolean verify() {
186 return false;
106 } 187 }
107} 188}
diff --git a/src/main/java/org/gnunet/voting/GroupCert.java b/src/main/java/org/gnunet/voting/GroupCert.java
index 6899faa..c363674 100644
--- a/src/main/java/org/gnunet/voting/GroupCert.java
+++ b/src/main/java/org/gnunet/voting/GroupCert.java
@@ -60,7 +60,7 @@ public class GroupCert {
60 signData += expiration.getSeconds(); 60 signData += expiration.getSeconds();
61 signData += group; 61 signData += group;
62 signData += signerPublicKey; 62 signData += signerPublicKey;
63 groupCert.signature = signerPrivateKey.sign(0 /*FIXME*/, signData.getBytes()); 63 groupCert.signature = signerPrivateKey.sign(signData.getBytes(), 0);
64 return groupCert; 64 return groupCert;
65 65
66 } 66 }
diff --git a/src/main/java/org/gnunet/voting/SignedEncryptedVote.java b/src/main/java/org/gnunet/voting/SignedEncryptedVote.java
new file mode 100644
index 0000000..196476c
--- /dev/null
+++ b/src/main/java/org/gnunet/voting/SignedEncryptedVote.java
@@ -0,0 +1,8 @@
1package org.gnunet.voting;
2
3import org.gnunet.construct.Message;
4import org.gnunet.util.crypto.EcdsaSignedMessage;
5
6public class SignedEncryptedVote implements Message {
7 EcdsaSignedMessage<EncryptedVote> signedMessage;
8}
diff --git a/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java b/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
index e3a1d8e..f1f8bc7 100644
--- a/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
+++ b/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
@@ -27,6 +27,7 @@ import org.gnunet.consensus.ConsensusElement;
27import org.gnunet.construct.Construct; 27import org.gnunet.construct.Construct;
28import org.gnunet.mesh.Mesh; 28import org.gnunet.mesh.Mesh;
29import org.gnunet.mesh.MeshRunabout; 29import org.gnunet.mesh.MeshRunabout;
30import org.gnunet.mesh.TunnelEndHandler;
30import org.gnunet.secretsharing.*; 31import org.gnunet.secretsharing.*;
31import org.gnunet.secretsharing.callbacks.DecryptCallback; 32import org.gnunet.secretsharing.callbacks.DecryptCallback;
32import org.gnunet.secretsharing.callbacks.SecretReadyCallback; 33import org.gnunet.secretsharing.callbacks.SecretReadyCallback;
@@ -173,11 +174,13 @@ public class TallyAuthorityDaemon extends Program {
173 public void onResult(Plaintext plaintext) { 174 public void onResult(Plaintext plaintext) {
174 logger.info("got decypt result"); 175 logger.info("got decypt result");
175 long l = electionState.countedVoters.size(); 176 long l = electionState.countedVoters.size();
176 long t = plaintext.bruteForceDiscreteLog(l); 177 long t[] = plaintext.bruteForceDiscreteLog(l, electionState.ballot.generators);
177 logger.info("brute-forced result"); 178 if (null == t) {
178 electionState.tally = new long[2]; 179 logger.warn("could not brute-force result");
179 electionState.tally[0] = (l - t) / 2; 180 } else {
180 electionState.tally[1] = l - electionState.tally[0]; 181 logger.info("brute-forced result");
182 electionState.tally = t;
183 }
181 } 184 }
182 }); 185 });
183 } 186 }
@@ -217,8 +220,7 @@ public class TallyAuthorityDaemon extends Program {
217 // FIXME! 220 // FIXME!
218 tm.purpose = 0; 221 tm.purpose = 0;
219 tm.time = AbsoluteTime.now().asMessage(); 222 tm.time = AbsoluteTime.now().asMessage();
220 tm.signature = authorityPrivateKey.sign(authorityPublicKey, tm.purpose, 223 tm.signature = authorityPrivateKey.sign(Construct.toBinary(tm.time), tm.purpose,authorityPublicKey);
221 Construct.toBinary(tm.time));
222 return tm; 224 return tm;
223 } 225 }
224 226
@@ -371,8 +373,8 @@ public class TallyAuthorityDaemon extends Program {
371 rm.signedGuidKey = ballotPublicKey; 373 rm.signedGuidKey = ballotPublicKey;
372 // FIXME! 374 // FIXME!
373 rm.purpose = 0; 375 rm.purpose = 0;
374 rm.signature = authorityPrivateKey.sign(authorityPublicKey, rm.purpose, 376 rm.signature = authorityPrivateKey.sign(Construct.toBinary(rm.signedGuidKey),
375 Construct.toBinary(rm.signedGuidKey)); 377 rm.purpose, authorityPublicKey);
376 getSender().send(rm); 378 getSender().send(rm);
377 } 379 }
378 } 380 }
@@ -391,7 +393,12 @@ public class TallyAuthorityDaemon extends Program {
391 @Override 393 @Override
392 public void run() { 394 public void run() {
393 logger.info("running tally daemon"); 395 logger.info("running tally daemon");
394 mesh = new Mesh(getConfiguration(), null, null, new TallyMeshReceiver(), MESH_PORT); 396 mesh = new Mesh(getConfiguration(), null, new TunnelEndHandler() {
397 @Override
398 public void onChannelEnd(Mesh.Channel channel) {
399 logger.warn("on channel end");
400 }
401 }, new TallyMeshReceiver(), MESH_PORT);
395 402
396 Scheduler.addDelayed(RelativeTime.FOREVER, new Scheduler.Task() { 403 Scheduler.addDelayed(RelativeTime.FOREVER, new Scheduler.Task() {
397 @Override 404 @Override
diff --git a/src/main/java/org/gnunet/voting/messages/SubmitMessage.java b/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
index 4f131e3..1fdeb0c 100644
--- a/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
+++ b/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
@@ -38,7 +38,6 @@ public class SubmitMessage implements GnunetMessage.Body {
38 /** 38 /**
39 * The encrypted vote, including zero knowledge proofs 39 * The encrypted vote, including zero knowledge proofs
40 * for correctness. 40 * for correctness.
41 * FIXME: wrap in a signature container
42 */ 41 */
43 @NestedMessage 42 @NestedMessage
44 public EncryptedVote encryptedVote; 43 public EncryptedVote encryptedVote;
diff --git a/src/main/java/org/gnunet/voting/simulation/Ballot.java b/src/main/java/org/gnunet/voting/simulation/Ballot.java
index 1c2bfbe..ed8f39f 100644
--- a/src/main/java/org/gnunet/voting/simulation/Ballot.java
+++ b/src/main/java/org/gnunet/voting/simulation/Ballot.java
@@ -76,7 +76,6 @@ public class Ballot {
76 BigInteger h = groupPublicKey.getKey(); 76 BigInteger h = groupPublicKey.getKey();
77 // verifier 77 // verifier
78 78
79
80 if (!c.equals(CryptoUtil.hash(voterId, x, y, a_1, b_1, a_2, b_2).mod(parameters.q))) { 79 if (!c.equals(CryptoUtil.hash(voterId, x, y, a_1, b_1, a_2, b_2).mod(parameters.q))) {
81 throw new AssertionError(); 80 throw new AssertionError();
82 } 81 }
@@ -99,7 +98,5 @@ public class Ballot {
99 if (!b_1.equals(h.modPow(r_1, p).multiply(y.multiply(g).modPow(d_1, p)).mod(p))) { 98 if (!b_1.equals(h.modPow(r_1, p).multiply(y.multiply(g).modPow(d_1, p)).mod(p))) {
100 throw new AssertionError(); 99 throw new AssertionError();
101 } 100 }
102
103
104 } 101 }
105} 102}
diff --git a/src/main/java/org/gnunet/voting/simulation/VotingParameters.java b/src/main/java/org/gnunet/voting/simulation/VotingParameters.java
index 0086578..27b0015 100644
--- a/src/main/java/org/gnunet/voting/simulation/VotingParameters.java
+++ b/src/main/java/org/gnunet/voting/simulation/VotingParameters.java
@@ -46,8 +46,7 @@ public class VotingParameters {
46 BigInteger[] safePrimes = generateSafePrimes(p_bitlen, certainty); 46 BigInteger[] safePrimes = generateSafePrimes(p_bitlen, certainty);
47 BigInteger p = safePrimes[0]; 47 BigInteger p = safePrimes[0];
48 BigInteger q = safePrimes[1]; 48 BigInteger q = safePrimes[1];
49 BigInteger alpha = selectGenerator(p, q); 49 BigInteger g = selectSubgroupGenerator(p, q);
50 BigInteger g = selectSubgroupHigherOrderElement(alpha, p, q);
51 if (!g.modPow(q, p).equals(BigInteger.ONE)) { 50 if (!g.modPow(q, p).equals(BigInteger.ONE)) {
52 throw new AssertionError(); 51 throw new AssertionError();
53 } 52 }
@@ -82,21 +81,6 @@ public class VotingParameters {
82 return new BigInteger[]{p, q}; 81 return new BigInteger[]{p, q};
83 } 82 }
84 83
85 /*
86 * Select a high order element of the multiplicative group Zn*
87 */
88 private static BigInteger selectHighOrderElement(BigInteger n, SecureRandom random) {
89 BigInteger g;
90 final BigInteger nMinusTwo = n.subtract(BigInteger.valueOf(2));
91 do {
92 BigInteger h = CryptoUtil.createRandomInRange(BigInteger.valueOf(2), nMinusTwo);
93
94 g = h.modPow(BigInteger.valueOf(2), n);
95 }
96 while (g.equals(BigInteger.valueOf(1)));
97
98 return g;
99 }
100 84
101 /** 85 /**
102 * Returns a higher-order-element of Gq, the subgroup of Zp*, 86 * Returns a higher-order-element of Gq, the subgroup of Zp*,
@@ -135,15 +119,9 @@ public class VotingParameters {
135 return q; 119 return q;
136 } 120 }
137 121
138 public BigInteger generateGq() { 122 public static BigInteger selectSubgroupGenerator(BigInteger p, BigInteger q) {
139 BigInteger r; 123 BigInteger alpha = selectGenerator(p, q);
140 while (true) { 124 return selectSubgroupHigherOrderElement(alpha, p, q);
141 r = CryptoUtil.createRandomInRange(BigInteger.ZERO, this.p);
142 if (r.modPow(q, p).equals(BigInteger.ONE)) {
143 break;
144 }
145 }
146 return r;
147 } 125 }
148 126
149 /** 127 /**