Author: nextgens
Date: 2006-09-24 01:02:49 +0000 (Sun, 24 Sep 2006)
New Revision: 10505
Modified:
trunk/freenet/src/freenet/crypt/DSA.java
trunk/freenet/src/freenet/crypt/DSAGroup.java
Log:
Fix some crypto code:
1) we were generating the "h" parameter of the group with only a few
bytes
2) we weren't verifying DSA signatures as we ought to
TODO: what about following FIPS-186-3 insteed of the first version ?
Of course it needs to be carefully reviewed... and hasn't been tested ;p
Modified: trunk/freenet/src/freenet/crypt/DSA.java
===================================================================
--- trunk/freenet/src/freenet/crypt/DSA.java 2006-09-23 22:47:03 UTC (rev
10504)
+++ trunk/freenet/src/freenet/crypt/DSA.java 2006-09-24 01:02:49 UTC (rev
10505)
@@ -14,23 +14,20 @@
* Returns a DSA signature given a group, private key (x), a random nonce
* (k), and the hash of the message (m).
*/
- public static DSASignature sign(DSAGroup g,
- DSAPrivateKey x,
- BigInteger k,
- BigInteger m) {
+ public static DSASignature sign(DSAGroup g,
+ DSAPrivateKey x,
+ BigInteger k,
+ BigInteger m) {
BigInteger r=g.getG().modPow(k, g.getP()).mod(g.getQ());
-
+
BigInteger kInv=k.modInverse(g.getQ());
return sign(g, x, r, kInv, m);
- }
-
- public static DSASignature sign(DSAGroup g, DSAPrivateKey x, BigInteger m,
- Random r) {
- BigInteger k;
- do {
- k=new NativeBigInteger(256, r);
- } while ((k.compareTo(g.getQ())>-1) ||
(k.compareTo(BigInteger.ZERO)==0));
- return sign(g, x, k, m);
+ }
+
+ public static DSASignature sign(DSAGroup g, DSAPrivateKey x, BigInteger
m,
+ Random r) {
+ BigInteger k = DSA.generateK(g, r);
+ return sign(g, x, k, m);
}
/**
@@ -41,10 +38,7 @@
BigInteger[][] result=new BigInteger[count][2];
for (int i=0; i<count; i++) {
- BigInteger k;
- do {
- k=new NativeBigInteger(160, r);
- } while ((k.compareTo(g.getQ())>-1) ||
(k.compareTo(BigInteger.ZERO)==0));
+ BigInteger k = DSA.generateK(g, r);
result[i][0] = g.getG().modPow(k, g.getP()); // r
result[i][1] = k.modInverse(g.getQ()); // k^-1
@@ -60,10 +54,20 @@
public static DSASignature sign(DSAGroup g, DSAPrivateKey x,
BigInteger r, BigInteger kInv,
BigInteger m) {
- BigInteger s1=m.add(x.getX().multiply(r)).mod(g.getQ());
- BigInteger s=kInv.multiply(s1).mod(g.getQ());
- return new DSASignature(r,s);
+ BigInteger s1=m.add(x.getX().multiply(r)).mod(g.getQ());
+ BigInteger s=kInv.multiply(s1).mod(g.getQ());
+ // FIXME: the following case would involve recomputing the sig. with a
different k
+ if((r.compareTo(BigInteger.ZERO) == 0) || (s.compareTo(BigInteger.ZERO)
== 0)) throw new NullPointerException("Something is wrong there!");
+ return new DSASignature(r,s);
}
+
+ private static BigInteger generateK(DSAGroup g, Random r){
+ BigInteger k;
+ do {
+ k=new NativeBigInteger(DSAGroup.Q_BIT_LENGTH, r);
+ } while ((g.getQ().compareTo(k) < 1) ||
(k.compareTo(BigInteger.ZERO) == 0));
+ return k;
+ }
/**
* Verifies the message authenticity given a group, the public key
@@ -73,7 +77,12 @@
DSASignature sig,
BigInteger m) {
try {
- BigInteger w=sig.getS().modInverse(kp.getQ());
+ // 0<r<q has to be true
+ if((sig.getR().compareTo(BigInteger.ZERO) < 1) ||
(kp.getQ().compareTo(sig.getR()) < 1)) return false;
+ // 0<s<q has to be true as well
+ if((sig.getS().compareTo(BigInteger.ZERO) < 1) ||
(kp.getQ().compareTo(sig.getS()) < 1)) return false;
+
+ BigInteger w=sig.getS().modInverse(kp.getQ());
BigInteger u1=m.multiply(w).mod(kp.getQ());
BigInteger u2=sig.getR().multiply(w).mod(kp.getQ());
BigInteger v1=kp.getG().modPow(u1, kp.getP());
@@ -81,7 +90,6 @@
BigInteger v=v1.multiply(v2).mod(kp.getP()).mod(kp.getQ());
return v.equals(sig.getR());
-
//FIXME: is there a better way to handle this exception raised on
the 'w=' line above?
} catch (ArithmeticException e) { // catch error raised by invalid data
return false; // and report that that data is bad.
Modified: trunk/freenet/src/freenet/crypt/DSAGroup.java
===================================================================
--- trunk/freenet/src/freenet/crypt/DSAGroup.java 2006-09-23 22:47:03 UTC
(rev 10504)
+++ trunk/freenet/src/freenet/crypt/DSAGroup.java 2006-09-24 01:02:49 UTC
(rev 10505)
@@ -21,6 +21,8 @@
*/
public class DSAGroup extends CryptoKey {
private static final long serialVersionUID = -1;
+
+ public static final int Q_BIT_LENGTH = 160;
private BigInteger p, q, g;
@@ -171,7 +173,7 @@
public void run() {
while (true) {
- qs.addElement(makePrime(160, 80, r));
+ qs.addElement(makePrime(DSAGroup.Q_BIT_LENGTH, 80, r));
synchronized (this) {
notifyAll();
}
@@ -239,7 +241,7 @@
qg.notify();
}
} else
- q = makePrime(160, 80, r);
+ q = makePrime(DSAGroup.Q_BIT_LENGTH, 80, r);
BigInteger X = new BigInteger(bits, r).setBit(bits - 1);
@@ -252,7 +254,7 @@
BigInteger h;
do {
if ((cc++) % 5 == 0) System.err.print("+");
- h = new NativeBigInteger(160, r);
+ h = new NativeBigInteger(bits, r);
g = h.modPow(pmin1.divide(q), p);
} while ((h.compareTo(p.subtract(BigInteger.ONE)) != -1)
|| (h.compareTo(BigInteger.ONE) < 1)
@@ -267,8 +269,9 @@
q = grp.getQ();
g = grp.getG();
BigInteger pmin1 = p.subtract(BigInteger.ONE);
+ // TODO: that's FIPS-186-1, we should consider implementing 3 insteed!
boolean rv = !((p.bitLength() > 1024) || (p.bitLength() < 512))
- && ((p.bitLength() % 64) == 0) && (q.bitLength() == 160)
+ && ((p.bitLength() % 64) == 0) && (q.bitLength() ==
DSAGroup.Q_BIT_LENGTH)
&& (q.compareTo(p) == -1) && isPrime(p, 80) && isPrime(q, 80)
&& pmin1.mod(q).equals(BigInteger.ZERO)
&& (g.compareTo(BigInteger.ONE) == 1)