[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));
+ }
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [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,
gnunet <=