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>