diff options
author | Florian Dold <florian.dold@gmail.com> | 2014-03-30 21:41:58 +0000 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2014-03-30 21:41:58 +0000 |
commit | 9f10abfdc35d8f189a8e0a77a389799ca6b7f9e5 (patch) | |
tree | 39d855abacebeaa45752e4abc5b4a660d2603d70 /src/main/java/org | |
parent | 1fbef203844b19f8141bddcba20a977de34b211e (diff) | |
download | gnunet-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')
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 | */ |
10 | public interface ConnectHandler { | 10 | public 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 @@ | |||
1 | package org.gnunet.mesh; | ||
2 | |||
3 | import org.gnunet.util.PeerIdentity; | ||
4 | |||
5 | /** | ||
6 | * ... | ||
7 | * | ||
8 | * @author Florian Dold | ||
9 | */ | ||
10 | public 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 @@ | |||
1 | package org.gnunet.mesh; | ||
2 | |||
3 | import org.gnunet.util.PeerIdentity; | ||
4 | |||
5 | /** | ||
6 | * ... | ||
7 | * | ||
8 | * @author Florian Dold | ||
9 | */ | ||
10 | public 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 @@ | |||
1 | package org.gnunet.mesh; | ||
2 | |||
3 | import org.gnunet.util.PeerIdentity; | ||
4 | |||
5 | /** | ||
6 | * ... | ||
7 | * | ||
8 | * @author Florian Dold | ||
9 | */ | ||
10 | public 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 | */ |
10 | public class MeshRunabout extends Runabout { | 10 | public 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 | */ |
8 | public interface TunnelEndHandler { | 8 | public 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 @@ | |||
1 | package org.gnunet.mesh; | ||
2 | |||
3 | import org.gnunet.construct.NestedMessage; | ||
4 | import org.gnunet.construct.UInt32; | ||
5 | import org.gnunet.util.GnunetMessage; | ||
6 | import org.gnunet.util.PeerIdentity; | ||
7 | |||
8 | /** | ||
9 | * ... | ||
10 | * | ||
11 | * @author Florian Dold | ||
12 | */ | ||
13 | public 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 | */ |
25 | package org.gnunet.mesh; | 25 | package 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 | ||
4 | import org.gnunet.util.GnunetMessage; | 4 | import org.gnunet.util.GnunetMessage; |
5 | import org.slf4j.Logger; | ||
6 | import org.slf4j.LoggerFactory; | ||
5 | 7 | ||
6 | import java.util.LinkedList; | 8 | import 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 | */ |
11 | public abstract class MessageQueue { | 13 | public 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; | |||
26 | import org.gnunet.util.Strings; | 26 | import org.gnunet.util.Strings; |
27 | 27 | ||
28 | import java.math.BigInteger; | 28 | import java.math.BigInteger; |
29 | import 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 | ||
21 | package org.gnunet.secretsharing; | 21 | package org.gnunet.secretsharing; |
22 | 22 | ||
23 | import org.gnunet.voting.simulation.VotingParameters; | ||
24 | |||
23 | import java.math.BigInteger; | 25 | import java.math.BigInteger; |
26 | import 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 | */ |
28 | public interface Parameters { | 31 | public 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 | ||
27 | import java.math.BigInteger; | 27 | import java.math.BigInteger; |
28 | import java.security.SecureRandom; | 28 | import java.security.SecureRandom; |
29 | import java.util.Arrays; | ||
29 | 30 | ||
30 | public class Plaintext implements Message { | 31 | public 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 @@ | |||
1 | package org.gnunet.statistics; | ||
2 | |||
3 | import org.gnunet.mq.Envelope; | ||
4 | import org.gnunet.mq.MessageQueue; | ||
5 | import org.gnunet.requests.Request; | ||
6 | import org.gnunet.requests.RequestContainer; | ||
7 | import org.gnunet.statistics.messages.SetMessage; | ||
8 | import org.gnunet.util.RelativeTime; | ||
9 | |||
10 | |||
11 | public 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 @@ | |||
1 | package org.gnunet.util.crypto; | ||
2 | |||
3 | import org.gnunet.construct.Message; | ||
4 | import org.gnunet.construct.UInt32; | ||
5 | import org.gnunet.construct.Union; | ||
6 | |||
7 | /** | ||
8 | * Purpose header fields, together with content union. | ||
9 | */ | ||
10 | public 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; | |||
24 | import org.gnunet.construct.Message; | 24 | import org.gnunet.construct.Message; |
25 | import org.gnunet.util.HashCode; | 25 | import org.gnunet.util.HashCode; |
26 | 26 | ||
27 | import java.io.ByteArrayOutputStream; | ||
28 | import java.io.DataOutputStream; | ||
29 | import java.io.IOError; | ||
30 | import java.io.IOException; | ||
27 | import java.math.BigInteger; | 31 | import java.math.BigInteger; |
28 | import java.security.SecureRandom; | 32 | import 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; | |||
26 | import org.gnunet.util.HashCode; | 26 | import org.gnunet.util.HashCode; |
27 | import org.gnunet.util.Strings; | 27 | import org.gnunet.util.Strings; |
28 | 28 | ||
29 | import java.io.ByteArrayOutputStream; | ||
30 | import java.io.DataOutputStream; | ||
31 | import java.io.IOError; | ||
32 | import java.io.IOException; | ||
29 | import java.math.BigInteger; | 33 | import java.math.BigInteger; |
30 | import java.security.SecureRandom; | 34 | import 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 | ||
21 | package org.gnunet.util.crypto; | 21 | package org.gnunet.util.crypto; |
22 | 22 | ||
23 | import org.gnunet.construct.Construct; | 23 | import org.gnunet.construct.*; |
24 | import org.gnunet.construct.Message; | ||
25 | import org.gnunet.construct.NestedMessage; | ||
26 | import 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 | */ |
31 | public class EcdsaSignedMessage<M extends Message> implements Message { | 28 | public 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; | |||
22 | import org.gnunet.construct.FixedSizeIntegerArray; | 22 | import org.gnunet.construct.FixedSizeIntegerArray; |
23 | import org.gnunet.construct.Message; | 23 | import org.gnunet.construct.Message; |
24 | 24 | ||
25 | import java.io.ByteArrayOutputStream; | ||
26 | import java.io.DataOutputStream; | ||
27 | import java.io.IOError; | ||
28 | import java.io.IOException; | ||
25 | import java.math.BigInteger; | 29 | import java.math.BigInteger; |
26 | import java.nio.ByteBuffer; | 30 | import java.nio.ByteBuffer; |
27 | import java.security.MessageDigest; | 31 | import 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; | |||
24 | import org.gnunet.construct.Message; | 24 | import org.gnunet.construct.Message; |
25 | import org.gnunet.util.Strings; | 25 | import org.gnunet.util.Strings; |
26 | 26 | ||
27 | import java.io.ByteArrayOutputStream; | ||
28 | import java.io.DataOutputStream; | ||
29 | import java.io.IOError; | ||
30 | import java.io.IOException; | ||
27 | import java.security.SecureRandom; | 31 | import java.security.SecureRandom; |
28 | import java.util.Arrays; | 32 | import 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; | |||
25 | import org.gnunet.construct.Message; | 25 | import org.gnunet.construct.Message; |
26 | import org.gnunet.util.Strings; | 26 | import org.gnunet.util.Strings; |
27 | 27 | ||
28 | import java.io.ByteArrayOutputStream; | ||
29 | import java.io.DataOutputStream; | ||
30 | import java.io.IOError; | ||
31 | import java.io.IOException; | ||
28 | import java.math.BigInteger; | 32 | import java.math.BigInteger; |
29 | import java.nio.ByteBuffer; | 33 | import java.nio.ByteBuffer; |
30 | import java.security.SecureRandom; | 34 | import 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 | |||
21 | package org.gnunet.util.crypto; | ||
22 | |||
23 | import org.gnunet.construct.Construct; | ||
24 | import org.gnunet.construct.Message; | ||
25 | import org.gnunet.construct.NestedMessage; | ||
26 | |||
27 | /** | ||
28 | * A message together with a signature on the message and its purpose. | ||
29 | */ | ||
30 | public 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 @@ | |||
1 | package org.gnunet.util.crypto; | ||
2 | |||
3 | |||
4 | import org.gnunet.construct.MessageUnion; | ||
5 | |||
6 | public 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; | |||
27 | import com.google.common.collect.HashBiMap; | 27 | import com.google.common.collect.HashBiMap; |
28 | import com.google.common.collect.Maps; | 28 | import com.google.common.collect.Maps; |
29 | import com.google.common.primitives.Longs; | 29 | import com.google.common.primitives.Longs; |
30 | import org.gnunet.secretsharing.Parameters; | ||
30 | import org.gnunet.secretsharing.ThresholdPublicKey; | 31 | import org.gnunet.secretsharing.ThresholdPublicKey; |
31 | import org.gnunet.util.AbsoluteTime; | 32 | import org.gnunet.util.AbsoluteTime; |
32 | import org.gnunet.util.Configuration; | 33 | import org.gnunet.util.Configuration; |
@@ -37,7 +38,10 @@ import org.gnunet.util.crypto.EcdsaPublicKey; | |||
37 | import org.gnunet.util.crypto.EcdsaSignature; | 38 | import org.gnunet.util.crypto.EcdsaSignature; |
38 | import org.gnunet.util.crypto.EddsaSignature; | 39 | import org.gnunet.util.crypto.EddsaSignature; |
39 | import org.gnunet.voting.messages.KeyQueryResponseMessage; | 40 | import org.gnunet.voting.messages.KeyQueryResponseMessage; |
41 | import org.gnunet.voting.simulation.VotingParameters; | ||
42 | import org.omg.CORBA.DynAnyPackage.Invalid; | ||
40 | 43 | ||
44 | import java.math.BigInteger; | ||
41 | import java.security.MessageDigest; | 45 | import java.security.MessageDigest; |
42 | import java.security.NoSuchAlgorithmException; | 46 | import java.security.NoSuchAlgorithmException; |
43 | import java.util.*; | 47 | import 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 | |||
21 | package org.gnunet.voting; | ||
22 | |||
23 | import org.gnunet.construct.FixedSizeIntegerArray; | ||
24 | import org.gnunet.construct.Message; | ||
25 | import org.gnunet.secretsharing.Parameters; | ||
26 | |||
27 | import 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 | */ | ||
35 | public 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 | |||
21 | package org.gnunet.voting; | ||
22 | |||
23 | import org.gnunet.construct.*; | ||
24 | import org.gnunet.secretsharing.Parameters; | ||
25 | |||
26 | import java.math.BigInteger; | ||
27 | import java.security.MessageDigest; | ||
28 | import java.security.NoSuchAlgorithmException; | ||
29 | |||
30 | /** | ||
31 | * Disjunction of Chaum Pedersen ZKPs. | ||
32 | */ | ||
33 | public 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 | ||
24 | import com.google.common.base.Optional; | 24 | import com.google.common.base.Optional; |
25 | import org.gnunet.construct.Construct; | ||
25 | import org.gnunet.construct.Message; | 26 | import org.gnunet.construct.Message; |
26 | import org.gnunet.construct.NestedMessage; | 27 | import org.gnunet.construct.NestedMessage; |
27 | import org.gnunet.secretsharing.Ciphertext; | 28 | import org.gnunet.secretsharing.Ciphertext; |
28 | import org.gnunet.secretsharing.Plaintext; | 29 | import org.gnunet.secretsharing.Parameters; |
29 | import org.gnunet.secretsharing.ThresholdPublicKey; | 30 | import org.gnunet.secretsharing.ThresholdPublicKey; |
31 | import org.gnunet.util.BigIntegers; | ||
30 | import org.gnunet.util.Configuration; | 32 | import org.gnunet.util.Configuration; |
33 | import org.gnunet.util.Strings; | ||
31 | import org.gnunet.util.crypto.EcdsaPrivateKey; | 34 | import org.gnunet.util.crypto.EcdsaPrivateKey; |
32 | import org.gnunet.util.crypto.EcdsaPublicKey; | 35 | import org.gnunet.util.crypto.EcdsaPublicKey; |
33 | import org.gnunet.voting.simulation.Voter; | 36 | import org.gnunet.util.crypto.SignedContentMessage; |
34 | import org.omg.CORBA.DynAnyPackage.Invalid; | 37 | import org.gnunet.voting.simulation.CryptoUtil; |
35 | 38 | ||
36 | import java.math.BigInteger; | 39 | import java.math.BigInteger; |
40 | import java.util.Arrays; | ||
37 | 41 | ||
38 | public class EncryptedVote implements Message { | 42 | public 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 @@ | |||
1 | package org.gnunet.voting; | ||
2 | |||
3 | import org.gnunet.construct.Message; | ||
4 | import org.gnunet.util.crypto.EcdsaSignedMessage; | ||
5 | |||
6 | public 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; | |||
27 | import org.gnunet.construct.Construct; | 27 | import org.gnunet.construct.Construct; |
28 | import org.gnunet.mesh.Mesh; | 28 | import org.gnunet.mesh.Mesh; |
29 | import org.gnunet.mesh.MeshRunabout; | 29 | import org.gnunet.mesh.MeshRunabout; |
30 | import org.gnunet.mesh.TunnelEndHandler; | ||
30 | import org.gnunet.secretsharing.*; | 31 | import org.gnunet.secretsharing.*; |
31 | import org.gnunet.secretsharing.callbacks.DecryptCallback; | 32 | import org.gnunet.secretsharing.callbacks.DecryptCallback; |
32 | import org.gnunet.secretsharing.callbacks.SecretReadyCallback; | 33 | import 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 | /** |