[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r32476 - in gnunet-java: . src/main/java/org/gnunet/constru
From: |
gnunet |
Subject: |
[GNUnet-SVN] r32476 - in gnunet-java: . src/main/java/org/gnunet/construct src/main/java/org/gnunet/construct/parsers src/main/java/org/gnunet/dht src/main/java/org/gnunet/mesh src/main/java/org/gnunet/secretsharing src/main/java/org/gnunet/secretsharing/messages src/main/java/org/gnunet/util src/main/java/org/gnunet/util/crypto src/main/java/org/gnunet/voting src/main/java/org/gnunet/voting/messages src/main/resources/org/gnunet/construct src/main/resources/org/gnunet/voting src/test src/test/python |
Date: |
Tue, 25 Feb 2014 12:15:15 +0100 |
Author: dold
Date: 2014-02-25 12:15:15 +0100 (Tue, 25 Feb 2014)
New Revision: 32476
Added:
gnunet-java/src/main/java/org/gnunet/mesh/RejectMessage.java
gnunet-java/src/main/java/org/gnunet/util/BigIntegers.java
gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryFailureMessage.java
gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryMessage.java
gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryResponseMessage.java
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryFailureMessage.java
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryMessage.java
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryResponseMessage.java
gnunet-java/src/test/python/
gnunet-java/src/test/python/test_voting.conf
gnunet-java/src/test/python/test_voting_single.py
Modified:
gnunet-java/ISSUES
gnunet-java/src/main/java/org/gnunet/construct/Construct.java
gnunet-java/src/main/java/org/gnunet/construct/parsers/NestedParser.java
gnunet-java/src/main/java/org/gnunet/dht/ClientGetStopMessage.java
gnunet-java/src/main/java/org/gnunet/mesh/Mesh.java
gnunet-java/src/main/java/org/gnunet/mesh/TunnelDestroyMessage.java
gnunet-java/src/main/java/org/gnunet/secretsharing/Ciphertext.java
gnunet-java/src/main/java/org/gnunet/secretsharing/Plaintext.java
gnunet-java/src/main/java/org/gnunet/secretsharing/ThresholdPublicKey.java
gnunet-java/src/main/java/org/gnunet/secretsharing/messages/DecryptDoneMessage.java
gnunet-java/src/main/java/org/gnunet/util/MessageStreamTokenizer.java
gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java
gnunet-java/src/main/java/org/gnunet/voting/Ballot.java
gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java
gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitFailureMessage.java
gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt
gnunet-java/src/main/resources/org/gnunet/voting/ballot-template.espec
Log:
- support mesh's new NACK message
- remove
- python test skeleton for voting
- encrypted votes
- establish threshold key during ballot registration
- ballot tool can request threshold public keys from authorities
Modified: gnunet-java/ISSUES
===================================================================
--- gnunet-java/ISSUES 2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/ISSUES 2014-02-25 11:15:15 UTC (rev 32476)
@@ -1,16 +1,38 @@
+testbed:
+Could it be possible that there are some issues with operation scheduling?
+I'm currently having problems executing a ~15-peer testbed
-secretsharing:
- * almost all ZKPs are implemented now
- * crypto works (even for decryption :-)
+crypto in java:
+public class EddsaSignedMessage<M extends Message> implements Message {
+ @NestedMessage
+ public EddsaSignature signature;
+ @UInt32
+ public int purpose;
+ @NestedMessage
+ public M innerMessage;
+// ...
+}
-mesh:
-* 10 minute delay problem
+Unfortunately, this does not work, as the type of 'M' is erased,
+reflection will give 'Message' as type of the 'innerMessage' field
+=> ditch generics
-Consensus:
- * fixed some problems with set and consensus
- * Timeouts are now correctly implemented.
- * Round synchronization: How can a peer know to skip a (sub-)round without
waiting for the timeout?
- * when our peer is "outgoing", there's no problem -- the other peer will
reject
- * otherwise there's just the timeout
- * do you have any suggestions?
+voting:
+As discussed, the key generation is done after the ballot has been registered,
+one threshold key pair per election.
+gnunet-ballot -k <ballotfile> # fetch threshold pubkey from authority
+(preferably the issuer should do that)
+
+ballots are now actually encrypted
+
+testing voting:
+python test case with arbitrary number of authorities and voters
+
+close to working ...
+
+misc:
+gnunet-config always writes the whole default configuration with the
+requested change. What if, however, I don't want the default part to be
written?
+
+
Modified: gnunet-java/src/main/java/org/gnunet/construct/Construct.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/construct/Construct.java
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/construct/Construct.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -85,15 +85,21 @@
* @return instance of the desired object type
*/
public static <T extends Message> T parseAs(ByteBuffer srcBuf, Class<T> c)
{
- T m = ReflectUtil.justInstantiate(c);
+ try {
+ T m = ReflectUtil.justInstantiate(c);
- try {
- getParser(c).parse(srcBuf, 0, m, m, null);
- } catch (ProtocolViolationException e) {
- e.augmentPath("on " + c);
+ try {
+ getParser(c).parse(srcBuf, 0, m, m, null);
+ } catch (ProtocolViolationException e) {
+ e.augmentPath("on " + c);
+ }
+
+ return m;
+ } catch (Error e) {
+ System.err.println(
+ String.format("Exception while parsing message for class
'%s':", c.getCanonicalName()));
+ throw e;
}
-
- return m;
}
/**
Modified:
gnunet-java/src/main/java/org/gnunet/construct/parsers/NestedParser.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/construct/parsers/NestedParser.java
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/construct/parsers/NestedParser.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -80,7 +80,9 @@
return 0;
}
}
-
+ if (targetField.getType().isInterface()) {
+ throw new AssertionError(String.format("Target field '%s' is an
interface, not a class.", targetField));
+ }
ReflectUtil.justSet(dstObj, targetField,
ReflectUtil.justInstantiate(targetField.getType()));
try {
Modified: gnunet-java/src/main/java/org/gnunet/dht/ClientGetStopMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/dht/ClientGetStopMessage.java
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/dht/ClientGetStopMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -28,12 +28,9 @@
import org.gnunet.util.HashCode;
/**
-* Created with IntelliJ IDEA.
-* User: dold
-* Date: 5/2/12
-* Time: 7:05 PM
-* To change this template use File | Settings | File Templates.
-*/
+ * Sent by the client to the service.
+ * Requests that the service stops a 'get' operation.
+ */
@UnionCase(144)
public class ClientGetStopMessage implements GnunetMessage.Body {
@UInt32
Modified: gnunet-java/src/main/java/org/gnunet/mesh/Mesh.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/Mesh.java 2014-02-25 09:42:06 UTC
(rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/mesh/Mesh.java 2014-02-25 11:15:15 UTC
(rev 32476)
@@ -133,8 +133,7 @@
* @param nobuffer Flag for disabling buffering on relay nodes.
* @param reliable Flag for end-to-end reliability.
*/
- public Tunnel(PeerIdentity peer, int port, boolean nobuffer, boolean
reliable, T context)
- {
+ public Tunnel(PeerIdentity peer, int port, boolean nobuffer, boolean
reliable, T context) {
this(peer, 0, port, nobuffer, reliable);
TunnelCreateMessage tcm = new TunnelCreateMessage();
tcm.otherEnd = peer;
@@ -144,6 +143,7 @@
client.send(tcm);
}
+
/**
* Private tunnel constructor, for creating tunnel objects for
* incoming tunnels.
@@ -188,7 +188,7 @@
if (!destroyedByService) {
TunnelDestroyMessage m = new TunnelDestroyMessage();
m.tunnelId = tunnelId;
- m.reserved = new byte[64];
+ m.reserved = new byte[32];
client.send(m);
}
tunnelMap.remove(tunnelId);
@@ -258,7 +258,10 @@
logger.warn("got unexpected message from service");
t.receiveDoneExpected = true;
messageReceiver.setSender(t);
- messageReceiver.visitAppropriate(Construct.parseAs(m.payload,
GnunetMessage.class).body);
+ GnunetMessage gnunetMessage = Construct.parseAs(m.payload,
GnunetMessage.class);
+ logger.debug("received message of size {} and type {}",
+ gnunetMessage.header.messageSize,
gnunetMessage.header.messageType);
+ messageReceiver.visitAppropriate(gnunetMessage.body);
messageReceiver.setSender(null);
}
}
@@ -286,6 +289,20 @@
}
}
+ public void visit(RejectMessage m) {
+ // FIXME: C code indicates that the nack/reject message might
change ...
+ Tunnel t = tunnelMap.get(m.tunnelId);
+ if (null == t) {
+ logger.warn("server got confused with tunnel IDs on destroy,
ignoring message");
+ return;
+ }
+ t.destroyedByService = true;
+ t.destroy();
+ if (null != tunnelEndHandler) {
+ tunnelEndHandler.onTunnelEnd(t);
+ }
+ }
+
@Override
public void handleError() {
logger.warn("lost connection to mesh service, reconnecting");
Added: gnunet-java/src/main/java/org/gnunet/mesh/RejectMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/RejectMessage.java
(rev 0)
+++ gnunet-java/src/main/java/org/gnunet/mesh/RejectMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -0,0 +1,49 @@
+/*
+ This file is part of GNUnet.
+ (C) 2014 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+package org.gnunet.mesh;
+
+import org.gnunet.construct.FixedSizeIntegerArray;
+import org.gnunet.construct.UInt32;
+import org.gnunet.construct.UnionCase;
+import org.gnunet.util.GnunetMessage;
+
+/**
+ * Message sent by the server to indicate that a tunnel could not
+ * be created.
+ *
+ * (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_NACK)
+ *
+ * @author Florian Dold
+ */
address@hidden(276)
+public class RejectMessage implements GnunetMessage.Body {
+ @UInt32
+ public long tunnelId;
+
+ @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
+ public byte[] reserved;
+
+ @UInt32
+ public int port;
+
+ @UInt32
+ public int opt;
+}
Modified: gnunet-java/src/main/java/org/gnunet/mesh/TunnelDestroyMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/mesh/TunnelDestroyMessage.java
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/mesh/TunnelDestroyMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -17,8 +17,9 @@
@UInt32
public long tunnelId;
- @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 64)
+ @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
public byte[] reserved;
+
@UInt32
public int port;
Modified: gnunet-java/src/main/java/org/gnunet/secretsharing/Ciphertext.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/secretsharing/Ciphertext.java
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/secretsharing/Ciphertext.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -22,7 +22,11 @@
import org.gnunet.construct.FixedSizeIntegerArray;
import org.gnunet.construct.Message;
+import org.gnunet.util.BigIntegers;
+import org.gnunet.util.Strings;
+import java.math.BigInteger;
+
/**
* ElGamal ciphertext
*/
@@ -32,4 +36,50 @@
@FixedSizeIntegerArray(signed = true, bitSize = 8, length =
Parameters.elgamalBits / 8)
public byte[] c_2;
+
+ /**
+ * Allocate the ciphertext with zeros.
+ */
+ public void allocate() {
+ c_1 = new byte[Parameters.elgamalBits / 8];
+ c_2 = new byte[Parameters.elgamalBits / 8];
+ }
+
+ @Override
+ public String toString() {
+ byte[] allBytes = new byte[c_1.length + c_2.length];
+ System.arraycopy(c_1, 0, allBytes, 0, c_1.length);
+ System.arraycopy(c_2, 0, allBytes, c_1.length, c_2.length);
+ return Strings.dataToString(allBytes);
+ }
+
+ public static Ciphertext fromString(String s) {
+ byte[] allBytes = new byte[2 * Parameters.elgamalBits / 8];
+ if (!Strings.stringToData(s, allBytes))
+ return null;
+ Ciphertext ciphertext = new Ciphertext();
+ ciphertext.allocate();
+ System.arraycopy(allBytes, 0, ciphertext.c_1, 0,
ciphertext.c_1.length);
+ System.arraycopy(allBytes, ciphertext.c_1.length, ciphertext.c_2, 0,
ciphertext.c_2.length);
+ return ciphertext;
+ }
+
+ /**
+ * Multiply two elgamal ciphertexts.
+ *
+ * @param v the other ciphertext
+ * @return the product of two ciphertexts
+ */
+ public Ciphertext multiply(Ciphertext v) {
+ BigInteger xc_1 = new BigInteger(1, this.c_1);
+ BigInteger xc_2 = new BigInteger(1, this.c_2);
+ BigInteger yc_1 = new BigInteger(1, v.c_1);
+ BigInteger yc_2 = new BigInteger(1, v.c_2);
+ Ciphertext ciphertext = new Ciphertext();
+ ciphertext.c_1 =
BigIntegers.serializeUnsigned(xc_1.multiply(yc_1).mod(Parameters.elgamalP),
+ Parameters.elgamalBits);
+ ciphertext.c_2 =
BigIntegers.serializeUnsigned(xc_2.multiply(yc_2).mod(Parameters.elgamalP),
+ Parameters.elgamalBits);
+ return ciphertext;
+ }
}
Modified: gnunet-java/src/main/java/org/gnunet/secretsharing/Plaintext.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/secretsharing/Plaintext.java
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/secretsharing/Plaintext.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -23,6 +23,7 @@
import com.google.common.base.Preconditions;
import org.gnunet.construct.FixedSizeIntegerArray;
import org.gnunet.construct.Message;
+import org.gnunet.util.BigIntegers;
import java.math.BigInteger;
import java.security.SecureRandom;
@@ -35,32 +36,19 @@
BigInteger val;
val = Parameters.elgamalG.modPow(exp, Parameters.elgamalP);
Plaintext plaintext = new Plaintext();
- plaintext.bits = serializeBigIntUnsigned(val, Parameters.elgamalBits);
+ plaintext.bits = BigIntegers.serializeUnsigned(val,
Parameters.elgamalBits);
return plaintext;
}
- /**
- * Serialize a BigInteger, but do not add an extra bit for a
- * sign.
- *
- * @param bigInteger
- * @param bits
- * @return
- */
- private static byte[] serializeBigIntUnsigned(BigInteger bigInteger, int
bits) {
- byte[] bytes = bigInteger.toByteArray();
- int start;
- Preconditions.checkArgument(bigInteger.bitCount() <= bits);
- // skip byte that was only added to fit the sign
- if (bytes[0] == 0) {
- start = 1;
- } else {
- start = 0;
+ public long bruteForceDiscreteLog(final long l) {
+ BigInteger needle = new BigInteger(1, bits);
+ for (long i = -l; i < l; i++) {
+ BigInteger val;
+ val = Parameters.elgamalG.modPow(BigInteger.valueOf(l),
Parameters.elgamalP);
+ if (val.equals(needle))
+ return i;
}
- byte[] fixedBytes = new byte[(bits + 7) / 8];
- System.arraycopy(bytes, start, fixedBytes,
- fixedBytes.length - bytes.length + start, bytes.length -
start);
- return fixedBytes;
+ throw new ArithmeticException("discrete log has no solution in given
range");
}
public Ciphertext encrypt(ThresholdPublicKey publicKey) {
@@ -82,8 +70,8 @@
c_2 = m.multiply(h.modPow(y,
Parameters.elgamalP)).mod(Parameters.elgamalP);
Ciphertext ciphertext = new Ciphertext();
- ciphertext.c_1 = serializeBigIntUnsigned(c_1, Parameters.elgamalBits);
- ciphertext.c_2 = serializeBigIntUnsigned(c_2, Parameters.elgamalBits);
+ ciphertext.c_1 = BigIntegers.serializeUnsigned(c_1,
Parameters.elgamalBits);
+ ciphertext.c_2 = BigIntegers.serializeUnsigned(c_2,
Parameters.elgamalBits);
return ciphertext;
}
Modified:
gnunet-java/src/main/java/org/gnunet/secretsharing/ThresholdPublicKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/secretsharing/ThresholdPublicKey.java
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/secretsharing/ThresholdPublicKey.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -22,11 +22,40 @@
import org.gnunet.construct.FixedSizeIntegerArray;
import org.gnunet.construct.Message;
+import org.gnunet.util.Strings;
+import java.util.Arrays;
+
/**
* Threshold public key.
*/
public class ThresholdPublicKey implements Message {
+
@FixedSizeIntegerArray(signed = true, bitSize = 8, length =
Parameters.elgamalBits / 8)
public byte[] bits;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ThresholdPublicKey that = (ThresholdPublicKey) o;
+ return Arrays.equals(bits, that.bits);
+ }
+
+ @Override
+ public int hashCode() {
+ return bits != null ? Arrays.hashCode(bits) : 0;
+ }
+
+ public static ThresholdPublicKey fromString(String value) {
+ ThresholdPublicKey pk = new ThresholdPublicKey();
+ pk.bits = new byte[Parameters.elgamalBits / 8];
+ Strings.stringToData(value, pk.bits);
+ return pk;
+ }
+
+ @Override
+ public String toString() {
+ return Strings.dataToString(bits);
+ }
}
Modified:
gnunet-java/src/main/java/org/gnunet/secretsharing/messages/DecryptDoneMessage.java
===================================================================
---
gnunet-java/src/main/java/org/gnunet/secretsharing/messages/DecryptDoneMessage.java
2014-02-25 09:42:06 UTC (rev 32475)
+++
gnunet-java/src/main/java/org/gnunet/secretsharing/messages/DecryptDoneMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -1,5 +1,4 @@
/*
-
This file is part of GNUnet.
(C) 2014 Christian Grothoff (and other contributing authors)
@@ -17,7 +16,6 @@
along with GNUnet; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
-
*/
package org.gnunet.secretsharing.messages;
@@ -29,7 +27,8 @@
import org.gnunet.util.GnunetMessage;
/**
- * Created by dold on 2/2/14.
+ * Sent by the service to the client.
+ * Contains the plaintext for a successfully decrypted ciphertext.
*/
@UnionCase(782)
public class DecryptDoneMessage implements GnunetMessage.Body{
Added: gnunet-java/src/main/java/org/gnunet/util/BigIntegers.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/BigIntegers.java
(rev 0)
+++ gnunet-java/src/main/java/org/gnunet/util/BigIntegers.java 2014-02-25
11:15:15 UTC (rev 32476)
@@ -0,0 +1,56 @@
+/*
+ This file is part of GNUnet.
+ (C) 2014 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+package org.gnunet.util;
+
+import com.google.common.base.Preconditions;
+
+import java.math.BigInteger;
+
+/**
+ * Helper class for BigIntegers.
+ */
+public class BigIntegers {
+
+ /**
+ * Serialize a BigInteger, but do not add an extra bit for a
+ * sign.
+ *
+ * @param bigInteger big integer to serialize
+ * @param bits how many bits should the binary representation have?
+ * rounded up to the next multiple of 8.
+ * @return big endian representation of the given BigInteger, without a
sign bit
+ */
+ public static byte[] serializeUnsigned(BigInteger bigInteger, int bits) {
+ byte[] bytes = bigInteger.toByteArray();
+ int start;
+ Preconditions.checkArgument(bigInteger.bitCount() <= bits);
+ // skip byte that was only added to fit the sign
+ if (bytes[0] == 0) {
+ start = 1;
+ } else {
+ start = 0;
+ }
+ byte[] fixedBytes = new byte[(bits + 7) / 8];
+ System.arraycopy(bytes, start, fixedBytes,
+ fixedBytes.length - bytes.length + start, bytes.length -
start);
+ return fixedBytes;
+ }
+}
Modified: gnunet-java/src/main/java/org/gnunet/util/MessageStreamTokenizer.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/MessageStreamTokenizer.java
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/util/MessageStreamTokenizer.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -70,8 +70,9 @@
}
int parsedSize = buffer.position() - oldPos;
if (parsedSize != msg.header.messageSize) {
- throw new AssertionError("mismatch between parsed message and
header for " +
- msg.body.getClass());
+ throw new AssertionError(
+ String.format("mismatch between parsed message and
header for %s: parsed size %s, header size %s",
+ msg.body.getClass(), parsedSize,
msg.header.messageSize));
}
mstCalllback.onKnownMessage(msg);
} else {
Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -65,6 +65,7 @@
*/
public static EcdsaPublicKey fromString(String s) {
EcdsaPublicKey publicKey = new EcdsaPublicKey();
+ publicKey.y = new byte[32];
if (Strings.stringToData(s, publicKey.y))
return publicKey;
return null;
Modified: gnunet-java/src/main/java/org/gnunet/voting/Ballot.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/Ballot.java 2014-02-25
09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/voting/Ballot.java 2014-02-25
11:15:15 UTC (rev 32476)
@@ -25,12 +25,12 @@
import com.google.common.base.Preconditions;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
+import com.google.common.collect.Maps;
import com.google.common.primitives.Longs;
+import org.gnunet.secretsharing.ThresholdPublicKey;
import org.gnunet.util.*;
-import org.gnunet.util.crypto.EcdsaPrivateKey;
-import org.gnunet.util.crypto.EcdsaPublicKey;
-import org.gnunet.util.crypto.EcdsaSignature;
-import org.gnunet.util.crypto.EddsaSignature;
+import org.gnunet.util.crypto.*;
+import org.gnunet.voting.messages.KeyQueryResponseMessage;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -51,6 +51,14 @@
*/
String group;
/**
+ * When will the distributed key generation among the authorities start?
+ */
+ AbsoluteTime keygenStartTime;
+ /**
+ * When will the distributed key generation among the authorities be
finished?
+ */
+ AbsoluteTime keygenEndTime;
+ /**
* List of choices for the election.
*/
List<String> choices;
@@ -74,21 +82,53 @@
* When are the election results discarded by the authority?
*/
AbsoluteTime endTime;
+ /**
+ * Mapping from authority alias to peer identity.
+ */
BiMap<String,PeerIdentity> authorities;
+ /**
+ * Signatures from the authority certifying that it
+ * will be available for this election.
+ */
SortedMap<String,EddsaSignature> registrationSigs;
+ /**
+ * Public key of the certificate authority for group membership.
+ */
EcdsaPublicKey caPub;
+ /**
+ * Public key of the issues.
+ */
EcdsaPublicKey issuerPub;
+ /**
+ * Signature of the issuer on the basic data of the ballot.
+ */
EcdsaSignature issuerSig;
+ /**
+ * Public key of the voter that fills out this ballot.
+ */
EcdsaPublicKey voterPub;
+ /**
+ * Confirmation for the fact that a vote was accepted by an authority.
+ */
SortedMap<String,EddsaSignature> confirmationSigs;
+ /**
+ * Certificate that a voter belongs to a certain group.
+ */
GroupCert groupCert;
+ /**
+ * Threshold public keys per authority alias.
+ * Ideally this should be the same for each authority, but with malicious
authorities
+ * we can't trust that, so we must collect all the keys.
+ */
+ SortedMap<String,KeyQueryResponseMessage> thresholdPublicKeys;
/**
- * Choice in plaintext.
- * This field would be encrypted in a secure version.
+ * Threshold for the election.
*/
- int choiceId = -1;
+ public int threshold;
+ EncryptedVote encryptedVote;
+
/**
* Load a ballot from file.
*
@@ -163,6 +203,14 @@
throw new InvalidBallotException("ballot must have elegibility
group");
}
group = optGroup.get();
+ Optional<Long> optThreshold = cfg.getValueNumber("election",
"THRESHOLD");
+ if (!optThreshold.isPresent()) {
+ throw new InvalidBallotException("ballot must have threshold");
+ }
+ if (optThreshold.get() <= 0) {
+ throw new InvalidBallotException("threshold must be positive");
+ }
+ threshold = optThreshold.get().intValue();
authorities = HashBiMap.create();
for (Map.Entry<String,String> e :
cfg.getSection("authorities").entrySet()) {
String alias = e.getKey();
@@ -215,16 +263,7 @@
}
confirmationSigs.put(e.getKey(), sig);
}
- Optional<String> optChoiceId = cfg.getValueString("vote", "CHOICE_ID");
- if (optChoiceId.isPresent()) {
- choiceId = Integer.parseInt(optChoiceId.get());
- if (choiceId < 0 || choiceId >= choices.size()) {
- throw new InvalidBallotException("invalid choice in vote");
- }
- } else {
- choiceId = -1;
- }
-
+ encryptedVote = EncryptedVote.parseFromConfiguration(cfg);
Optional<String> optVoterPub = cfg.getValueString("vote", "VOTER_PUB");
if (optVoterPub.isPresent()) {
voterPub = EcdsaPublicKey.fromString(optVoterPub.get());
@@ -238,10 +277,33 @@
concludeTime = getTime(cfg, "CONCLUDE");
queryTime = getTime(cfg, "QUERY");
endTime = getTime(cfg, "END");
+ keygenStartTime = getTime(cfg, "KEYGEN_START");
+ keygenEndTime = getTime(cfg, "KEYGEN_END");
if (cfg.haveValue("vote", "GROUP_SIG")) {
groupCert = GroupCert.fromBallotConfig(this, cfg);
}
+
+ thresholdPublicKeys = new TreeMap<String, KeyQueryResponseMessage>();
+ for (Map.Entry<String,String> e :
cfg.getSection("threshold-pubkeys").entrySet()) {
+ String alias = e.getKey();
+ if (!authorities.containsKey(alias)) {
+ throw new InvalidBallotException(String.format(
+ "Alias '%s' has threshold pubkey, but alias does not
belong to any authority.", alias));
+ }
+ Optional<String> optSig =
cfg.getValueString("threshold-pubkey-sigs", alias);
+ if (!optSig.isPresent()) {
+ throw new InvalidBallotException(String.format(
+ "no signature present for threshold pubkey from
authority '%s'", alias));
+ }
+
+ KeyQueryResponseMessage m = new KeyQueryResponseMessage();
+ m.signature = EddsaSignature.fromString(optSig.get());
+ m.signedGuidKey = new KeyQueryResponseMessage.BallotPublicKey();
+ m.signedGuidKey.ballotGuid = getBallotGuid();
+ m.signedGuidKey.publicKey =
ThresholdPublicKey.fromString(e.getValue());
+ }
+
}
/**
@@ -270,6 +332,8 @@
}
digest.update(issuerPub.y);
digest.update(caPub.y);
+ digest.update(Longs.toByteArray(keygenStartTime.getSeconds()));
+ digest.update(Longs.toByteArray(keygenEndTime.getSeconds()));
digest.update(Longs.toByteArray(startTime.getSeconds()));
digest.update(Longs.toByteArray(endTime.getSeconds()));
digest.update(Longs.toByteArray(closingTime.getSeconds()));
@@ -278,14 +342,46 @@
}
/**
+ * Get the threshold public key that the majority of authorities
+ * advertise. The majority key must have at least 'threshold' peers that
+ * advertise it in order to be valid
+ *
+ * @return the majority threshold public key
+ */
+ public ThresholdPublicKey getMajorityThresholdPublicKey() {
+ HashMap<ThresholdPublicKey,Integer> counts = Maps.newHashMap();
+ for (Map.Entry<String,KeyQueryResponseMessage> e :
thresholdPublicKeys.entrySet()) {
+ ThresholdPublicKey pk = e.getValue().signedGuidKey.publicKey;
+ if (counts.containsKey(pk)) {
+ counts.put(pk, counts.get(pk) + 1);
+ } else {
+ counts.put(pk, 0);
+ }
+ }
+ int maxCount = 0;
+ ThresholdPublicKey bestKey = null;
+ for (Map.Entry<ThresholdPublicKey, Integer> e : counts.entrySet()) {
+ if (e.getValue() > maxCount) {
+ maxCount = e.getValue();
+ bestKey = e.getKey();
+ }
+ }
+ if (maxCount < threshold) {
+ return null;
+ }
+ return bestKey;
+ }
+
+ /**
* Encode the given choice permanently in the ballot.
* Also encodes the voter's public key.
*
* @param choice the choice to encode the ballot
- * @param privateKey the private key to use for encoding
+ * @param voterPrivateKey the private key to use for encoding
*/
- public void encodeChoice(String choice, EcdsaPrivateKey privateKey) {
- choiceId = -1;
+ public void encodeChoice(String choice, ThresholdPublicKey
thresholdPublicKey,
+ EcdsaPrivateKey voterPrivateKey) {
+ int choiceId = -1;
int i = 0;
for (String possibleChoice : choices) {
if (choice.equals(possibleChoice)) {
@@ -293,10 +389,12 @@
}
i++;
}
- voterPub = privateKey.getPublicKey();
- if (choiceId == -1) {
+ voterPub = voterPrivateKey.getPublicKey();
+ if (choiceId < 0 || choiceId > 1) {
throw new InvalidBallotException(String.format("choice '%s' not
valid", choice));
}
+
+ encryptedVote = EncryptedVote.fromChoice(choiceId, thresholdPublicKey,
voterPrivateKey);
}
/**
@@ -310,6 +408,9 @@
cfg.setValueString("election", "GROUP", group);
cfg.setValueString("election", "CHOICES",
Joiner.on("//").join(choices));
cfg.setValueString("election", "CA_PUB", caPub.toString());
+ cfg.setValueNumber("election", "THRESHOLD", threshold);
+ cfg.setValueNumber("election", "TIMESTAMP_KEYGEN_START",
keygenStartTime.getSeconds());
+ cfg.setValueNumber("election", "TIMESTAMP_KEYGEN_END",
keygenEndTime.getSeconds());
cfg.setValueNumber("election", "TIMESTAMP_START",
startTime.getSeconds());
cfg.setValueNumber("election", "TIMESTAMP_CLOSING",
closingTime.getSeconds());
cfg.setValueNumber("election", "TIMESTAMP_QUERY",
queryTime.getSeconds());
@@ -332,8 +433,8 @@
cfg.setValueString("election", "ISSUER_PUB", issuerPub.toString());
cfg.setValueString("election", "ISSUER_SIG", issuerSig.toString());
}
- if (-1 != choiceId) {
- cfg.setValueNumber("vote", "CHOICE_ID", choiceId);
+ if (null != encryptedVote) {
+ encryptedVote.writeToConfiguration(cfg);
}
if (null != voterPub) {
cfg.setValueString("vote", "VOTER_PUB", voterPub.toString());
@@ -341,6 +442,14 @@
if (null != groupCert) {
groupCert.writeBallotConfig(cfg);
}
+ System.out.println("thresh set when writing: " +
thresholdPublicKeys.size());
+ for (Map.Entry<String,KeyQueryResponseMessage> e :
thresholdPublicKeys.entrySet()) {
+ System.out.println("writing tresh");
+ cfg.setValueString("threshold-pubkeys", e.getKey(),
+ e.getValue().signedGuidKey.publicKey.toString());
+ cfg.setValueString("threshold-pubkey-sigs", e.getKey(),
+ e.getValue().signature.toString());
+ }
return cfg;
}
@@ -371,6 +480,10 @@
buf.append(group);
buf.append("\n");
+ buf.append("Threshold: ");
+ buf.append(threshold);
+ buf.append("\n");
+
buf.append("Start Time: ");
buf.append(startTime.toFancyString());
buf.append("\n");
@@ -389,7 +502,7 @@
buf.append("Choices:\n");
for (int i = 0; i < choices.size(); i++) {
- buf.append(""+(i+1));
+ buf.append(i + 1);
buf.append(". '");
buf.append(choices.get(i));
buf.append("'\n");
@@ -430,7 +543,7 @@
else {
buf.append("ballot not submitted\n");
}
- if (choiceId != -1) {
+ if (encryptedVote != null) {
buf.append("choice selected\n");
} else {
buf.append("no choice selected\n");
@@ -538,4 +651,22 @@
voterPub = groupCert.getMemberPublicKey();
this.groupCert = groupCert;
}
+
+ /**
+ * Get the list of authorities that this ballot does not have a signature
+ * on the threshold key from.
+ */
+ public List<PeerIdentity> getRemainingKeyAuthorities() {
+ LinkedList<PeerIdentity> remaining = new LinkedList<PeerIdentity>();
+ for (Map.Entry<String,PeerIdentity> x : authorities.entrySet()) {
+ if (!thresholdPublicKeys.containsKey(x.getKey()))
+ remaining.add(x.getValue());
+ }
+ return remaining;
+ }
+
+ public void addThresholdPublicKey(PeerIdentity currentAuthority,
KeyQueryResponseMessage m) {
+ String alias = authorities.inverse().get(currentAuthority);
+ thresholdPublicKeys.put(alias, m);
+ }
}
Modified: gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java 2014-02-25
09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/voting/BallotTool.java 2014-02-25
11:15:15 UTC (rev 32476)
@@ -30,14 +30,14 @@
import org.gnunet.mesh.Mesh;
import org.gnunet.mesh.MeshRunabout;
import org.gnunet.mesh.TunnelEndHandler;
+import org.gnunet.secretsharing.ThresholdPublicKey;
import org.gnunet.testbed.CompressedConfig;
-import org.gnunet.util.AbsoluteTime;
-import org.gnunet.util.Configuration;
-import org.gnunet.util.PeerIdentity;
-import org.gnunet.util.Program;
+import org.gnunet.util.*;
import org.gnunet.util.getopt.Argument;
import org.gnunet.util.getopt.ArgumentAction;
import org.gnunet.voting.messages.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileOutputStream;
@@ -50,6 +50,9 @@
* Tool for creating, manipulating and submitting ballot files.
*/
public class BallotTool extends Program {
+ private static final Logger logger = LoggerFactory
+ .getLogger(BallotTool.class);
+
@Argument(
shortname = "e",
longname = "ego",
@@ -107,6 +110,12 @@
description = "incorporate the group cert into the ballot")
String groupCertFile = null;
+ @Argument(
+ shortname = "k",
+ longname = "request-key",
+ action = ArgumentAction.SET,
+ description = "request the threshold public key from authorities")
+ boolean requestKey = false;
@Argument(
shortname = "t",
@@ -115,14 +124,35 @@
description = "write a template ballot to the give ballot file")
boolean template = false;
+ /**
+ * The ego to use for the currently executing action.
+ */
private Identity.Ego ego;
+ /**
+ * The (possibly modified) ballot originally loaded
+ * from 'ballotFilename'
+ */
private Ballot ballot;
+
+ /**
+ * Filename to read the ballot from, and write modifications to.
+ */
private String ballotFilename;
+ /**
+ * Our handle to MESH.
+ */
private Mesh mesh;
+
+ /**
+ * A tunnel to 'currentAuthority' or null.
+ */
private Mesh.Tunnel tunnel;
+ /**
+ * The authority we are currently communicating with.
+ */
private PeerIdentity currentAuthority;
/**
@@ -131,32 +161,59 @@
*/
private boolean tunnelCommunicationFinished;
+ private RelativeTime tunnelReconnectBackoff = RelativeTime.STD_BACKOFF;
+
public class BallotTunnelEndHandler implements TunnelEndHandler {
@Override
- public void onTunnelEnd(Mesh.Tunnel tunnel) {
- // FIXME
+ public void onTunnelEnd(final Mesh.Tunnel tunnel) {
+ // FIXME: just re-running 'doCommands' is a bit of a hack
+ BallotTool.this.tunnel = null;
+ if (!tunnelCommunicationFinished) {
+ logger.warn("mesh tunnel disconnected, but operation not
finished");
+ Scheduler.addDelayed(tunnelReconnectBackoff, new
Scheduler.Task() {
+ @Override
+ public void run(Scheduler.RunContext ctx) {
+ doCommands();
+ }
+ });
+ tunnelReconnectBackoff = tunnelReconnectBackoff.backoff();
+ }
}
}
+ /**
+ * Destroy the tunnel to the authority as well
+ * as the mesh handle.
+ */
+ private void endMesh() {
+ tunnelCommunicationFinished = true;
+ if (null != tunnel) {
+ tunnel.destroy();
+ tunnel = null;
+ }
+ if (null != mesh) {
+ mesh.destroy();
+ mesh = null;
+ }
+ }
+
public class BallotRegisterReceiver extends MeshRunabout {
public void visit(BallotRegisterSuccessMessage m) {
System.out.println("ballot successfully registered");
ballot.addRegistrationSignature(currentAuthority,
m.registrationSignature);
writeBallot();
- tunnel.destroy();
- mesh.destroy();
+ endMesh();
}
public void visit(BallotRegisterFailureMessage m) {
System.out.println("registering failed: " + m.reason);
- tunnel.destroy();
- mesh.destroy();
+ endMesh();
+ setReturnValue(1);
}
-
}
public class QueryReceiver extends MeshRunabout {
- public void visit(QueryResponseMessage m) {
+ public void visit(ResultQueryResponseMessage m) {
if (m.results.length != ballot.choices.size()) {
System.out.println("failure to query result: malformed
response");
} else {
@@ -165,16 +222,30 @@
System.out.println("'" + ballot.choices.get(i) + "': " +
m.results[i]);
}
}
+ endMesh();
+ }
- tunnel.destroy();
- mesh.destroy();
+ public void visit(ResultQueryFailureMessage m) {
+ System.out.println("failure to query result: " + m.reason);
+ endMesh();
+ setReturnValue(1);
}
+ }
- public void visit(QueryFailureMessage m) {
+
+ public class PublicKeyReceiver extends MeshRunabout {
+ public void visit(KeyQueryResponseMessage m) {
+ System.out.println("got threshold public key!");
+ ballot.addThresholdPublicKey(currentAuthority, m);
+ writeBallot();
+ endMesh();
+ }
+ public void visit(KeyQueryFailureMessage m) {
System.out.println("failure to query result: " + m.reason);
- tunnel.destroy();
- mesh.destroy();
+ endMesh();
+ setReturnValue(1);
}
+
}
public class SubmitReceiver extends MeshRunabout {
@@ -183,19 +254,18 @@
System.out.println("vote successfully submitted");
ballot.addConfirmation(currentAuthority, m.confirmationSig);
writeBallot();
- tunnel.destroy();
- mesh.destroy();
+ endMesh();
}
public void visit(SubmitFailureMessage m) {
System.out.println("vote not submitted: " + m.reason);
- if (m.authorityTime != null) {
+ if (m.signedAuthorityTime != null) {
// FIXME: verify
System.out.println("authority time: " +
-
AbsoluteTime.fromNetwork(m.authorityTime.innerMessage).toFancyString());
+
AbsoluteTime.fromNetwork(m.signedAuthorityTime.time).toFancyString());
}
- tunnel.destroy();
- mesh.destroy();
+ endMesh();
+ setReturnValue(1);
}
}
@@ -220,6 +290,9 @@
}
}
+ /**
+ * Write the ballot back to disk.
+ */
private void writeBallot() {
try {
Files.write(ballot.serialize(), new File(ballotFilename),
Charsets.UTF_8);
@@ -228,6 +301,9 @@
}
}
+ /**
+ * Actually execute the action the user requested.
+ */
void doCommands() {
if (null != groupCertFile) {
Configuration groupCertConfig = new Configuration();
@@ -270,7 +346,13 @@
setReturnValue(1);
return;
}
- ballot.encodeChoice(select, ego.getPrivateKey());
+ ThresholdPublicKey thresholdPublicKey =
ballot.getMajorityThresholdPublicKey();
+ if (null == thresholdPublicKey) {
+ System.err.println("no threshold public key in ballot");
+ setReturnValue(1);
+ return;
+ }
+ ballot.encodeChoice(select, thresholdPublicKey,
ego.getPrivateKey());
writeBallot();
return;
}
@@ -297,7 +379,10 @@
m.groupCertExpiration =
ballot.groupCert.getExpiration().asMessage();
m.groupCert = ballot.groupCert.getSignature();
m.ballotGuid = ballot.getBallotGuid();
- m.choiceId = ballot.choiceId;
+ if (null == ballot.encryptedVote) {
+ throw new InvalidBallotException("no encrypted vote in
ballot");
+ }
+ m.encryptedVote = ballot.encryptedVote;
tunnel.send(m);
return;
}
@@ -313,15 +398,33 @@
return;
}
Random r = new Random();
- PeerIdentity authority =
remainingAuthorities.get(r.nextInt(remainingAuthorities.size()));
- System.out.println("querying authority" + authority.toString());
+ currentAuthority =
remainingAuthorities.get(r.nextInt(remainingAuthorities.size()));
+ System.out.println("querying authority " +
currentAuthority.toString());
mesh = new Mesh(cfg, new BallotTunnelEndHandler(), new
QueryReceiver());
- tunnel = mesh.createTunnel(authority,
TallyAuthorityDaemon.MESH_PORT, true, true, null);
- QueryMessage m = new QueryMessage();
- m.ballotGUID = ballot.getBallotGuid();
+ tunnel = mesh.createTunnel(currentAuthority,
TallyAuthorityDaemon.MESH_PORT, true, true, null);
+ ResultQueryMessage m = new ResultQueryMessage();
+ m.ballotGuid = ballot.getBallotGuid();
tunnel.send(m);
return;
}
+ if (requestKey) {
+ List<PeerIdentity> remainingAuthorities =
ballot.getRemainingKeyAuthorities();
+ if (remainingAuthorities.isEmpty()) {
+ System.err.println("all authorities already signed group key");
+ return;
+ }
+ Random r = new Random();
+ currentAuthority =
remainingAuthorities.get(r.nextInt(remainingAuthorities.size()));
+ System.out.println("asking authority for key " +
currentAuthority.toString());
+ mesh = new Mesh(cfg, new BallotTunnelEndHandler(), new
PublicKeyReceiver());
+ tunnel = mesh.createTunnel(currentAuthority,
TallyAuthorityDaemon.MESH_PORT, true, true, null);
+ KeyQueryMessage m = new KeyQueryMessage();
+ m.ballotGuid = ballot.getBallotGuid();
+ tunnel.send(m);
+ return;
+ }
+ setReturnValue(1);
+ System.err.println("no action specified");
}
@Override
@@ -342,7 +445,15 @@
System.err.println("ballot file does not exist");
return;
}
- ballot = new Ballot(ballotFilename);
+ try {
+ ballot = new Ballot(ballotFilename);
+ } catch (InvalidBallotException e) {
+ System.err.println("Invalid or incomplete ballot:");
+ System.err.println(e.getMessage());
+ setReturnValue(1);
+ return;
+ }
+ // if there's an ego name, look it up ...
if (null != egoName) {
Identity.lookup(getConfiguration(), egoName, new
IdentityCallback() {
@Override
Modified: gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/voting/TallyAuthorityDaemon.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -30,6 +30,9 @@
import org.gnunet.construct.UInt32;
import org.gnunet.mesh.Mesh;
import org.gnunet.mesh.MeshRunabout;
+import org.gnunet.secretsharing.*;
+import org.gnunet.secretsharing.callbacks.DecryptCallback;
+import org.gnunet.secretsharing.callbacks.SecretReadyCallback;
import org.gnunet.testbed.CompressedConfig;
import org.gnunet.util.*;
import org.gnunet.util.crypto.*;
@@ -37,28 +40,37 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.math.BigInteger;
import java.util.*;
/**
- * Daemon that is responsible for counting votes.
+ * Daemon that is responsible for accepting and counting votes.
*/
public class TallyAuthorityDaemon extends Program {
private static final Logger logger = LoggerFactory
.getLogger(TallyAuthorityDaemon.class);
+ /**
+ * Mesh port used to connect to to the tally authority daemon.
+ */
public static final int MESH_PORT = 1002;
+
+ /**
+ * Mesh handle.
+ */
private Mesh mesh;
+
+ /**
+ * Private key of the local peer.
+ */
private EddsaPrivateKey authorityPrivateKey;
+
+ /**
+ * Public key of the local peer.
+ */
private EddsaPublicKey authorityPublicKey;
- public static class Vote implements Message {
- @UInt32
- public int choice;
- @NestedMessage
- public EcdsaPublicKey voterPub;
- }
-
/**
* All elections known to this authority
*/
@@ -74,24 +86,53 @@
Ballot ballot;
/**
- * Set of voters that have submitted their ballot.
+ * The threshold crypto share, null if the key has not yet been
+ * established.
*/
- Set<EcdsaPublicKey> voters = new HashSet<EcdsaPublicKey>();
+ Share share;
/**
+ * A voter is in this set if its vote has been in the consensus.
+ */
+ Set<EcdsaPublicKey> countedVoters = new HashSet<EcdsaPublicKey>();
+
+ /**
+ * Key generation session.
+ */
+ KeyGeneration keyGeneration;
+
+ /**
* Consensus with the other authorities on the set of ballots.
*/
Consensus consensus;
+ /**
+ * Are we done with the vote consensus?
+ */
boolean consensusDone;
/**
+ * Product of all encrypted votes (mod q), used to compute the final
tally.
+ */
+ Ciphertext voteProduct;
+
+ /**
* Maping from choice to number of votes for that choice.
+ * In our currently simplified implementation, tally.length is always
2.
+ * If the tally has not been counted yet, 'tally' is null.
*/
- int[] tally;
+ long[] tally;
+
+ /**
+ * The decrypt session.
+ */
+ Decryption decryption;
}
- static class ElectionConsensusConclude implements ConsensusCallback {
+ /**
+ * Callbacks for the vote consensus.
+ */
+ class ElectionConsensusConclude implements ConsensusCallback {
private final ElectionState electionState;
public ElectionConsensusConclude(ElectionState electionState) {
@@ -100,22 +141,39 @@
@Override
public void onElement(ConsensusElement element) {
System.out.println("got element from consensus");
- Vote vote = Construct.parseAs(element.data, Vote.class);
- if (vote.choice >= 0 && vote.choice < electionState.tally.length) {
- electionState.tally[vote.choice] += 1;
- }
+ EncryptedVote vote = Construct.parseAs(element.data,
EncryptedVote.class);
+ electionState.voteProduct =
electionState.voteProduct.multiply(vote.v);
}
@Override
public void onDone() {
- System.out.println("got element from consensus");
+ System.out.println("consensus concluded");
electionState.consensusDone = true;
electionState.consensus.destroy();
electionState.consensus = null;
+
+ electionState.decryption = new Decryption(
+ getConfiguration(),
+ electionState.share,
+ electionState.voteProduct,
+ electionState.ballot.concludeTime,
+ electionState.ballot.queryTime,
+ new DecryptCallback() {
+ @Override
+ public void onResult(Plaintext plaintext) {
+ logger.info("got decypt result");
+ long l = electionState.countedVoters.size();
+ long t = plaintext.bruteForceDiscreteLog(l);
+ logger.info("brute-forced result");
+ electionState.tally = new long[2];
+ electionState.tally[0] = (l - t) / 2;
+ electionState.tally[1] = l -
electionState.tally[0];
+ }
+ });
}
}
- static class ConsensusConcludeTask implements Scheduler.Task {
+ class ConsensusConcludeTask implements Scheduler.Task {
/**
* Which election on this authority is the consensus conclude for?
*/
@@ -130,11 +188,30 @@
}
}
- private EddsaSignedMessage<AbsoluteTimeMessage> getTimeSigMessage() {
- AbsoluteTimeMessage m = AbsoluteTime.now().asMessage();
- return EddsaSignedMessage.signMessage(m, 0, authorityPrivateKey,
authorityPublicKey);
+ static class SecretReady implements SecretReadyCallback {
+ private final ElectionState electionState;
+
+ public SecretReady(ElectionState electionState) {
+ this.electionState = electionState;
+ }
+
+ @Override
+ public void onSecretReady(Share share) {
+ electionState.keyGeneration = null;
+ electionState.share = share;
+ }
}
+ private SubmitFailureMessage.SignedAuthorityTime getTimeSigMessage() {
+ SubmitFailureMessage.SignedAuthorityTime tm = new
SubmitFailureMessage.SignedAuthorityTime();
+ // FIXME!
+ tm.purpose = 0;
+ tm.time = AbsoluteTime.now().asMessage();
+ tm.signature = authorityPrivateKey.sign(authorityPublicKey, tm.purpose,
+ Construct.toBinary(tm.time));
+ return tm;
+ }
+
private class TallyMeshReceiver extends MeshRunabout {
public void visit(SubmitMessage m) {
logger.debug("got submit message");
@@ -143,32 +220,23 @@
SubmitFailureMessage fm = new SubmitFailureMessage();
fm.reason = "no matching ballot found";
getSender().send(fm);
- } else if (m.choiceId < 0 || m.choiceId >=
electionState.tally.length) {
- SubmitFailureMessage fm = new SubmitFailureMessage();
- fm.reason = "invalid vote";
- getSender().send(fm);
- } else if (electionState.voters.contains(m.voterPub)) {
- SubmitFailureMessage fm = new SubmitFailureMessage();
- fm.reason = "duplicate vote detected";
- getSender().send(fm);
} else if (!electionState.ballot.startTime.isDue()) {
SubmitFailureMessage fm = new SubmitFailureMessage();
fm.reason = "too early to submit vote";
- fm.authorityTime = getTimeSigMessage();
+ fm.signedAuthorityTime = getTimeSigMessage();
getSender().send(fm);
} else if (electionState.ballot.closingTime.isDue()) {
SubmitFailureMessage fm = new SubmitFailureMessage();
fm.reason = "too late to submit vote";
- fm.authorityTime = getTimeSigMessage();
+ fm.signedAuthorityTime = getTimeSigMessage();
getSender().send(fm);
}
// FIXME: check signatures of voter and CA
else {
- electionState.voters.add(m.voterPub);
- Vote vote = new Vote();
- vote.choice = m.choiceId;
- vote.voterPub = m.voterPub;
- byte[] elem = Construct.toBinary(vote);
+ // we do *not* check for duplicate votes here,
+ // as consensus takes care of this, and there is no harm in
sending
+ // exact duplicates
+ byte[] elem = Construct.toBinary(m.encryptedVote);
electionState.consensus.insertElement(new
ConsensusElement(elem, 0));
SubmitSuccessMessage sm = new SubmitSuccessMessage();
sm.confirmationSig = EddsaSignature.randomGarbage();
@@ -200,11 +268,11 @@
return;
}
ElectionState electionState = new ElectionState();
- electionState.tally = new int[b.choices.size()];
electionState.ballot = b;
PeerIdentity[] ids = new PeerIdentity[b.getAuthorities().size()];
ids = b.getAuthorities().toArray(ids);
- electionState.consensus = new Consensus(getConfiguration(),
+ electionState.consensus = new Consensus(
+ getConfiguration(),
ids,
b.getBallotGuid(),
electionState.ballot.closingTime,
@@ -218,37 +286,83 @@
logger.info("concluding in {}",
b.closingTime.getRemaining().getSeconds());
Scheduler.addDelayed(b.closingTime.getRemaining(), t);
}
+ // we hash the GUID a second time, so that there's no
+ // collision with the consensus (as secretsharing also uses
consensus internally)
+ electionState.keyGeneration = new KeyGeneration(
+ getConfiguration(),
+ ids,
+ HashCode.hash(b.getBallotGuid().data),
+ electionState.ballot.keygenStartTime,
+ electionState.ballot.keygenEndTime,
+ electionState.ballot.threshold, new
SecretReady(electionState));
elections.put(guid, electionState);
+
BallotRegisterSuccessMessage rm = new
BallotRegisterSuccessMessage();
rm.registrationSignature = EddsaSignature.randomGarbage();
getSender().send(rm);
-
}
- public void visit(QueryMessage m) {
- ElectionState electionState = elections.get(m.ballotGUID);
+ public void visit(ResultQueryMessage m) {
+ logger.debug("got result query message");
+ ElectionState electionState = elections.get(m.ballotGuid);
if (null == electionState) {
- QueryFailureMessage rm = new QueryFailureMessage();
+ ResultQueryFailureMessage rm = new ResultQueryFailureMessage();
rm.reason = "no matching ballot found";
getSender().send(rm);
} else {
- if (!electionState.consensusDone) {
- QueryFailureMessage rm = new QueryFailureMessage();
- rm.reason = "consensus not finished (sorry...)";
+ if (!electionState.ballot.queryTime.isDue()) {
+ ResultQueryFailureMessage rm = new
ResultQueryFailureMessage();
+ rm.reason = "result query not allowed yet";
getSender().send(rm);
}
- else if (electionState.ballot.queryTime.isDue()) {
- QueryResponseMessage rm = new QueryResponseMessage();
+ else if (null == electionState.tally) {
+ ResultQueryFailureMessage rm = new
ResultQueryFailureMessage();
+ rm.reason = "tally not yet available";
+ getSender().send(rm);
+ }
+ else {
+ ResultQueryResponseMessage rm = new
ResultQueryResponseMessage();
rm.results = electionState.tally;
getSender().send(rm);
- } else {
- QueryFailureMessage rm = new QueryFailureMessage();
- rm.reason = "result query not allowed yet";
- getSender().send(rm);
}
}
getSender().receiveDone();
}
+
+ public void visit(KeyQueryMessage m) {
+ logger.debug("got key query message");
+ getSender().receiveDone();
+ ElectionState electionState = elections.get(m.ballotGuid);
+ if (null == electionState) {
+ KeyQueryFailureMessage rm = new KeyQueryFailureMessage();
+ rm.reason = "no matching ballot found";
+ getSender().send(rm);
+ return;
+ }
+ if (!electionState.ballot.keygenEndTime.isDue()) {
+ KeyQueryFailureMessage rm = new KeyQueryFailureMessage();
+ rm.reason = "key query not allowed yet";
+ getSender().send(rm);
+ return;
+ }
+ if (null == electionState.share) {
+ KeyQueryFailureMessage rm = new KeyQueryFailureMessage();
+ rm.reason = "key not yet established";
+ getSender().send(rm);
+ return;
+ }
+ KeyQueryResponseMessage.BallotPublicKey ballotPublicKey = new
KeyQueryResponseMessage.BallotPublicKey();
+ ballotPublicKey.ballotGuid = electionState.ballot.getBallotGuid();
+ ballotPublicKey.publicKey = electionState.share.publicKey;
+
+ KeyQueryResponseMessage rm = new KeyQueryResponseMessage();
+ rm.signedGuidKey = ballotPublicKey;
+ // FIXME!
+ rm.purpose = 0;
+ rm.signature = authorityPrivateKey.sign(authorityPublicKey,
rm.purpose,
+ Construct.toBinary(rm.signedGuidKey));
+ getSender().send(rm);
+ }
}
public TallyAuthorityDaemon(String[] args) {
@@ -266,5 +380,15 @@
public void run() {
logger.info("running tally daemon");
mesh = new Mesh(getConfiguration(), null, null, new
TallyMeshReceiver(), MESH_PORT);
+
+ Scheduler.addDelayed(RelativeTime.FOREVER, new Scheduler.Task() {
+ @Override
+ public void run(Scheduler.RunContext ctx) {
+ if (null != mesh) {
+ mesh.destroy();
+ mesh = null;
+ }
+ }
+ });
}
}
Added:
gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryFailureMessage.java
===================================================================
---
gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryFailureMessage.java
(rev 0)
+++
gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryFailureMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -0,0 +1,11 @@
+package org.gnunet.voting.messages;
+
+import org.gnunet.construct.UnionCase;
+import org.gnunet.construct.ZeroTerminatedString;
+import org.gnunet.util.GnunetMessage;
+
address@hidden(42015)
+public class KeyQueryFailureMessage implements GnunetMessage.Body {
+ @ZeroTerminatedString
+ public String reason;
+}
Added: gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryMessage.java
(rev 0)
+++ gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -0,0 +1,12 @@
+package org.gnunet.voting.messages;
+
+import org.gnunet.construct.NestedMessage;
+import org.gnunet.construct.UnionCase;
+import org.gnunet.util.GnunetMessage;
+import org.gnunet.util.HashCode;
+
address@hidden(42013)
+public class KeyQueryMessage implements GnunetMessage.Body {
+ @NestedMessage
+ public HashCode ballotGuid;
+}
Added:
gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryResponseMessage.java
===================================================================
---
gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryResponseMessage.java
(rev 0)
+++
gnunet-java/src/main/java/org/gnunet/voting/messages/KeyQueryResponseMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -0,0 +1,51 @@
+/*
+ This file is part of GNUnet.
+ (C) 2014 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+package org.gnunet.voting.messages;
+
+import org.gnunet.construct.Message;
+import org.gnunet.construct.NestedMessage;
+import org.gnunet.construct.UInt32;
+import org.gnunet.construct.UnionCase;
+import org.gnunet.secretsharing.ThresholdPublicKey;
+import org.gnunet.util.GnunetMessage;
+import org.gnunet.util.HashCode;
+import org.gnunet.util.crypto.EddsaSignature;
+
address@hidden(42014)
+public class KeyQueryResponseMessage implements GnunetMessage.Body {
+
+ public static class BallotPublicKey implements Message {
+ @NestedMessage
+ public HashCode ballotGuid;
+
+ @NestedMessage
+ public ThresholdPublicKey publicKey;
+ }
+
+ @NestedMessage
+ public EddsaSignature signature;
+
+ @UInt32
+ public int purpose;
+
+ @NestedMessage
+ public BallotPublicKey signedGuidKey;
+}
Added:
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryFailureMessage.java
===================================================================
---
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryFailureMessage.java
(rev 0)
+++
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryFailureMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -0,0 +1,31 @@
+/*
+ This file is part of GNUnet.
+ (C) 2012, 2013 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+package org.gnunet.voting.messages;
+
+import org.gnunet.construct.UnionCase;
+import org.gnunet.construct.ZeroTerminatedString;
+import org.gnunet.util.GnunetMessage;
+
address@hidden(42009)
+public class ResultQueryFailureMessage implements GnunetMessage.Body {
+ @ZeroTerminatedString
+ public String reason;
+}
Added:
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryMessage.java
===================================================================
---
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryMessage.java
(rev 0)
+++
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -0,0 +1,12 @@
+package org.gnunet.voting.messages;
+
+import org.gnunet.construct.NestedMessage;
+import org.gnunet.construct.UnionCase;
+import org.gnunet.util.GnunetMessage;
+import org.gnunet.util.HashCode;
+
address@hidden(42005)
+public class ResultQueryMessage implements GnunetMessage.Body {
+ @NestedMessage
+ public HashCode ballotGuid;
+}
Added:
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryResponseMessage.java
===================================================================
---
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryResponseMessage.java
(rev 0)
+++
gnunet-java/src/main/java/org/gnunet/voting/messages/ResultQueryResponseMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -0,0 +1,12 @@
+package org.gnunet.voting.messages;
+
+
+import org.gnunet.construct.*;
+import org.gnunet.util.GnunetMessage;
+import org.gnunet.util.HashCode;
+
address@hidden(42006)
+public class ResultQueryResponseMessage implements GnunetMessage.Body {
+ @IntegerFill(signed = false, bitSize = 32)
+ public long[] results;
+}
Modified:
gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitFailureMessage.java
===================================================================
---
gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitFailureMessage.java
2014-02-25 09:42:06 UTC (rev 32475)
+++
gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitFailureMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -22,17 +22,27 @@
import org.gnunet.construct.NestedMessage;
+import org.gnunet.construct.UInt32;
import org.gnunet.construct.UnionCase;
import org.gnunet.construct.ZeroTerminatedString;
import org.gnunet.util.AbsoluteTimeMessage;
import org.gnunet.util.GnunetMessage;
-import org.gnunet.util.crypto.EcdsaSignedMessage;
-import org.gnunet.util.crypto.EddsaSignedMessage;
+import org.gnunet.util.crypto.EddsaSignature;
@UnionCase(42010)
public class SubmitFailureMessage implements GnunetMessage.Body {
+ public static class SignedAuthorityTime {
+ @NestedMessage
+ public EddsaSignature signature;
+ @UInt32
+ public int purpose;
+ @NestedMessage
+ public AbsoluteTimeMessage time;
+ }
+
@ZeroTerminatedString
public String reason;
+
@NestedMessage(optional = true)
- public EddsaSignedMessage<AbsoluteTimeMessage> authorityTime;
+ public SignedAuthorityTime signedAuthorityTime;
}
Modified:
gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/java/org/gnunet/voting/messages/SubmitMessage.java
2014-02-25 11:15:15 UTC (rev 32476)
@@ -7,6 +7,7 @@
import org.gnunet.util.crypto.EcdsaPublicKey;
import org.gnunet.util.crypto.EcdsaSignature;
import org.gnunet.util.crypto.EddsaSignature;
+import org.gnunet.voting.EncryptedVote;
/**
* Message send by the voter to the election authority to submit a vote.
@@ -33,10 +34,12 @@
*/
@NestedMessage
public AbsoluteTimeMessage groupCertExpiration;
+
/**
- * The actual vote.
- * FIXME: this will be encrypted!
+ * The encrypted vote, including zero knowledge proofs
+ * for correctness.
+ * FIXME: wrap in a signature container
*/
- @UInt32
- public int choiceId;
+ @NestedMessage
+ public EncryptedVote encryptedVote;
}
Modified: gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt
===================================================================
--- gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/resources/org/gnunet/construct/MsgMap.txt
2014-02-25 11:15:15 UTC (rev 32476)
@@ -1,41 +1,30 @@
org.gnunet.util.Resolver$Address|0=org.gnunet.util.Resolver$TextualAddress
org.gnunet.util.Resolver$Address|1=org.gnunet.util.Resolver$NumericAddress
+org.gnunet.util.GnunetMessage$Body|1=org.gnunet.util.TestMessage
org.gnunet.util.GnunetMessage$Body|274=org.gnunet.mesh.TunnelDestroyMessage
-org.gnunet.util.GnunetMessage$Body|1=org.gnunet.util.TestMessage
org.gnunet.util.GnunetMessage$Body|273=org.gnunet.mesh.TunnelCreateMessage
org.gnunet.util.GnunetMessage$Body|272=org.gnunet.mesh.ClientConnectMessage
org.gnunet.util.GnunetMessage$Body|4=org.gnunet.util.Resolver$GetMessage
org.gnunet.util.GnunetMessage$Body|5=org.gnunet.util.Resolver$ResolverResponse
-org.gnunet.util.GnunetMessage$Body|143=org.gnunet.dht.ClientGetMessage
-org.gnunet.util.GnunetMessage$Body|142=org.gnunet.dht.ClientPutMessage
+org.gnunet.util.GnunetMessage$Body|276=org.gnunet.mesh.RejectMessage
org.gnunet.util.GnunetMessage$Body|10=org.gnunet.arm.messages.ResultMessage
org.gnunet.util.GnunetMessage$Body|11=org.gnunet.arm.messages.StatusMessage
+org.gnunet.util.GnunetMessage$Body|13=org.gnunet.arm.messages.ListResultMessage
org.gnunet.util.GnunetMessage$Body|286=org.gnunet.mesh.LocalAckMessage
-org.gnunet.util.GnunetMessage$Body|13=org.gnunet.arm.messages.ListResultMessage
org.gnunet.util.GnunetMessage$Body|285=org.gnunet.mesh.DataMessage
org.gnunet.util.GnunetMessage$Body|17=org.gnunet.hello.HelloMessage
-org.gnunet.util.GnunetMessage$Body|153=org.gnunet.dht.MonitorStartStop
org.gnunet.util.GnunetMessage$Body|42002=org.gnunet.voting.messages.BallotRegisterFailureMessage
org.gnunet.util.GnunetMessage$Body|42001=org.gnunet.voting.messages.BallotRegisterRequestMessage
-org.gnunet.util.GnunetMessage$Body|155=org.gnunet.dht.ClientPutConfirmationMessage
org.gnunet.util.GnunetMessage$Body|42007=org.gnunet.voting.messages.SubmitMessage
-org.gnunet.util.GnunetMessage$Body|42006=org.gnunet.voting.messages.QueryResponseMessage
-org.gnunet.util.GnunetMessage$Body|42005=org.gnunet.voting.messages.QueryMessage
-org.gnunet.util.GnunetMessage$Body|144=org.gnunet.dht.ClientGetStopMessage
-org.gnunet.util.GnunetMessage$Body|145=org.gnunet.dht.ClientResultMessage
+org.gnunet.util.GnunetMessage$Body|42006=org.gnunet.voting.messages.ResultQueryResponseMessage
+org.gnunet.util.GnunetMessage$Body|42005=org.gnunet.voting.messages.ResultQueryMessage
org.gnunet.util.GnunetMessage$Body|42010=org.gnunet.voting.messages.SubmitFailureMessage
-org.gnunet.util.GnunetMessage$Body|42009=org.gnunet.voting.messages.QueryFailureMessage
+org.gnunet.util.GnunetMessage$Body|42009=org.gnunet.voting.messages.ResultQueryFailureMessage
org.gnunet.util.GnunetMessage$Body|42008=org.gnunet.voting.messages.SubmitSuccessMessage
-org.gnunet.util.GnunetMessage$Body|149=org.gnunet.dht.MonitorGetMessage
-org.gnunet.util.GnunetMessage$Body|150=org.gnunet.dht.MonitorGetRespMessage
-org.gnunet.util.GnunetMessage$Body|151=org.gnunet.dht.MonitorPutMessage
+org.gnunet.util.GnunetMessage$Body|42015=org.gnunet.voting.messages.KeyQueryFailureMessage
+org.gnunet.util.GnunetMessage$Body|42014=org.gnunet.voting.messages.KeyQueryResponseMessage
+org.gnunet.util.GnunetMessage$Body|42013=org.gnunet.voting.messages.KeyQueryMessage
org.gnunet.util.GnunetMessage$Body|42012=org.gnunet.voting.messages.BallotRegisterSuccessMessage
-org.gnunet.util.GnunetMessage$Body|171=org.gnunet.statistics.GetResponseEndMessage
-org.gnunet.util.GnunetMessage$Body|170=org.gnunet.statistics.GetResponseMessage
-org.gnunet.util.GnunetMessage$Body|169=org.gnunet.statistics.GetMessage
-org.gnunet.util.GnunetMessage$Body|168=org.gnunet.statistics.SetMessage
-org.gnunet.util.GnunetMessage$Body|173=org.gnunet.statistics.WatchResponseMessage
-org.gnunet.util.GnunetMessage$Body|172=org.gnunet.statistics.WatchMessage
org.gnunet.util.GnunetMessage$Body|524=org.gnunet.consensus.messages.ConcludeMessage
org.gnunet.util.GnunetMessage$Body|525=org.gnunet.consensus.messages.ConcludeDoneMessage
org.gnunet.util.GnunetMessage$Body|520=org.gnunet.consensus.messages.JoinMessage
@@ -47,37 +36,23 @@
org.gnunet.util.GnunetMessage$Body|781=org.gnunet.secretsharing.messages.ClientDecryptMessage
org.gnunet.util.GnunetMessage$Body|68=org.gnunet.core.DisconnectNotifyMessage
org.gnunet.util.GnunetMessage$Body|70=org.gnunet.core.NotifyInboundTrafficMessage
-org.gnunet.util.GnunetMessage$Body|476=org.gnunet.testbed.messages.PeerGetInformationMessage
org.gnunet.util.GnunetMessage$Body|71=org.gnunet.core.NotifyOutboundTrafficMessage
-org.gnunet.util.GnunetMessage$Body|477=org.gnunet.testbed.messages.PeerInformationMessage
org.gnunet.util.GnunetMessage$Body|64=org.gnunet.core.InitMessage
-org.gnunet.util.GnunetMessage$Body|474=org.gnunet.testbed.messages.PeerCreateSuccessMessage
org.gnunet.util.GnunetMessage$Body|65=org.gnunet.core.InitReplyMessage
-org.gnunet.util.GnunetMessage$Body|475=org.gnunet.testbed.messages.GenericOperationSuccessMessage
-org.gnunet.util.GnunetMessage$Body|472=org.gnunet.testbed.messages.ConnectionEventMessage
org.gnunet.util.GnunetMessage$Body|67=org.gnunet.core.ConnectNotifyMessage
-org.gnunet.util.GnunetMessage$Body|473=org.gnunet.testbed.messages.OperationFailEventMessage
org.gnunet.util.GnunetMessage$Body|76=org.gnunet.core.SendMessage
-org.gnunet.util.GnunetMessage$Body|470=org.gnunet.testbed.messages.OverlayConnectMessage
-org.gnunet.util.GnunetMessage$Body|471=org.gnunet.testbed.messages.PeerEventMessage
-org.gnunet.util.GnunetMessage$Body|468=org.gnunet.testbed.messages.PeerDestroyMessage
-org.gnunet.util.GnunetMessage$Body|466=org.gnunet.testbed.messages.PeerStartMessage
-org.gnunet.util.GnunetMessage$Body|467=org.gnunet.testbed.messages.PeerStopMessage
org.gnunet.util.GnunetMessage$Body|74=org.gnunet.core.SendMessageRequest
-org.gnunet.util.GnunetMessage$Body|464=org.gnunet.testbed.messages.PeerCreateMessage
org.gnunet.util.GnunetMessage$Body|75=org.gnunet.core.SendMessageReady
-org.gnunet.util.GnunetMessage$Body|465=org.gnunet.testbed.messages.PeerReconfigureMessage
org.gnunet.util.GnunetMessage$Body|627=org.gnunet.identity.messages.GetDefaultMessage
org.gnunet.util.GnunetMessage$Body|626=org.gnunet.identity.messages.UpdateListMessage
org.gnunet.util.GnunetMessage$Body|625=org.gnunet.identity.messages.ResultCodeMessage
-org.gnunet.util.GnunetMessage$Body|460=org.gnunet.testbed.messages.ControllerInitMessage
org.gnunet.util.GnunetMessage$Body|624=org.gnunet.identity.messages.StartMessage
org.gnunet.util.GnunetMessage$Body|631=org.gnunet.identity.messages.DeleteMessage
+org.gnunet.util.GnunetMessage$Body|323=org.gnunet.nse.UpdateMessage
org.gnunet.util.GnunetMessage$Body|630=org.gnunet.identity.messages.RenameMessage
-org.gnunet.util.GnunetMessage$Body|323=org.gnunet.nse.UpdateMessage
org.gnunet.util.GnunetMessage$Body|629=org.gnunet.identity.messages.CreateRequestMessage
+org.gnunet.util.GnunetMessage$Body|321=org.gnunet.nse.StartMessage
org.gnunet.util.GnunetMessage$Body|628=org.gnunet.identity.messages.SetDefaultMessage
-org.gnunet.util.GnunetMessage$Body|321=org.gnunet.nse.StartMessage
org.gnunet.util.GnunetMessage$Body|332=org.gnunet.peerinfo.InfoMessage
org.gnunet.util.GnunetMessage$Body|333=org.gnunet.peerinfo.InfoEnd
org.gnunet.util.GnunetMessage$Body|331=org.gnunet.peerinfo.ListAllPeersMessage
@@ -85,15 +60,44 @@
org.gnunet.util.GnunetMessage$Body|369=org.gnunet.transport.messages.BlacklistInitMessage
org.gnunet.util.GnunetMessage$Body|371=org.gnunet.transport.messages.BlacklistReplyMessage
org.gnunet.util.GnunetMessage$Body|370=org.gnunet.transport.messages.BlacklistQueryMessage
+org.gnunet.util.GnunetMessage$Body|380=org.gnunet.transport.messages.AddressIterateMessage
+org.gnunet.util.GnunetMessage$Body|383=org.gnunet.transport.messages.AddressIterateResponseMessage
+org.gnunet.util.GnunetMessage$Body|366=org.gnunet.transport.messages.SetQuotaMessage
+org.gnunet.util.GnunetMessage$Body|360=org.gnunet.transport.messages.StartMessage
+org.gnunet.util.GnunetMessage$Body|143=org.gnunet.dht.ClientGetMessage
+org.gnunet.util.GnunetMessage$Body|142=org.gnunet.dht.ClientPutMessage
+org.gnunet.util.GnunetMessage$Body|153=org.gnunet.dht.MonitorStartStop
+org.gnunet.util.GnunetMessage$Body|155=org.gnunet.dht.ClientPutConfirmationMessage
+org.gnunet.util.GnunetMessage$Body|144=org.gnunet.dht.ClientGetStopMessage
+org.gnunet.util.GnunetMessage$Body|145=org.gnunet.dht.ClientResultMessage
+org.gnunet.util.GnunetMessage$Body|149=org.gnunet.dht.MonitorGetMessage
+org.gnunet.util.GnunetMessage$Body|150=org.gnunet.dht.MonitorGetRespMessage
+org.gnunet.util.GnunetMessage$Body|151=org.gnunet.dht.MonitorPutMessage
+org.gnunet.util.GnunetMessage$Body|171=org.gnunet.statistics.GetResponseEndMessage
+org.gnunet.util.GnunetMessage$Body|170=org.gnunet.statistics.GetResponseMessage
+org.gnunet.util.GnunetMessage$Body|169=org.gnunet.statistics.GetMessage
+org.gnunet.util.GnunetMessage$Body|168=org.gnunet.statistics.SetMessage
+org.gnunet.util.GnunetMessage$Body|173=org.gnunet.statistics.WatchResponseMessage
+org.gnunet.util.GnunetMessage$Body|172=org.gnunet.statistics.WatchMessage
+org.gnunet.util.GnunetMessage$Body|476=org.gnunet.testbed.messages.PeerGetInformationMessage
+org.gnunet.util.GnunetMessage$Body|477=org.gnunet.testbed.messages.PeerInformationMessage
+org.gnunet.util.GnunetMessage$Body|474=org.gnunet.testbed.messages.PeerCreateSuccessMessage
+org.gnunet.util.GnunetMessage$Body|475=org.gnunet.testbed.messages.GenericOperationSuccessMessage
+org.gnunet.util.GnunetMessage$Body|472=org.gnunet.testbed.messages.ConnectionEventMessage
+org.gnunet.util.GnunetMessage$Body|473=org.gnunet.testbed.messages.OperationFailEventMessage
+org.gnunet.util.GnunetMessage$Body|470=org.gnunet.testbed.messages.OverlayConnectMessage
+org.gnunet.util.GnunetMessage$Body|471=org.gnunet.testbed.messages.PeerEventMessage
+org.gnunet.util.GnunetMessage$Body|468=org.gnunet.testbed.messages.PeerDestroyMessage
+org.gnunet.util.GnunetMessage$Body|466=org.gnunet.testbed.messages.PeerStartMessage
+org.gnunet.util.GnunetMessage$Body|467=org.gnunet.testbed.messages.PeerStopMessage
+org.gnunet.util.GnunetMessage$Body|464=org.gnunet.testbed.messages.PeerCreateMessage
+org.gnunet.util.GnunetMessage$Body|465=org.gnunet.testbed.messages.PeerReconfigureMessage
+org.gnunet.util.GnunetMessage$Body|460=org.gnunet.testbed.messages.ControllerInitMessage
org.gnunet.util.GnunetMessage$Body|500=org.gnunet.gns.messages.ClientLookupMessage
org.gnunet.util.GnunetMessage$Body|501=org.gnunet.gns.messages.ClientLookupResultMessage
-org.gnunet.util.GnunetMessage$Body|380=org.gnunet.transport.messages.AddressIterateMessage
-org.gnunet.util.GnunetMessage$Body|383=org.gnunet.transport.messages.AddressIterateResponseMessage
org.gnunet.util.GnunetMessage$Body|496=org.gnunet.testbed.messages.HelperReplyMessage
org.gnunet.util.GnunetMessage$Body|495=org.gnunet.testbed.messages.HelperInitMessage
-org.gnunet.util.GnunetMessage$Body|366=org.gnunet.transport.messages.SetQuotaMessage
-org.gnunet.util.GnunetMessage$Body|360=org.gnunet.transport.messages.StartMessage
org.gnunet.util.GnunetMessage$Body|483=org.gnunet.testbed.messages.ManagePeerServiceMessage
org.gnunet.gns.records.RecordData|65536=org.gnunet.gns.records.PkeyRecordData
org.gnunet.gns.records.RecordData|1=org.gnunet.gns.records.ARecordData
-# generated 2014/02/03 23:33:43
+# generated 2014/02/25 01:43:32
Modified: gnunet-java/src/main/resources/org/gnunet/voting/ballot-template.espec
===================================================================
--- gnunet-java/src/main/resources/org/gnunet/voting/ballot-template.espec
2014-02-25 09:42:06 UTC (rev 32475)
+++ gnunet-java/src/main/resources/org/gnunet/voting/ballot-template.espec
2014-02-25 11:15:15 UTC (rev 32476)
@@ -36,6 +36,9 @@
# public key of the election issuer
# ISSUER_PUB =
+# how many authorities would have to collude to
+# deanonymize a voter?
+THRESHOLD =
[authorities]
# specified as <authority-alias> = <peer-identity>, one entry for each
authority; e.g.
@@ -61,3 +64,12 @@
[confirmations]
# signatures by the authorities that counted the ballot, in the form of
<alias> = <sig>
+
+[threshold-pubkeys]
+# <authority-alias> = <treshold-pubkey>
+
+[threshold-pubkey-signatures]
+# Signature of the authority which certifies
+# that the pubkey (from the threshold-pubkeys section)
+# belongs to this election (with its GUID)
+# <autority-alias> = <signature>
\ No newline at end of file
Added: gnunet-java/src/test/python/test_voting.conf
===================================================================
--- gnunet-java/src/test/python/test_voting.conf
(rev 0)
+++ gnunet-java/src/test/python/test_voting.conf 2014-02-25 11:15:15 UTC
(rev 32476)
@@ -0,0 +1,5 @@
+[arm]
+DEFAULTSERVICES = mesh set consensus secretsharing
+
+[testbed]
+OVERLAY_TOPOLOGY = CLIQUE
Added: gnunet-java/src/test/python/test_voting_single.py
===================================================================
--- gnunet-java/src/test/python/test_voting_single.py
(rev 0)
+++ gnunet-java/src/test/python/test_voting_single.py 2014-02-25 11:15:15 UTC
(rev 32476)
@@ -0,0 +1,154 @@
+"""
+Test the voting implementation with a single authority.
+"""
+import os
+import subprocess
+import time
+
+
+NUM_AUTHORITIES = 1
+NUM_VOTERS = 1
+
+
+def wait_for_after(ts):
+ now = time.time()
+ if now < ts:
+ time.sleep(ts - now)
+
+def get_config(section, option, filename=None, expand=False):
+ args = ["gnunet-config"]
+ if filename is not None:
+ args.extend(["-c", filename])
+ args.extend(["-s", section])
+ args.extend(["-o", option])
+ if expand:
+ args.extend(["-f"])
+ return subprocess.check_output(args).strip()
+
+
+def create_identity(name, config=None):
+ args = ["gnunet-identity", "-C", name]
+ if config is not None:
+ args.extend(["-c", config])
+ subprocess.check_call(args)
+
+def get_identity_pubkey(name, config=None):
+ args = ["gnunet-identity", "-d", name]
+ if config is not None:
+ args.extend(["-c", config])
+ out = subprocess.check_output(args)
+ components = out.split("-")
+ return components[-1].strip()
+
+testdir = subprocess.check_output(["mktemp", "-d", "test-voting-XXXXXXXXXX.d",
"--tmpdir"])
+testdir = testdir.strip()
+ballot = os.path.join(testdir, "ballot")
+print "testdir", testdir
+
+
+testbed_conf = "test_voting.conf"
+env = os.environ.copy()
+env["GNUNET_TESTING_PREFIX"] = testdir
+testbed = subprocess.Popen(["gnunet-testbed-profiler", "-n", "-c",
testbed_conf, "-p", "1"], env=env)
+
+ballot_filename = os.path.join(testdir, "ballot")
+
+conf = []
+conf.append(os.path.join(testdir, "0", "config"))
+
+for c in conf:
+ while not os.path.exists(c):
+ print "waiting for creation of", c
+ time.sleep(0.1)
+
+print "test dir:", testdir
+
+
+# start authority
+# FIXME: using gnunet-arm for this might be nicer,
+auth = subprocess.Popen(["gnunet-daemon-ballot-tally", "-c", conf[0]])
+
+private_key_filename = get_config("peer", "private_key", conf[0], expand=True)
+
+public_key = subprocess.check_output(["gnunet-ecc", "--print-public-key",
private_key_filename]).strip()
+
+print "public key", public_key
+
+create_identity("voter0", conf[0])
+create_identity("issuer", conf[0])
+create_identity("groupca", conf[0])
+
+print "created identities"
+
+ballot = open(ballot_filename, "w")
+
+now = int(time.time())
+TS_KEYGEN_START = now + 10
+TS_KEYGEN_END = now + 20
+TS_START = now + 20
+TS_CLOSING = now + 25
+TS_CONCLUDE = now + 45
+TS_QUERY = now + 65
+TS_END = now + 65
+
+ballot.write("[authorities]\n")
+ballot.write("auth0 = %s\n" % public_key)
+ballot.write("[election]\n")
+ballot.write("TOPIC = mytopic\n")
+ballot.write("THRESHOLD = 1\n")
+ballot.write("CHOICES = yes//no\n")
+ballot.write("GROUP = mygroup\n")
+ballot.write("CA_PUB = %s\n" % get_identity_pubkey("groupca", conf[0]))
+ballot.write("TIMESTAMP_KEYGEN_START = %s\n" % TS_KEYGEN_START)
+ballot.write("TIMESTAMP_KEYGEN_END = %s\n" % TS_KEYGEN_END)
+ballot.write("TIMESTAMP_START = %s\n" % TS_START)
+ballot.write("TIMESTAMP_CLOSING = %s\n" % TS_CLOSING)
+ballot.write("TIMESTAMP_CONCLUDE = %s\n" % TS_CONCLUDE)
+ballot.write("TIMESTAMP_QUERY = %s\n" % TS_QUERY)
+ballot.write("TIMESTAMP_END = %s\n" % TS_END)
+
+ballot.close()
+
+groupcert_filename = os.path.join(testdir, "v0-cert")
+groupcert_file = open(groupcert_filename, "w")
+
+v0_pub = get_identity_pubkey("voter0", conf[0])
+
+subprocess.check_call(["gnunet-ballot-group-certify", "-c", conf[0],
+ "-g", "mygroup", "-e", "groupca", "-m", v0_pub], stdout=groupcert_file)
+
+groupcert_file.close()
+
+# register the ballot with authorities
+subprocess.check_call(["gnunet-ballot", "-LINFO", "-i", ballot_filename, "-e",
"issuer", "-c", conf[0]])
+
+# register the ballot with authorities
+subprocess.check_call(["gnunet-ballot", "-LINFO", "-r", ballot_filename, "-c",
conf[0]])
+
+wait_for_after(TS_KEYGEN_END)
+
+print "getting threshold public key"
+
+# get the threshold public key
+subprocess.check_call(["gnunet-ballot", "-LDEBUG", "-k", ballot_filename,
"-c", conf[0]])
+
+print "threshold public key retrieved"
+
+# add voter's group information
+subprocess.check_call(["gnunet-ballot", "-g", groupcert_filename,
ballot_filename, "-c", conf[0]])
+
+# actually vote ...
+subprocess.check_call(["gnunet-ballot", "-x", "yes", ballot_filename, "-e",
"voter0", "-c", conf[0]])
+
+wait_for_after(TS_START)
+
+# submit the ballot with the vote
+subprocess.check_call(["gnunet-ballot", "-s", ballot_filename, "-c", conf[0]])
+
+wait_for_after(TS_QUERY)
+
+# query the result
+subprocess.check_call(["gnunet-ballot", "-q", ballot_filename, "-c", conf[0]])
+
+# FIXME: cleanup
+
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r32476 - in gnunet-java: . src/main/java/org/gnunet/construct src/main/java/org/gnunet/construct/parsers src/main/java/org/gnunet/dht src/main/java/org/gnunet/mesh src/main/java/org/gnunet/secretsharing src/main/java/org/gnunet/secretsharing/messages src/main/java/org/gnunet/util src/main/java/org/gnunet/util/crypto src/main/java/org/gnunet/voting src/main/java/org/gnunet/voting/messages src/main/resources/org/gnunet/construct src/main/resources/org/gnunet/voting src/test src/test/python,
gnunet <=