欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DSA数字签名理论分析及代码实现

程序员文章站 2024-03-19 14:10:52
...

DSA数字签名理论分析

1、准备

素数p:约512+比特(512~1024位的素数);
素数q:约160比特,要求是p-1的因子,并与 p-1 互素的因子,q 能整除 p-1;
参数g:g=h((p-1)/q) mod p;其中 h < p-1 且 h((p-1)/q) mod p >1;

2、**

私钥x:x < q ;
公钥y:y=???????? mod p ;

3、签名

k-随机数
r=(????????mod p) mod q;
s= k-1 (H(M)+xr) mod q;
(r,s)即是签名

4、验签

u1=H(M’) ×s’-1 mod q;
u2=r’×s’-1 mod q;
v=gu1×yu2 mod p mod q;
若 v = r ;验签成功

Java代码实现DSA签名与验签

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class DSASignAndVerify {

    /**
     * 第一步  准备
     */
    //系统参数 p,q,y 公开,私钥 x ,公钥 y
    public BigInteger p,q,g,x,y;
    //生成随机数 x ,要求 x < q
    public BigInteger getX(){
        BigInteger x= null;
        do {
            x = new BigInteger(160, new SecureRandom());
        }while(x.compareTo(q) >=0);
        return x;
    }
    //生成随机数 h ,要求 h < p - 1, h^((p-1)/q) mod p > 1
    public BigInteger getH(){
        BigInteger h= null;
        do {
            h = new BigInteger(160, new SecureRandom());
        }while((h.compareTo(p.subtract(BigInteger.ONE))) >=0||(h.modPow(p.subtract(BigInteger.ONE).divide(q), p)).compareTo(BigInteger.ONE) <=0);
        return h;
    }
    //对消息message进行哈希
    public BigInteger getHashM(byte message[]){
        MessageDigest messageDigest;
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(message);
            byte a[] = messageDigest.digest(message);
            return new BigInteger(a);
        }catch (NoSuchAlgorithmException e){
            e.printStackTrace();
        }
        return null;
    }
    /**
     * 第二步 初始化各参数,包括私钥 x 和公钥 y
     */
    public void initParamsAndKeys(){
        q = new BigInteger(160, 100, new SecureRandom());// q 为160bits素因子
        do {
            BigInteger t = new BigInteger(512, new SecureRandom());
            p = t.multiply(q).add(BigInteger.ONE);// p : L bits长的素数.L是64倍数,范围[512, 1024]
        }while(!p.isProbablePrime(100));
        g = getH().modPow(p.subtract(BigInteger.ONE).divide(q), p);
        x = getX();
        y = g.modPow(x, p);
    }
    /**
     * 第三步 签名和验签
     * @param message 输入消息
     * @return
     */
    //签名
    public BigInteger[] signature(byte message[]){
        BigInteger k = new BigInteger(160, new SecureRandom());
        BigInteger signature[] = new BigInteger[2];
        signature[0] = g.modPow(k, p).mod(q);
        signature[1] = getHashM(message).add(x.multiply(signature[0])).mod(q).multiply(k.modInverse(q)).mod(q);
        return signature;
    }
    //验签
    public boolean verify(byte message[], BigInteger signature[]){
        BigInteger w = signature[1].modInverse(q);
        BigInteger u1 = getHashM(message).multiply(w).mod(q);
        BigInteger u2 = signature[0].multiply(w).mod(q);
        BigInteger v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);
        System.out.println("v = " + v);
        System.out.println("r = " + signature[0]);
        if(v.compareTo(signature[0]) == 0)
            return true;
        return false;
    }

    /**
     * 主类测试
     * @param args
     */
    public static void main(String args[]){
        DSASignAndVerify dsaSignAndVerify = new DSASignAndVerify();
        dsaSignAndVerify.initParamsAndKeys();
        String message = "区块链技术与应用";
        System.out.println(message);
        BigInteger signature[] = dsaSignAndVerify.signature(message.getBytes());
        System.out.println(dsaSignAndVerify.verify(message.getBytes(),signature));
    }

}
相关标签: java 密码学