java中的DSA算法:检查和建议

时间:2016-06-15 09:48:51

标签: java algorithm dsa

如果你们其中一个人熟悉DSA算法,你能检查一下我是否理解算法吗?或者至少回答以下两个问题?我的工作基于Wikipedia DSA article

我尽量让代码尽可能清晰地阅读。

public static class KeyGenerator {
    private final BigInteger TWO = new BigInteger("2");
    private final BigInteger P, Q, G;

    public KeyGenerator(int pLength) {
        this.Q = generateQ();
        this.P = generateP(Q,pLength);
        this.G = generateG(P,Q,TWO);
    }

    private BigInteger generateQ() {
        return BigInteger.probablePrime(160, new Random());
    }

    private BigInteger generateP(BigInteger Q, int l) {
        //l should be multiple of 64
        if(l%64!=0) throw new InvalidParameterException("64 should divide l");

        //P is prime and P mod Q == 1 ( i.e. P-1 = Q*Z )
        BigInteger P = BigInteger.probablePrime(512, new Random());//We generate a potential random P
        BigInteger remainder = P.mod(Q);//We calculate the remainder
        P = P.subtract(remainder).add(BigInteger.ONE);//We make P being P = Q*Z + 1 by removing the remainder
        while(!P.isProbablePrime(100)) {P = P.add(Q);}//Z++ until P = Q*Z + 1 is primal

        //P has to be l bits (l = 512 or 1024 generally)
        if(P.bitCount()>l) {return generateP(Q,l);}
        return P;
    }

    private BigInteger generateG(BigInteger P, BigInteger Q, BigInteger H) {
        //G is H^((P-1)/Q) mod P with H being any value 1<H<Q
        BigInteger G = H.modPow(P.subtract(BigInteger.ONE).divide(Q),P);
        if(G.compareTo(BigInteger.ONE)<=0) return generateG(P, Q, H.add(BigInteger.ONE));//G must be >1
        return G;
    }

    public KeyPair generateKeyPair() {
        BigInteger privateKey = new BigInteger(159, new Random());//private key should be <Q, but Q is 160 bits.
        //public key is G^X mod P where X is the private key
        BigInteger publicKey = G.modPow(privateKey,P);
        return new KeyPair(privateKey, publicKey);
    }

}

public static class SignatureMaker {

    ...

    public Signature sign(String message) {
        BigInteger K = new BigInteger(159,new Random());//Random K < Q
        BigInteger R = G.modPow(K, P).mod(Q);//R = G^K mod P mod Q
        if(R.compareTo(BigInteger.ZERO)==0) {return sign(message);}//R should be >0
        BigInteger M = new BigInteger(DigestUtils.sha1(message));//M = sha1(message) (i.e. M = H(m))
        BigInteger S = K.modInverse(Q).multiply(M.add(privateKey.multiply(R))).mod(Q);//S = K^-1*(H(m)+X*R) mod Q
        if(S.compareTo(BigInteger.ZERO)==0) {return sign(message);}//S should be >0
        return new Signature(R, S);
    }
}

public static class SignatureChecker {

    ...

    public boolean check(String message, Signature signature) {
        BigInteger R = signature.R;
        BigInteger S = signature.S;
        if(R.signum()<1 || R.compareTo(Q)>=0 || S.signum()<1 || S.compareTo(Q)>=0) return false;//0<R<Q and 0<S<Q
        BigInteger W = S.modInverse(Q);//W = S^-1 mod Q
        BigInteger M = new BigInteger(DigestUtils.sha1(message));//M = sha1(message) i.e. M = H(m)
        BigInteger U1 = M.multiply(W).mod(Q);//U1 = (H(M)*W) mod Q
        BigInteger U2 = R.multiply(W).mod(Q);//U2 = (R*W) mod Q
        BigInteger V = G.modPow(U1, P).multiply(publicKey.modPow(U2, P)).mod(P).mod(Q);//V = (G^U1 mod P)*(Y^U2 mod P) mod P mod Q
        return V.compareTo(R)==0;//Valid only if V==R
    }
}

我进行了一些测试,似乎有效,但这并不意味着我没有犯任何错误。

  • 我特别不确定S期间signV期间check的计算,因为我无法确定公式这是用维基百科写的。

  • [在评论中解决] 我也完全不明白为什么维基百科中的算法会在验证过程中要求mod P mod Q。通常,mod P mod Q应返回与mod Q ...

  • 相同的结果

如果你看到可能的改善,我也很乐意接受它。

非常感谢!

0 个答案:

没有答案