gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r30794 - in gnunet-java: . src/main/java/org/gnunet/util sr


From: gnunet
Subject: [GNUnet-SVN] r30794 - in gnunet-java: . src/main/java/org/gnunet/util src/main/java/org/gnunet/util/crypto src/main/java/org/gnunet/voting src/test/java/org/gnunet/util
Date: Tue, 19 Nov 2013 12:15:53 +0100

Author: dold
Date: 2013-11-19 12:15:52 +0100 (Tue, 19 Nov 2013)
New Revision: 30794

Added:
   gnunet-java/src/test/java/org/gnunet/util/EcdheTest.java
   gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java
   gnunet-java/src/test/java/org/gnunet/util/Ed25519Test.java
Removed:
   gnunet-java/src/main/java/org/gnunet/util/crypto/Curve25519.java
Modified:
   gnunet-java/ISSUES
   gnunet-java/src/main/java/org/gnunet/util/HashCode.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/DsaPrng.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePrivateKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePublicKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/Ed25519.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java
   gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java
   gnunet-java/src/main/java/org/gnunet/voting/Ballot.java
   gnunet-java/src/main/java/org/gnunet/voting/CertifyGroupTool.java
   gnunet-java/src/main/java/org/gnunet/voting/GroupCert.java
   gnunet-java/src/test/java/org/gnunet/util/EddsaTest.java
Log:
- crypto + crypto tests


Modified: gnunet-java/ISSUES
===================================================================
--- gnunet-java/ISSUES  2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/ISSUES  2013-11-19 11:15:52 UTC (rev 30794)
@@ -1,44 +1,37 @@
-set:
- * generation collection and other stuff in set is implemented now
-  * some structural changes were necessary to implement everything
+general crypto implementation:
+ * key generation problem (setting/clearing bits) has been fixed in libgcrypt, 
but what about NaCl incompatibility?
+   (NaCl uses Curve25519/montgomery coordinates for ECDH, Ed25519/twisted 
edwards coordinates for EdDSA;
+    GNUnet with libgcrypt uses Ed25519 coordinates for everything; also in 
NaCl ecdhe pubkeys are just the x-coordinate)
+ * libgcrypt does not use montgomery x-addition (=> slower)
+  * MPI_EC_MONTGOMERY exists, but is not implemented yet
+ * reasons for not using NaCl and its optimized crypto-code?
+  * I guess (unclear) licensing?
+ * I _think_ the 
 
- * GNUNET_CONTAINER_HashMapIterator vs GNUNET_CONTAINER_MultiHashMapIterator
-  * very confusing name clash
+java crypto implementation:
+ implementing crypto is INCREDIBLY frustrating
 
- * there's now also an external iterator for multihashmap32
+ * original ed25519 java implementation had a pretty nice bug that occured 
with p=1/256 ...
 
- * documentation: I'll meet with cfuchs on wednesday
+ * 'gnunet-ecc -E' generates some random reference values
 
+ * gnunet-java now "implements" all three pk cryptosystems in pure java
+  * all but ECDSA pass sanity checks
+  * I'm relatively confident in Ed25519, it gives the same results as the 
python ref implementation
+  * aB key generation does not give the same results as GNUnet?
 
-doxygen:
- * would it be possible to remove e.g. the call graphs to make
-   the doxygen on gnunet.org more accessible?
-  * see e.g. https://gnunet.org/doxygen/de/d22/crypto__hkdf_8c.html
+set documentation:
+https://gnunet.org/content/gnunets-set-subsystem
 
 
+embeding curve points / using ECC for secret sharing:
+ * problem: with the usual message-embeding injections we lose homomorphic 
properties
+ * I found (=read somewhere ;) a scheme for elgamal with ecc, but i'm not 100%
+   sure all the ZKPs will still work ...
+
+
 secretsharing:
- * if you want a shorter name: vss (verifyable secret sharing)
- * discuss api
- * how should shares be serialized
-  * ... and should they contain the list of peers?
-  * => maybe a configuration file / string?
- * Should broadcast steps in the secret sharing protocol
-  be replaced by a consensus on signed commitments?
-  * this way all peers will have the same result
- * what if one of the authorities does not send some of the signed share parts 
s_{i,j}? who / how to blame?
-  * one idea is to use consensus with encrypted signeds{i,j}, so only the 
receiver can open it and
-    it can be known who sent their share parts 
-  * but: what if the encrypted value is wrong? there's no way to demonstrate 
this without revealing the
-    private key => can we somehow use ecdh+key derivation for that, so that 
the key can still
-    be revealed to blame somebody?
-  * round1: each peer puts a freshly generated, signed ecdh key in consensus
-  * in the share part exchange round: if a share part is wrong (signature 
verification or F_{i,j} verification fails),
-    the authority that finds out puts a complaint element in the consensus, 
revealing its private ecdh key
-  * the other authorities check the complaint for validity
-   * if the complaint is valid, the offending authority is excluded
-   * if the complaint is invalid, the complainer is excluded
- * what parameters should be the default?
-  * q (where q divides (p-1)) determines the size of the group, so how large 
do we want it?
-    (for practical purposes and security)
+ * see document I mailed you ...
 
 
+

Modified: gnunet-java/src/main/java/org/gnunet/util/HashCode.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/HashCode.java     2013-11-19 
10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/HashCode.java     2013-11-19 
11:15:52 UTC (rev 30794)
@@ -39,12 +39,48 @@
     @FixedSizeIntegerArray(length = 64, signed = false, bitSize = 8)
     public byte[] data; // should be immutable, final, can't be due to 
construct
 
-
+    /**
+     * Create a hash code initialized to zero.
+     */
     public HashCode() {
         data = new byte[64];
     }
 
-    public HashCode(byte[] hash) {
+    /**
+     * Create a HashCode from an existing SHA-512 hash code value.
+     *
+     * @param hash SHA-512 hash code value
+     * @return a HashCode
+     */
+    public static HashCode fromHashCode(byte[] hash) {
+        return new HashCode(hash);
+    }
+
+    /**
+     * Create a HashCode from data to be hashed.
+     *
+     * @param data data to hash
+     * @return a HashCode
+     */
+    public static HashCode hash(byte[] data) {
+        MessageDigest digest;
+        try {
+            digest = MessageDigest.getInstance("SHA-512");
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("crypto algorithm 'SHA-512' required 
but not provided");
+        }
+        byte[] hb = digest.digest(data);
+        HashCode h = new HashCode(hb);
+        return h;
+    }
+
+    /**
+     * Private constructor for HashCode from the hash code value.  Made
+     * private because there are two ways to create hash codes from byte 
arrays.
+     *
+     * @param hash hash code value to store in the HashCode
+     */
+    private HashCode(byte[] hash) {
         if (hash.length != 64) {
             throw new AssertionError("HashCode has to have length 64");
         }

Deleted: gnunet-java/src/main/java/org/gnunet/util/crypto/Curve25519.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/Curve25519.java    
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/Curve25519.java    
2013-11-19 11:15:52 UTC (rev 30794)
@@ -1,69 +0,0 @@
-/*
- 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.util.crypto;
-
-
-import java.math.BigInteger;
-
-/**
- * Java-only implementation of arithmetic on DJBs Curve25519.
- * The curve is a Montgomery curve, and we use coordinates in
- * Montgomery form.
- * Very, very slow.
- */
-public class Curve25519 {
-    private BigInteger X;
-    private BigInteger Z;
-
-    private BigInteger B = new BigInteger("486662");
-
-    // curve parameter q =  255^(-19)
-    private static final BigInteger q = new 
BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564819949");
-
-
-    public Curve25519(BigInteger X, BigInteger Z) {
-        this.X = X;
-        this.Z = Z;
-    }
-
-    public Curve25519 scalarmult(BigInteger e) {
-        if (e.equals(BigInteger.ZERO)) {
-            return new Curve25519(BigInteger.ZERO, BigInteger.ONE);
-        }
-        Curve25519 Q = scalarmult(e.shiftRight(1));
-        Q = Q.add(Q);
-        if (e.testBit(0)) Q = Q.add(this);
-        return Q;
-    }
-
-    /**
-     * Addition law for montgomery curve in montgomery coordinates.
-     *
-     * @param other
-     * @return
-     */
-    public Curve25519 add(Curve25519 other) {
-        return null;
-    }
-
-
-
-}

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/DsaPrng.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/DsaPrng.java       
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/DsaPrng.java       
2013-11-19 11:15:52 UTC (rev 30794)
@@ -32,15 +32,21 @@
 
 /**
  * Deterministic generator for the 'k'-value of DSA, conforming to RFC 6979.
- * SHA-1 is used as H.
+ * SHA-512 is used as H.
  */
 public class DsaPrng {
-    private static final int qlen = 32;
     private Mac mac;
     private byte[] V = new byte[64];
     private byte[] K = new byte[64];
+    private static final int qlen = 32;
 
-    public byte[] hmacK(byte[]... args) {
+    /**
+     * Compute the HMAC of the fiven data with our current K-value.
+     *
+     * @param args data
+     * @return result of the hmac
+     */
+    private byte[] hmacK(byte[]... args) {
         try {
             mac.init(new SecretKeySpec(K, "HmacSHA1"));
         } catch (InvalidKeyException e) {
@@ -52,6 +58,12 @@
         return mac.doFinal();
     }
 
+    /**
+     * Create an instance of the deterministic random number generator for the 
DSA 'k' vale.
+     *
+     * @param key private key
+     * @param message message
+     */
     public DsaPrng(byte[] key, byte[] message) {
         try {
             mac = Mac.getInstance("HmacSHA1");
@@ -73,6 +85,12 @@
         V = hmacK(V);
     }
 
+    /**
+     * Get the next deterministically generated candidate for
+     * the k value used in DSA.
+     *
+     * @return the next candidate value for 'k'
+     */
     public BigInteger nextK() {
         byte[] T = new byte[0];
         while (T.length < qlen) {

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePrivateKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePrivateKey.java       
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePrivateKey.java       
2013-11-19 11:15:52 UTC (rev 30794)
@@ -1,4 +1,89 @@
+/*
+ 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.util.crypto;
 
-public class EcdhePrivateKey {
+import org.gnunet.construct.FixedSizeIntegerArray;
+import org.gnunet.construct.Message;
+import org.gnunet.util.HashCode;
+
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+/**
+ * Private key for elliptic curve Diffie Hellman exchange.
+ */
+public class EcdhePrivateKey implements Message {
+    /**
+     * Private key byte string, in little endian form.
+     */
+    @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
+    public byte[] d;
+
+    /**
+     * Create an ecdh private key without allocating the key data.
+     */
+    public EcdhePrivateKey() {
+        // empty constructor for org.gnunet.construct.*
+    }
+
+    /**
+     * Get the public key for this private key.
+     *
+     * @return the public key for this private key
+     */
+    public EcdhePublicKey getPublicKey() {
+        BigInteger dCoeff = Ed25519.decodeScalar(d);
+        Ed25519 A = Ed25519.B.scalarmult(dCoeff);
+        return new EcdhePublicKey(A);
+    }
+
+    /*
+     * Derive key material from the give public key and a this private ECDHE 
key.
+     *
+     * @param publicKey public key to use for the ECDH
+     * @return key material
+     */
+    public HashCode ecdh(EcdhePublicKey publicKey) {
+        BigInteger dCoeff = Ed25519.decodeScalar(d);
+        Ed25519 Q = publicKey.asPoint().scalarmult(dCoeff);
+        // hash big endian representation of the x-coordinate.
+        return HashCode.hash(Q.P0.toByteArray());
+    }
+
+    /**
+     * Create a random private key.
+     *
+     * @return a random private key
+     */
+    public static EcdhePrivateKey createRandom() {
+        SecureRandom sr = new SecureRandom();
+        EcdhePrivateKey privateKey = new EcdhePrivateKey();
+        privateKey.d = new byte[32];
+        sr.nextBytes(privateKey.d);
+        // clear bits so that d mod 8 = 0
+        privateKey.d[0] &= (byte) 248;
+        // make sure the key fits in 255 bits
+        privateKey.d[31] &= (byte) 127;
+        // make sure key does not have lots of leading zeros
+        privateKey.d[31] |= (byte) 64;
+        return privateKey;
+    }
 }

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePublicKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePublicKey.java        
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdhePublicKey.java        
2013-11-19 11:15:52 UTC (rev 30794)
@@ -1,20 +1,83 @@
+/*
+ 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.util.crypto;
 
 import org.gnunet.construct.FixedSizeIntegerArray;
+import org.gnunet.util.Strings;
 
+/**
+ * Public key for elliptic curve diffie hellman exchange.
+ */
 public class EcdhePublicKey {
     /**
-     * x-coordinate of the point on the curve.
-     * The number is stored as little endian.
+     * Point on the curve, in Ed25519-compressed form.
      */
     @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
-    public byte[] x;
+    public byte[] y;
 
     /**
-     * y-coordinate of the point on the curve.
-     * The number is stored as little endian.
+     * Create a public key without allocating the key's data.
+     * Necessary for constructing the key with 'org.gnunet.construct.*'.
      */
-    @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
-    public byte[] y;
+    public EcdhePublicKey() {
+        // empty
+    }
 
+    /**
+     * Create a public key from the given point on the Ed25519 curve.
+     *
+     * @param a point to create the public key from
+     */
+    public EcdhePublicKey(Ed25519 a) {
+        y = a.encode();
+    }
+
+    /**
+     * Convert the public key to a point on the Ed25519 curve.
+     *
+     * @return point corresponding to this public key
+     */
+    public Ed25519 asPoint() {
+        return Ed25519.decode(y);
+    }
+
+    /**
+     * Get a GNUnet-style string representation of this key.
+     *
+     * @return the GNUnet-style string representation of this key.
+     */
+    @Override
+    public String toString() {
+        return Strings.dataToString(y);
+    }
+
+    /**
+     * Load an ECDHE key from a string.
+     *
+     * @param s string with the key data
+     * @return a public key
+     */
+    public EcdhePublicKey fromString(String s) {
+        EcdhePublicKey publicKey = new EcdhePublicKey();
+        Strings.stringToData(s, publicKey.y);
+        return publicKey;
+    }
 }

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java       
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPrivateKey.java       
2013-11-19 11:15:52 UTC (rev 30794)
@@ -1,3 +1,23 @@
+/*
+ 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.util.crypto;
 
 import org.gnunet.construct.FixedSizeIntegerArray;
@@ -2,36 +22,96 @@
 import org.gnunet.construct.Message;
+import org.gnunet.util.HashCode;
 
+import java.math.BigInteger;
 import java.security.SecureRandom;
 
+/**
+ * Private key for elliptic curve DSA.
+ */
 public class EcdsaPrivateKey implements Message {
+    /**
+     * Private key byte string, in little endian form.
+     */
     @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
     public byte[] d;
 
+    /**
+     * Create a private key without allocating the key data.
+     */
+    public EcdsaPrivateKey() {
+        // empty, needed by org.gnunet.construct.*
+    }
+
+    /**
+     * Get the anonymous private key.  Corresponds to '1'.
+     *
+     * @return the anonymous private ECDSA key
+     */
     public static EcdsaPrivateKey getAnonymous() {
-        return null;
+        EcdsaPrivateKey privateKey = new EcdsaPrivateKey();
+        privateKey.d = new byte[32];
+        privateKey.d[31] = 1;
+        return privateKey;
     }
 
+    /**
+     * Sign the given data with this private key.  Must include a purpose to 
mitigate
+     * replay / copy and paste attacks.
+     *
+     * @param purpose purpose for the signature
+     * @param data data to sign
+     * @return the signature over both the data and the purpose
+     */
     public EcdsaSignature sign(int purpose, byte[] data) {
-        EcdsaSignature signature = new EcdsaSignature();
-        return signature;
+        return sign(getPublicKey(), purpose, data);
     }
 
-    public static EcdsaPrivateKey fromFile(String privKeyFilename) {
-        return null;
+    /**
+     * Sign the given data with this private key.  Must include a purpose to 
mitigate
+     * replay / copy and paste attacks.
+     *
+     * @param publicKey public key corresponding to this private key, 
supplying this parameter
+     *                  leads to better performance as the public key does not 
have to be derived
+     * @param purpose purpose for the signature
+     * @param data data to sign
+     * @return the signature over both the data and the purpose
+     */
+    public EcdsaSignature sign(EcdsaPublicKey publicKey, int purpose, byte[] 
data) {
+        EcdsaSignature signature = new EcdsaSignature();
+        DsaPrng prng = new DsaPrng(d, data);
+        HashCode h = HashCode.hash(data);
+        byte[] zData = new byte[32];
+        System.arraycopy(h.data, 0, zData, 0, 32);
+        BigInteger z = new BigInteger(1, zData);
+        BigInteger dCoeff = Ed25519.decodeScalar(d);
+        while (true) {
+            BigInteger k = prng.nextK();
+            Ed25519 P = Ed25519.B.scalarmult(k);
+            BigInteger r = P.P0.mod(Ed25519.q);
+            if (r.equals(BigInteger.ZERO))
+                continue;
+            BigInteger s = 
k.modInverse(Ed25519.q).multiply(z.add(r.multiply(dCoeff)));
+            if (!r.equals(BigInteger.ZERO)) {
+                signature.r = Ed25519.encodeScalar(r);
+                signature.s = Ed25519.encodeScalar(s);
+                return signature;
+            }
+        }
     }
 
+    /**
+     * Get the public key for this private key.
+     *
+     * @return the public key for this private key
+     */
     public EcdsaPublicKey getPublicKey() {
-        // FIXME: this is not the real implementation,
-        // beware that this dummy implementation leaks the key!
-        EcdsaPublicKey publicKey = new EcdsaPublicKey();
-        byte[] v = new byte[32];
-        System.arraycopy(d, 0, v, 0, 8);
-        System.arraycopy(d, 0, v, 8, 8);
-        System.arraycopy(d, 0, v, 16, 8);
-        System.arraycopy(d, 0, v, 24, 8);
-        System.arraycopy(v, 0, publicKey.x, 0, 32);
-        System.arraycopy(v, 0, publicKey.y, 0, 32);
-        return publicKey;
+        Ed25519 A = Ed25519.B.scalarmult(Ed25519.decodeScalar(d));
+        return new EcdsaPublicKey(A);
     }
 
+    /**
+     * Create a randomly generated private ecdsa key.
+     *
+     * @return a freshly generated key
+     */
     public static EcdsaPrivateKey createRandom() {

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java        
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaPublicKey.java        
2013-11-19 11:15:52 UTC (rev 30794)
@@ -1,3 +1,23 @@
+/*
+ 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.util.crypto;
 
 import org.gnunet.construct.FixedSizeIntegerArray;
@@ -12,12 +32,6 @@
 public class EcdsaPublicKey implements Message {
     private static final Logger logger = LoggerFactory
             .getLogger(EcdsaPublicKey.class);
-    /**
-     * x-coordinate of the point on the curve.
-     * The number is stored as little endian.
-     */
-    @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
-    public byte[] x;
 
     /**
      * y-coordinate of the point on the curve.
@@ -26,28 +40,32 @@
     @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
     public byte[] y;
 
+    /**
+     * Create an ECDSA public key from a curve point.
+     *
+     * @param a curve point.
+     */
     public EcdsaPublicKey(Ed25519 a) {
-
+        y = a.encode();
     }
 
+    /**
+     * Create a public key without allocating space for the key data.
+     * Necessary for constructing this class with org.gnunet.construct.*
+     */
     public EcdsaPublicKey() {
-        x = new byte[32];
-        y = new byte[32];
+        // empty
     }
 
-    public static EcdsaPublicKey fromStringUncompressed(String s) {
-        if (s.length() != org.gnunet.util.Strings.getEncodedStringLength(64)) {
-            logger.debug("invalid key length");
-            return null;
-        }
-        byte[] data = new byte[64];
-        if (!Strings.stringToData(s, data)) {
-            logger.debug("invalid key format");
-            return null;
-        }
+    /**
+     * Load an ECDSA key from a string.
+     *
+     * @param s string with the key data
+     * @return a public key
+     */
+    public static EcdsaPublicKey fromString(String s) {
         EcdsaPublicKey publicKey = new EcdsaPublicKey();
-        System.arraycopy(data, 0, publicKey.x, 0, 32);
-        System.arraycopy(data, 32, publicKey.y, 0, 32);
+        Strings.stringToData(s, publicKey.y);
         return publicKey;
     }
 
@@ -60,17 +78,13 @@
     public static EcdsaPublicKey random() {
         SecureRandom sr = new SecureRandom();
         EcdsaPublicKey publicKey = new EcdsaPublicKey();
-        sr.nextBytes(publicKey.x);
         sr.nextBytes(publicKey.y);
         return publicKey;
     }
 
     @Override
     public String toString() {
-        byte[] keyData = new byte[64];
-        System.arraycopy(x, 0, keyData, 0, 32);
-        System.arraycopy(y, 0, keyData, 32, 32);
-        return Strings.dataToString(keyData);
+        return Strings.dataToString(y);
     }
 
     @Override
@@ -80,7 +94,6 @@
 
         EcdsaPublicKey publicKey = (EcdsaPublicKey) o;
 
-        if (!Arrays.equals(x, publicKey.x)) return false;
         if (!Arrays.equals(y, publicKey.y)) return false;
 
         return true;
@@ -88,8 +101,8 @@
 
     @Override
     public int hashCode() {
-        int result = Arrays.hashCode(x);
-        result = 31 * result + Arrays.hashCode(y);
+        int result = Arrays.hashCode(y);
         return result;
     }
+
 }

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java        
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignature.java        
2013-11-19 11:15:52 UTC (rev 30794)
@@ -23,11 +23,15 @@
 
 import org.gnunet.construct.FixedSizeIntegerArray;
 import org.gnunet.construct.Message;
+import org.gnunet.util.HashCode;
 import org.gnunet.util.Strings;
 
 import java.math.BigInteger;
-import java.nio.ByteBuffer;
+import java.security.SecureRandom;
 
+/**
+ * ECDSA Signature.
+ */
 public class EcdsaSignature implements Message {
     /**
      * R value of the signature in compressed form.
@@ -48,13 +52,38 @@
         this.s = new byte[32];
     }
 
+    /**
+     * Verify that this signature has been created by the given public key and 
signs the
+     * given data and purpose.
+     *
+     * @param m message that was signed
+     * @param purpose purpose of the signature
+     * @param publicKey public key to check for
+     * @return whether the signature is valid
+     */
     public boolean verify(byte[] m, int purpose, EcdsaPublicKey publicKey) {
-        return false;
+        HashCode h = HashCode.hash(m);
+        byte[] zData = new byte[32];
+        System.arraycopy(h.data, 0, zData, 0, 32);
+        BigInteger z = new BigInteger(1, zData);
+        BigInteger sCoeff = Ed25519.decodeScalar(s);
+        BigInteger rCoeff = Ed25519.decodeScalar(r);
+        BigInteger w = sCoeff.modInverse(Ed25519.q);
+        BigInteger u1 = z.multiply(w).mod(Ed25519.q);
+        BigInteger u2 = rCoeff.multiply(w).mod(Ed25519.q);
+        Ed25519 P = Ed25519.B.scalarmult(u1).add(Ed25519.B.scalarmult(u2));
+        return P.P0.equals(rCoeff.mod(Ed25519.q));
     }
 
+    /**
+     * Load a signature from a string.
+     *
+     * @param value serialized signature
+     * @return signature
+     */
     public static EcdsaSignature fromString(String value) {
         byte[] data = new byte[64];
-        if (!Strings.stringToData(value, data)) {
+        if (! Strings.stringToData(value, data)) {
             throw new AssertionError();
         }
         EcdsaSignature sig = new EcdsaSignature();
@@ -63,6 +92,12 @@
         return sig;
     }
 
+
+    /**
+     * Serialize the signature to a string.
+     *
+     * @return serialized signature
+     */
     @Override
     public String toString() {
         byte[] sigData = new byte[64];
@@ -72,4 +107,16 @@
     }
 
 
+    /**
+     * Return a signature that is invalid with very, very high probability.
+     *
+     * @return signature with random garbage
+     */
+    public static EcdsaSignature randomGarbage() {
+        EcdsaSignature sig = new EcdsaSignature();
+        SecureRandom r = new SecureRandom();
+        r.nextBytes(sig.r);
+        r.nextBytes(sig.s);
+        return sig;
+    }
 }

Modified: 
gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java    
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EcdsaSignedMessage.java    
2013-11-19 11:15:52 UTC (rev 30794)
@@ -26,7 +26,7 @@
 import org.gnunet.construct.UInt32;
 
 /**
- * A message together with a signature on the message and it's purpose.
+ * A message together with a signature on the message and its purpose.
  */
 public class EcdsaSignedMessage<M extends Message> implements Message {
     @NestedMessage

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/Ed25519.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/Ed25519.java       
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/Ed25519.java       
2013-11-19 11:15:52 UTC (rev 30794)
@@ -1,3 +1,23 @@
+/*
+ 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.util.crypto;
 
 
@@ -4,45 +24,125 @@
 import java.math.BigInteger;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
 
 /**
  * Java-only implementation of arithmetic on DJBs Ed25519.
  * Very, very slow.
  */
 public class Ed25519 {
-    // curve parameter b
-    static final int b = 256;
-    // curve parameter q =  255^(-19)
-    private static final BigInteger q = new 
BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564819949");
-    // q-3
-    private static final BigInteger qm2 = new 
BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564819947");
-    // q-3
-    private static final BigInteger qp3 = new 
BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564819952");
+    /**
+     * curve parameter b
+     */
+    public static final int b = 256;
+    /**
+     * curve parameter q =  2^255-19
+     */
+    public static final BigInteger q = new 
BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564819949");
+    /**
+     * q-2
+     */
+    private static final BigInteger qm2 = q.subtract(BigInteger.valueOf(2));
+    /**
+     * q+3
+     */
+    private static final BigInteger qp3 = q.add(BigInteger.valueOf(3));
+    /**
+     * ???
+     */
     static final BigInteger l = new 
BigInteger("7237005577332262213973186563042994240857116359379907606001950938285454250989");
+    /**
+     * ???
+     */
     private static final BigInteger d = new 
BigInteger("-4513249062541557337682894930092624173785641285191125241628941591882900924598840740");
+    /**
+     * ???
+     */
     private static final BigInteger I = new 
BigInteger("19681161376707505956807079304988542015446066515923890162744021073123829784752");
+    /**
+     * x-coordinate of the base point
+     */
+    private static final BigInteger Bx = new 
BigInteger("15112221349535400772501151409588531511454012693041857206046113283949847762202");
+    /**
+     * x-coordinate of the base point.
+     * Corresponds to '9' on Curve25519 in montgomery form
+     */
     private static final BigInteger By = new 
BigInteger("46316835694926478169428394003475163141307993866256225615783033603165251855960");
-    private static final BigInteger Bx = new 
BigInteger("15112221349535400772501151409588531511454012693041857206046113283949847762202");
-    static final Ed25519 B = new Ed25519(Bx.mod(q),By.mod(q));
-    // 2^255
-    private static final BigInteger un = new 
BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564819967");
+    /**
+     * base point
+     */
+    public static final Ed25519 B = new Ed25519(Bx.mod(q),By.mod(q));
 
+    /**
+     * Mask where only the first 255 bits are set.
+     */
+    private static final BigInteger mask255 = 
BigInteger.ONE.shiftLeft(255).subtract(BigInteger.ONE);
 
+    /**
+     * First coordinate (x) of this point.
+     */
     BigInteger P0;
+
+    /**
+     * Second coordinate (y) of this point.
+     */
     BigInteger P1;
 
+    /**
+     * Create a curve point from its coordinates.
+     * @param P0 x-coordinate
+     * @param P1 y-coordinate
+     */
     public Ed25519(BigInteger P0, BigInteger P1) {
         this.P0 = P0;
         this.P1 = P1;
     }
 
-    public static Ed25519 decompress(BigInteger y) {
+    /**
+     * Create a curve point from its string representation
+     *
+     * @param s the string representation
+     * @return a curve point corresponsing to 's'
+     */
+    public static Ed25519 decode(byte[] s) {
+        BigInteger y = decodeScalar(s);
+        BigInteger x = recoverX(y);
+        if ((x.testBit(0)?1:0) != bit(s, b-1)) {
+            x = q.subtract(x);
+        }
+        Ed25519 v = new Ed25519(x, y);
+        if (!v.isOnCurve()) {
+            throw new AssertionError("not on curve");
+        }
+        return v;
+    }
+
+    /**
+     * Get the i'th bit of a byte array
+     *
+     * @param h byte array
+     * @param i bit index
+     * @return value of the i'th bit in h
+     */
+    private static int bit(byte[] h, int i) {
+        return h[i/8] >> (i%8) & 1;
+    }
+
+    /**
+     * Recover the (positive) x-coordinate from y.
+     *
+     * @param y the y coordinate
+     * @return positive x-coordinate
+     */
+    public static BigInteger recoverX(BigInteger y) {
         BigInteger y2 = y.multiply(y);
         BigInteger xx = 
(y2.subtract(BigInteger.ONE)).multiply(inv(d.multiply(y2).add(BigInteger.ONE)));
         BigInteger x = xx.modPow(qp3.divide(BigInteger.valueOf(8)), q);
-        if (!x.multiply(x).subtract(xx).mod(q).equals(BigInteger.ZERO)) x = 
(x.multiply(I).mod(q));
-        if (!x.mod(BigInteger.valueOf(2)).equals(BigInteger.ZERO)) x = 
q.subtract(x);
-        return new Ed25519(x, y);
+        if (!x.multiply(x).subtract(xx).mod(q).equals(BigInteger.ZERO))
+            x = (x.multiply(I).mod(q));
+        if (!x.mod(BigInteger.valueOf(2)).equals(BigInteger.ZERO))
+            x = q.subtract(x);
+        return x;
     }
 
     /**
@@ -72,6 +172,12 @@
         return new Ed25519(x3.mod(q), y3.mod(q));
     }
 
+    /**
+     * Multiply this point by a scalar value.
+     *
+     * @param e scalar factor
+     * @return this*e
+     */
     public Ed25519 scalarmult(BigInteger e) {
         if (e.equals(BigInteger.ZERO)) {
             return new Ed25519(BigInteger.ZERO, BigInteger.ONE);
@@ -82,32 +188,59 @@
         return Q;
     }
 
+    /**
+     * Decode an integer from it's little endian byte array form.
+     * Takes a 32-byte array. The highest order bit is masked out.
+     *
+     * @param s string representation of a scalar
+     * @return scalar represented by 's'
+     */
     public static BigInteger decodeScalar(byte[] s) {
+        if (s.length != 32) {
+            throw new AssertionError();
+        }
+        // convert 's' to big endian
         byte[] out = new byte[s.length];
         for (int i=0; i < s.length;i++) {
             out[i] = s[s.length-1-i];
         }
-        return new BigInteger(out).and(un);
+        return new BigInteger(1, out).and(mask255);
     }
 
+    /**
+     * Encode a scalar to little endian byte array form.
+     * The resulting array is always 32 bytes large.
+     *
+     * @param n scalar to encode
+     * @return byte representation of 'n'
+     */
     public static byte[] encodeScalar(BigInteger n) {
-        byte[] in = n.toByteArray();
-        // reverse the array
-        for (int i = 0; i < in.length / 2; i++) {
-            byte tmp = in[i];
-            in[i] = in[in.length - i - 1];
-            in[in.length - i - 1] = tmp;
+        byte[] in = n.and(mask255).toByteArray();
+        if (in.length > 32) {
+            throw new AssertionError("size too big: " + in.length);
         }
-        return in;
+        byte[] full = new byte[32];
+        // reverse 'in' and copy to the beginning of 'full'
+        for (int i = 0; i < in.length; i++) {
+            full[in.length - i - 1] = in[i];
+        }
+        return full;
     }
 
+    /**
+     * Compress end encode a point on the curve.
+     *
+     * @return compressed and encoded point
+     */
     public byte[] encode() {
         byte[] out = encodeScalar(P1);
-        out[out.length-1] |= (P0.testBit(0) ? 0x80 : 0);
+        System.out.println("encodeScalar " + P1);
+        System.out.println("out1 " + Arrays.toString(out));
+        out[out.length-1] |= (P0.testBit(0) ? (byte) 0x80 : 0);
+        System.out.println("out2 " + Arrays.toString(out));
         return out;
     }
 
-
     /**
      * Hash the data in m and return 2^h(m)
      *
@@ -122,6 +255,7 @@
             throw new RuntimeException("crypto algorithm required but not 
provided");
         }
         final byte[] h = sha512.digest(m);
+        // reverse h
         for (int i = 0; i < 32; i++) {
             byte tmp = h[i];
             h[i] = h[63 - i];
@@ -130,4 +264,42 @@
         return new BigInteger(1, h);
     }
 
+    /**
+     * Check whether this point is on the curve, and thus valid.
+     *
+     * @return whether is point is on the curve
+     */
+    public boolean isOnCurve() {
+        BigInteger x = P0;
+        BigInteger y = P1;
+        BigInteger xx = x.multiply(x);
+        BigInteger yy = y.multiply(y);
+        BigInteger dxxyy = d.multiply(yy).multiply(xx);
+        return 
xx.negate().add(yy).subtract(BigInteger.ONE).subtract(dxxyy).mod(q).equals(BigInteger.ZERO);
+    }
+
+    @Override
+    public String toString() {
+        return "(" + P0.toString() + ", " + P1.toString() + ")";
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Ed25519 ed25519 = (Ed25519) o;
+
+        if (!P0.equals(ed25519.P0)) return false;
+        if (!P1.equals(ed25519.P1)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = P0.hashCode();
+        result = 31 * result + P1.hashCode();
+        return result;
+    }
 }

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java       
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPrivateKey.java       
2013-11-19 11:15:52 UTC (rev 30794)
@@ -1,3 +1,22 @@
+/*
+ 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.util.crypto;
 
 import org.gnunet.construct.FixedSizeIntegerArray;
@@ -17,7 +36,21 @@
         return sign(getPublicKey(), purpose, m);
     }
 
+
+    /**
+     * Sign the given data with this private key.  Must include a purpose to 
mitigate
+     * replay / copy and paste attacks.
+     *
+     * @param publicKey public key corresponding to this private key, 
supplying this parameter
+     *                  leads to better performance as the public key does not 
have to be derived
+     * @param purpose purpose for the signature
+     * @param m data to sign
+     * @return the signature over both the data and the purpose
+     */
     public EddsaSignature sign(EddsaPublicKey publicKey, int purpose, byte[] 
m) {
+        if (!publicKey.asPoint().isOnCurve()) {
+            throw new AssertionError();
+        }
         MessageDigest sha512;
         try {
             sha512 = MessageDigest.getInstance("SHA-512");
@@ -40,6 +73,12 @@
 
         BigInteger S = 
r.add(Ed25519.Hint(buf.array()).multiply(a)).mod(Ed25519.l);
 
+        if (!R.isOnCurve()) {
+            throw new AssertionError();
+        }
+        if (!publicKey.asPoint().isOnCurve()) {
+            throw new AssertionError();
+        }
         return new EddsaSignature(R, S);
     }
 
@@ -55,6 +94,12 @@
     }
 
 
+    /**
+     * Compute the coefficient that is used to derive the public key.
+     * See 'Daniel J. Bernstein et al, High-speed high-security signatures' 
for details.
+     *
+     * @return the public key coefficient
+     */
     private BigInteger computePublicKeyCoefficient() {
         MessageDigest sha512;
         try {
@@ -71,12 +116,30 @@
         return a;
     }
 
+    /**
+     * Get the public key for this private key.
+     *
+     * @return the public key for this private key
+     */
     public EddsaPublicKey getPublicKey() {
         BigInteger a = computePublicKeyCoefficient();
         Ed25519 A = Ed25519.B.scalarmult(a);
-        return new EddsaPublicKey(A);
+        if (!A.isOnCurve()) {
+            throw new AssertionError();
+        }
+        EddsaPublicKey publicKey = new EddsaPublicKey(A);
+
+        if (!A.equals(publicKey.asPoint())) {
+            throw new AssertionError();
+        }
+        return publicKey;
     }
 
+    /**
+     * Create a random private key.
+     *
+     * @return a random private key
+     */
     public static EddsaPrivateKey createRandom() {
         SecureRandom sr = new SecureRandom();
         EddsaPrivateKey privateKey = new EddsaPrivateKey();

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java        
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaPublicKey.java        
2013-11-19 11:15:52 UTC (rev 30794)
@@ -1,3 +1,23 @@
+/*
+ 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.util.crypto;
 
 import org.gnunet.construct.FixedSizeIntegerArray;
@@ -2,18 +22,22 @@
 import org.gnunet.construct.Message;
+import org.gnunet.util.Strings;
 
+import java.security.SecureRandom;
+import java.util.Arrays;
+
+/**
+ * EdDSA public key.
+ */
 public class EddsaPublicKey implements Message {
     /**
-     * x-coordinate of the point on the curve.
+     * y-coordinate of the point on the curve, in Ed25519-compressed form.
      * The number is stored as little endian.
      */
     @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
-    public byte[] x;
+    public byte[] y;
 
     /**
-     * y-coordinate of the point on the curve.
-     * The number is stored as little endian.
+     * Create a public key without allocating space for the key data.
+     * Necessary for constructing this class with org.gnunet.construct.*
      */
-    @FixedSizeIntegerArray(bitSize = 8, signed = false, length = 32)
-    public byte[] y;
-
     public EddsaPublicKey() {
@@ -23,11 +47,68 @@
     }
 
     public EddsaPublicKey(Ed25519 a) {
-        x = Ed25519.encodeScalar(a.P0);
-        y = Ed25519.encodeScalar(a.P1);
+        y = a.encode();
     }
 
-    public Ed25519 asPoint() {
-        return new Ed25519(Ed25519.decodeScalar(x), Ed25519.decodeScalar(y));
+    /**
+     * Convert this public key to a point on the Ed25519 curve.
+     *
+     * @return a point corresponding to this key
+     */
+    Ed25519 asPoint() {
+        return Ed25519.decode(y);
     }
+
+    /**
+     * Load an ECDSA key from a string.
+     *
+     * @param s string with the key data
+     * @return a public key
+     */
+    public EcdhePublicKey fromString(String s) {
+        EcdhePublicKey publicKey = new EcdhePublicKey();
+        Strings.stringToData(s, publicKey.y);
+        return publicKey;
+    }
+
+    /**
+     * Create a random public key.  The generated key might not even be valid
+     * (i.e. not on the curve), thus this method should only be used for 
testing.
+     *
+     * @return a random, possibly invalid public key
+     */
+    public static EcdsaPublicKey random() {
+        SecureRandom sr = new SecureRandom();
+        EcdsaPublicKey publicKey = new EcdsaPublicKey();
+        sr.nextBytes(publicKey.y);
+        return publicKey;
+    }
+
+    /**
+     * Converrt this public key to a string
+     *
+     * @return a string representing this public key
+     */
+    @Override
+    public String toString() {
+        return Strings.dataToString(y);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        EcdsaPublicKey publicKey = (EcdsaPublicKey) o;
+
+        if (!Arrays.equals(y, publicKey.y)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = Arrays.hashCode(y);
+        return result;
+    }
 }

Modified: gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java        
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignature.java        
2013-11-19 11:15:52 UTC (rev 30794)
@@ -18,26 +18,6 @@
   Boston, MA 02111-1307, USA.
  */
 
-/*
- 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.util.crypto;
 
 
@@ -75,7 +55,7 @@
     }
 
     public boolean verify(byte[] m, int purpose, EddsaPublicKey publicKey) {
-        Ed25519 R = Ed25519.decompress(Ed25519.decodeScalar(r));
+        Ed25519 R = Ed25519.decode(r);
         Ed25519 A = publicKey.asPoint();
         BigInteger S = Ed25519.decodeScalar(s);
         ByteBuffer Stemp = ByteBuffer.allocate(32 + 32 + m.length);
@@ -83,7 +63,19 @@
         BigInteger h = Ed25519.Hint(Stemp.array());
         Ed25519 ra = Ed25519.B.scalarmult(S);
         Ed25519 rb = R.add(A.scalarmult(h));
-        return rb.equals(rb);
+        if (!A.isOnCurve()) {
+            throw new AssertionError();
+        }
+        if (!R.isOnCurve()) {
+            throw new AssertionError();
+        }
+        if (!ra.isOnCurve()) {
+            throw new AssertionError();
+        }
+        if (!rb.isOnCurve()) {
+            throw new AssertionError();
+        }
+        return ra.equals(rb);
     }
 
     public static EddsaSignature fromString(String value) {

Modified: 
gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java    
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/util/crypto/EddsaSignedMessage.java    
2013-11-19 11:15:52 UTC (rev 30794)
@@ -18,26 +18,6 @@
   Boston, MA 02111-1307, USA.
  */
 
-/*
- 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.util.crypto;
 
 import org.gnunet.construct.Construct;

Modified: gnunet-java/src/main/java/org/gnunet/voting/Ballot.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/Ballot.java     2013-11-19 
10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/voting/Ballot.java     2013-11-19 
11:15:52 UTC (rev 30794)
@@ -180,13 +180,13 @@
         if (!optCaPub.isPresent()) {
             throw new InvalidBallotException("no CA pub key given");
         }
-        caPub = EcdsaPublicKey.fromStringUncompressed(optCaPub.get());
+        caPub = EcdsaPublicKey.fromString(optCaPub.get());
         if (null == caPub) {
             throw new InvalidBallotException("CA pub key invalid");
         }
         Optional<String> optIssuerPub = cfg.getValueString("election", 
"ISSUER_PUB");
         if (optIssuerPub.isPresent()) {
-            issuerPub = 
EcdsaPublicKey.fromStringUncompressed(optIssuerPub.get());
+            issuerPub = EcdsaPublicKey.fromString(optIssuerPub.get());
             Optional<String> optIssuerSig = cfg.getValueString("election", 
"ISSUER_SIG");
             if (!optIssuerSig.isPresent()) {
                 throw new InvalidBallotException("issuer public key present, 
but no signature");
@@ -227,7 +227,7 @@
 
         Optional<String> optVoterPub = cfg.getValueString("vote", "VOTER_PUB");
         if (optVoterPub.isPresent()) {
-            voterPub = 
EcdsaPublicKey.fromStringUncompressed(optVoterPub.get());
+            voterPub = EcdsaPublicKey.fromString(optVoterPub.get());
             if (null == voterPub) {
                 throw new InvalidBallotException("voter public key present but 
invalid");
             }
@@ -268,15 +268,13 @@
             digest.update(x.getKey().getBytes());
             digest.update(x.getValue().data);
         }
-        digest.update(issuerPub.x);
         digest.update(issuerPub.y);
-        digest.update(caPub.x);
         digest.update(caPub.y);
         digest.update(Longs.toByteArray(startTime.getSeconds()));
         digest.update(Longs.toByteArray(endTime.getSeconds()));
         digest.update(Longs.toByteArray(closingTime.getSeconds()));
         digest.update(Longs.toByteArray(queryTime.getSeconds()));
-        return new HashCode(digest.digest());
+        return HashCode.fromHashCode(digest.digest());
     }
 
     /**

Modified: gnunet-java/src/main/java/org/gnunet/voting/CertifyGroupTool.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/CertifyGroupTool.java   
2013-11-19 10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/voting/CertifyGroupTool.java   
2013-11-19 11:15:52 UTC (rev 30794)
@@ -109,7 +109,7 @@
             setReturnValue(1);
             return;
         }
-        final EcdsaPublicKey memberPubKey = 
EcdsaPublicKey.fromStringUncompressed(memberPubKeyString);
+        final EcdsaPublicKey memberPubKey = 
EcdsaPublicKey.fromString(memberPubKeyString);
         if (null == memberPubKey) {
             System.err.println("not a valid pubkey: '" + memberPubKeyString + 
"'");
             setReturnValue(1);

Modified: gnunet-java/src/main/java/org/gnunet/voting/GroupCert.java
===================================================================
--- gnunet-java/src/main/java/org/gnunet/voting/GroupCert.java  2013-11-19 
10:52:12 UTC (rev 30793)
+++ gnunet-java/src/main/java/org/gnunet/voting/GroupCert.java  2013-11-19 
11:15:52 UTC (rev 30794)
@@ -114,11 +114,11 @@
             throw new InvalidGroupCertException("invalid signature in group 
cert");
         }
         groupCert.expiration = AbsoluteTime.fromSeconds(optExpiration.get());
-        groupCert.signerPublicKey = 
EcdsaPublicKey.fromStringUncompressed(optCa.get());
+        groupCert.signerPublicKey = EcdsaPublicKey.fromString(optCa.get());
         if (null == groupCert.signerPublicKey) {
             throw new InvalidGroupCertException("invalid CA in group cert");
         }
-        groupCert.member = 
EcdsaPublicKey.fromStringUncompressed(optMember.get());
+        groupCert.member = EcdsaPublicKey.fromString(optMember.get());
         if (null == groupCert.member) {
             throw new InvalidGroupCertException("invalid member in group 
cert");
         }

Added: gnunet-java/src/test/java/org/gnunet/util/EcdheTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/EcdheTest.java                    
        (rev 0)
+++ gnunet-java/src/test/java/org/gnunet/util/EcdheTest.java    2013-11-19 
11:15:52 UTC (rev 30794)
@@ -0,0 +1,79 @@
+/*
+ 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.util;
+
+import org.gnunet.util.crypto.EcdhePrivateKey;
+import org.gnunet.util.crypto.EcdhePublicKey;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Test ECDHE.
+ */
+public class EcdheTest {
+
+    /**
+     * Test whether the key is correctly restored when serializing it.
+     */
+    @Test
+    public void test_compress() {
+        EcdhePrivateKey privKey1 = EcdhePrivateKey.createRandom();
+        EcdhePublicKey pubKey1 = privKey1.getPublicKey();
+        EcdhePublicKey pubKey2 = new EcdhePublicKey(pubKey1.asPoint());
+        Assert.assertArrayEquals(pubKey1.y, pubKey2.y);
+    }
+
+    /**
+     * Test a single ecdh operation.
+     */
+    @Test
+    public void test_simple() {
+        EcdhePrivateKey privKey1 = EcdhePrivateKey.createRandom();
+        EcdhePrivateKey privKey2 = EcdhePrivateKey.createRandom();
+        EcdhePublicKey pubKey1 = privKey1.getPublicKey();
+        EcdhePublicKey pubKey2 = privKey2.getPublicKey();
+
+        HashCode h1 = privKey1.ecdh(pubKey2);
+        HashCode h2 = privKey2.ecdh(pubKey1);
+
+        Assert.assertArrayEquals(h1.data, h2.data);
+    }
+
+    /**
+     * Test with values from the C GNUnet implementation.
+     * Generated with 'gnunet-ecc -E'
+     */
+    @Test
+    public void test_gnunet_values() {
+        EcdhePrivateKey privKey1 = new EcdhePrivateKey();
+        privKey1.d = new byte[32];
+        EcdhePrivateKey privKey2 = new EcdhePrivateKey();
+        privKey2.d = new byte[32];
+        
Strings.stringToData("FH7DONLOP82RMELK26NDEP8655HQFU9LUO36LNO1ENOJ5KOSRR00", 
privKey1.d);
+        
Strings.stringToData("LAJES5PBR68MJQP067I7DLJO3RUGG0EUHSOAVOFIDF24KBDE0SEG", 
privKey2.d);
+
+        EcdhePublicKey pubKey1 = privKey1.getPublicKey();
+        EcdhePublicKey pubKey2 = privKey2.getPublicKey();
+
+        
Assert.assertEquals("VU5U4KNC3OH5RUL6M5T6BPH52BFBICEG5Q60A43V97HQV1VD3AG0", 
pubKey1.toString());
+        
Assert.assertEquals("8DSB6D0OKS1SD71BKRTVT8OK18Q73Q7MUALJ76V9DQJO6J0170RG", 
pubKey2.toString());
+    }
+}

Added: gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java                    
        (rev 0)
+++ gnunet-java/src/test/java/org/gnunet/util/EcdsaTest.java    2013-11-19 
11:15:52 UTC (rev 30794)
@@ -0,0 +1,45 @@
+/*
+ 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.util;
+
+import org.gnunet.util.crypto.*;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EcdsaTest {
+    @Test
+    public void test_sign_success() {
+        byte[] data = "GNUnet".getBytes();
+        EcdsaPrivateKey privateKey = EcdsaPrivateKey.createRandom();
+        EcdsaPublicKey publicKey = privateKey.getPublicKey();
+        EcdsaSignature signature = privateKey.sign(publicKey, 0, data);
+        Assert.assertTrue(signature.verify(data, 0, publicKey));
+    }
+
+    @Test
+    public void test_sign_failure() {
+        byte[] data = "GNUnet".getBytes();
+        EcdsaPrivateKey privateKey = EcdsaPrivateKey.createRandom();
+        EcdsaPublicKey publicKey = privateKey.getPublicKey();
+        EcdsaSignature signature = EcdsaSignature.randomGarbage();
+        Assert.assertFalse(signature.verify(data, 0, publicKey));
+    }
+}

Added: gnunet-java/src/test/java/org/gnunet/util/Ed25519Test.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/Ed25519Test.java                  
        (rev 0)
+++ gnunet-java/src/test/java/org/gnunet/util/Ed25519Test.java  2013-11-19 
11:15:52 UTC (rev 30794)
@@ -0,0 +1,142 @@
+/*
+ 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.util;
+
+import org.gnunet.util.crypto.Ed25519;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+public class Ed25519Test {
+
+    /**
+     * Simple test for commutativity.
+     */
+    @Test
+    public void test_commutative() {
+        Ed25519 p1 = 
Ed25519.B.scalarmult(BigInteger.valueOf(42)).scalarmult(BigInteger.valueOf(100));
+        Ed25519 p2 = 
Ed25519.B.scalarmult(BigInteger.valueOf(100)).scalarmult(BigInteger.valueOf(42));
+
+        byte[] data1 = p1.encode();
+        byte[] data2 = p2.encode();
+        Assert.assertArrayEquals(data1, data2);
+    }
+
+
+    /**
+     * Raw ECDH check.
+     */
+    //@Test
+    public void test_ecdh() {
+        for (int i = 0; i < 5; ++i) {
+            System.out.println("try " + i);
+            byte[] d1 = new byte[32];
+            byte[] d2 = new byte[32];
+            Random r = new Random();
+            r.nextBytes(d1);
+            r.nextBytes(d2);
+            d1[0] &= 248;
+            d1[31] &= 127;
+            d1[31] |= 64;
+            d2[0] &= 248;
+            d2[31] &= 127;
+            d2[31] |= 64;
+
+
+            Ed25519 pk1 = Ed25519.B.scalarmult(Ed25519.decodeScalar(d1));
+            Ed25519 pk2 = Ed25519.B.scalarmult(Ed25519.decodeScalar(d2));
+            byte[] pk1Data = pk1.encode();
+            byte[] pk2Data = pk2.encode();
+
+            Assert.assertEquals(pk1, Ed25519.decode(pk1Data));
+            Assert.assertEquals(pk2, Ed25519.decode(pk2Data));
+
+
+
+            byte[] data1 = 
Ed25519.decode(pk1Data).scalarmult(Ed25519.decodeScalar(d2)).encode();
+            byte[] data2 = 
Ed25519.decode(pk2Data).scalarmult(Ed25519.decodeScalar(d1)).encode();
+
+
+
+            /*
+            Ed25519 p1 = 
Ed25519.B.scalarmult(Ed25519.decodeScalar(d1)).scalarmult(Ed25519.decodeScalar(d2));
+            Ed25519 p2 = 
Ed25519.B.scalarmult(Ed25519.decodeScalar(d2)).scalarmult(Ed25519.decodeScalar(d1));
+            byte[] data1 = p1.encode();
+            byte[] data2 = p2.encode();
+            */
+
+            Assert.assertArrayEquals(data1, data2);
+        }
+    }
+
+    /**
+     * Test if decode is the inverse of encode.
+     */
+    //@Test
+    public void test_encode_inverse() {
+        Random r = new Random();
+        for (int i = 0; i < 100; i++) {
+            byte[] d1 = new byte[32];
+            r.nextBytes(d1);
+            d1[31] &= 127;
+            Ed25519 p1 = Ed25519.B.scalarmult(Ed25519.decodeScalar(d1));
+            // encode and decode the same value!
+            byte[] data1 = p1.encode();
+            Ed25519 p2 = Ed25519.decode(data1);
+            Assert.assertEquals(p1, p2);
+            Assert.assertArrayEquals(p1.encode(), p2.encode());
+        }
+    }
+
+    @Test
+    public void test_encode_inverse_simple() {
+        Ed25519 p1 = Ed25519.B;
+        // encode and decode the same value!
+        byte[] data1 = p1.encode();
+        for (int i = 0; i < 32; i++) {
+            System.out.print(data1[i] + " ");
+        }
+        System.out.println();
+        Ed25519 p2 = Ed25519.decode(data1);
+        Assert.assertArrayEquals(p1.encode(), p2.encode());
+        Assert.assertEquals(p1, p2);
+    }
+
+    /**
+     *
+     */
+    @Test
+    public void test_encode_scalar() {
+        Random r = new Random();
+        for (int i = 0; i < 10; i++) {
+            byte[] d1 = new byte[32];
+            r.nextBytes(d1);
+            d1[31] &= 127;
+            BigInteger s1 = Ed25519.decodeScalar(d1);
+            byte[] d2 = Ed25519.encodeScalar(s1);
+            BigInteger s2 = Ed25519.decodeScalar(d2);
+            Assert.assertEquals(s1, s2);
+            Assert.assertArrayEquals(d1, d2);
+        }
+    }
+}

Modified: gnunet-java/src/test/java/org/gnunet/util/EddsaTest.java
===================================================================
--- gnunet-java/src/test/java/org/gnunet/util/EddsaTest.java    2013-11-19 
10:52:12 UTC (rev 30793)
+++ gnunet-java/src/test/java/org/gnunet/util/EddsaTest.java    2013-11-19 
11:15:52 UTC (rev 30794)
@@ -30,10 +30,19 @@
 public class EddsaTest {
     @Test
     public void test_eddsa_sign_success() {
-        byte[] data = "foo".getBytes();
+        byte[] data = "GNUnet".getBytes();
         EddsaPrivateKey privateKey = EddsaPrivateKey.createRandom();
         EddsaPublicKey publicKey = privateKey.getPublicKey();
         EddsaSignature signature = privateKey.sign(publicKey, 0, data);
         Assert.assertTrue(signature.verify(data, 0, publicKey));
     }
+
+    @Test
+    public void test_eddsa_sign_failure() {
+        byte[] data = "GNUnet".getBytes();
+        EddsaPrivateKey privateKey = EddsaPrivateKey.createRandom();
+        EddsaPublicKey publicKey = privateKey.getPublicKey();
+        EddsaSignature signature = EddsaSignature.randomGarbage();
+        Assert.assertFalse(signature.verify(data, 0, publicKey));
+    }
 }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]