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

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));
    }

}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值