On Sun, Sep 24, 2006 at 01:03:18AM +0000, nextgens at freenetproject.org wrote: > 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
Eh? h is the number of bits of another parameter; it's supposed to be short! Hmmm, having said that, our Q length needs to be the same as our hash length, i.e. 256. Which code did we actually use for group generation? I'm reasonably sure I generated a group with 2048/256... Having to change group would be rather destructive, please could you give a detailed justification? > 2) we weren't verifying DSA signatures as we ought to > > TODO: what about following FIPS-186-3 insteed of the first version ? I don't think it was available at the time of implementation. > > 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) > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 189 bytes Desc: Digital signature URL: <https://emu.freenetproject.org/pipermail/devl/attachments/20060925/28157a77/attachment.pgp>