DSA数字签名算法及其实现

一、实验目的

在掌握了ElGamal和Schorr数字签名算法的基础上,进一步地学习和掌握DSA签名算法。深入地理解该算法是如何降低了签名信息的长度(当其中一个重要参数选为512bit的素数时,ElGamal签名的长度为1024bit,而DSA中通过160bit的素数可以将签名的长度降低为320bit),从而减少了存储空间和传输带宽。

二、实验要求

4.学习DSA数字签名算法。
5.掌握如何使用Java BigInteger类,简单实现最基础的DSA公私钥签名算法。
6.深入地理解DSA签名算法与RSA算法的区别。

三、开发环境

JDK 1.8,Java开发环境
四、实验内容

【1-1】DSA签名算法的实现

  1. 实现系统参数的设置:根据书本上的知识, DSA公私钥生成算法首先选择一个160bit 的素数,接着选择一个长度在512~1024bit的素数,使得能被整除(),最后选择,其中是整数,满足,且。从中随机地选择一个整数作为私钥,计算,用户的公钥为。具体的代码如下:
public void initKeys(){
    	q = new BigInteger(160, 100, new SecureRandom());
    	do {
    		BigInteger t = new BigInteger(512, new SecureRandom());
    		p = t.multiply(q).add(BigInteger.ONE);
    		System.out.println("~");
    	}while(!p.isProbablePrime(100));
    	BigInteger h = _randomInZq();
    	g = h.modPow(p.subtract(BigInteger.ONE).divide(q), p);
    	x = _randomInZq();
    	y = g.modPow(x, p);
    	System.out.println("p : " + p);
    	System.out.println("q : " + q);
    	System.out.println("g : " + g);
    	System.out.println("x : " + x);
    	System.out.println("y : " + y);
}

其中,需要在前面定义、、、、、和设置一个随机函数。代码分别如下:

public class DSASign {
           public BigInteger p,q,g;
           public BigInteger x,y;
           public BigInteger _randomInZq(){
        	  BigInteger r= null;
      	do {
    		    System.out.print(".");
    		    r = new BigInteger(160, new SecureRandom());
         	}while(r.compareTo(q) >=0);
       	 System.out.print(".");
    	     return r;
    }
  1. 实现签名算法:DSA签名算法是对待签名的消息进行签名,其计算如下两个分量:

因此,可根据公式,写代码如下:

	  public BigInteger[] signature(byte m[]){
        	BigInteger k = _randomInZq();
      	BigInteger sig[] = new BigInteger[2];
     	sig[0] = g.modPow(k, p).mod(q);
     	sig[1] = _hashInZq(m).add(x.multiply(sig[0])).mod(q)
     	.multiply(k.modInverse(q)).mod(q);
     	return sig;
}

其中选择的DSA签名算法中规定了Hash函数为SHA-1算法:

public BigInteger __hash(byte m[]) {
		MessageDigest md;
		try {
			md = MessageDigest.getInstance("SHA-1");
			md.update(m);
		    byte b[] = new byte[17];
		    System.arraycopy(md.digest(), 0, b, 1, 16);
		    return new BigInteger(b);
		} catch (NoSuchAlgorithmException e) {
			System.out.println("this cannot happen.");
		}
	    return null;
	}

3.实现验证签名算法:当签名接收者在接收到消息和签名信息后,进行如下步骤计算:

实现该验证算法的代码如下:

public boolean verify(byte m[], BigInteger sig[]){
      	BigInteger w = sig[1].modInverse(q);
    	    BigInteger u1 = _hashInZq(m).multiply(w).mod(q);
      	BigInteger u2 = sig[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 = " + sig[0]);
     	return v.compareTo(sig[0]) == 0;
 }
4.实现main方法,在main方法中调用算法进行测试:注意,此处需要修改为你的名字和学号。
public static void main(String args[]){
      	DSASign dsa = new DSASign();
      	dsa.initKeys();
     	String message = "My name is xxx, my student number is xxxxxx.";
     	System.out.println(message);
     	BigInteger sig[] = dsa.signature(message.getBytes());
       	System.out.println("DSASignture verifies result:" + dsa.verify(message.getBytes(),sig) );
}

【1-2】完整参考代码。

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


public class DSASign {
    public BigInteger p,q,g;
    public BigInteger x,y;
    
    public BigInteger _randomInZq(){
    	BigInteger r= null;
    	do {
    		System.out.print(".");
    		r = new BigInteger(160, new SecureRandom());
    	}while(r.compareTo(q) >=0);
    	System.out.print(".");
    	return r;
    }
    
    public BigInteger _hashInZq(byte m[]){
    	MessageDigest md;
    	try {
    		md = MessageDigest.getInstance("SHA-1");
    		md.update(m);
    		byte b[] = new byte[17];
    		System.arraycopy(md.digest(), 0, b, 1, 16);
    		return new BigInteger(b);
    	}catch (NoSuchAlgorithmException e){
    		System.out.print("This cannot happen!");
    	}
    	return null;
    }
    
    public void initKeys(){
    	q = new BigInteger(160, 100, new SecureRandom());
    	do {
    		BigInteger t = new BigInteger(512, new SecureRandom());
    		p = t.multiply(q).add(BigInteger.ONE);
    		System.out.println("~");
    	}while(!p.isProbablePrime(100));
    	BigInteger h = _randomInZq();
    	g = h.modPow(p.subtract(BigInteger.ONE).divide(q), p);
    	x = _randomInZq();
    	y = g.modPow(x, p);
    	System.out.println("p : " + p);
    	System.out.println("q : " + q);
    	System.out.println("g : " + g);
    	System.out.println("x : " + x);
    	System.out.println("y : " + y);
    }
    
    public BigInteger[] signature(byte m[]){
    	BigInteger k = _randomInZq();
    	BigInteger sig[] = new BigInteger[2];
    	sig[0] = g.modPow(k, p).mod(q);
    	sig[1] = _hashInZq(m).add(x.multiply(sig[0])).mod(q)
    	.multiply(k.modInverse(q)).mod(q);
    	return sig;
    }
    public boolean verify(byte m[], BigInteger sig[]){
    	BigInteger w = sig[1].modInverse(q);
    	BigInteger u1 = _hashInZq(m).multiply(w).mod(q);
    	BigInteger u2 = sig[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 = " + sig[0]);
    	return v.compareTo(sig[0]) == 0;
    }
    
    public static void main(String args[]){
    	DSASign dsa = new DSASign();
    	dsa.initKeys();
    	String message = "My name is xxx, my student number is xxxxxx.";
    	System.out.println(message);
    	BigInteger sig[] = dsa.signature(message.getBytes());
    	System.out.println("DSASignture verifies result:" + dsa.verify(message.getBytes(),sig) );
    }
    
}

【1-3】算法运行截图

运行要求:运行算法,DSA签名验证结果应该为true。
在这里插入图片描述

【1-4】注意事项:

DSA数字签名算法主要依赖于整数有限域离散对数难题,素数必须足够大,且至少包含一个大素数因子以抵抗Pohlig &Hellman算法的攻击。一般都应采用信息的HASH值。DSA加密算法的安全性主要依赖于和,若选取不当则签名容易伪造,应保证对于的大素数因子不可约。其安全性与RSA相比差不多。DSA数字签名算法,它是另一种公开密钥算法,它不能用作加密,只用作数字签名(这就是何RSA的区别)。特别要注意的是,要深入地挖掘算法所隐藏的含义,这对我们理解算法和代码实现极其重要。同时在代码的实现过程中一定要细心地到底是模还是模,这关乎着验证过程的正确性。

  • 5
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 好的,下面是简单的NTRU数字签名的Matlab代码: ```matlab % NTRU数字签名 % 计算矩阵的逆 function inv_mat = mat_inv(mat, q) [n, ~] = size(mat); inv_mat = zeros(n); for i = 1:n inv_mat(i, i) = 1; end for i = 1:n-1 inv_mat(i, i+1:end) = mod(-mat(i, i+1:end)*inv_mat(i+1:end, i+1:end), q); inv_mat(i+1:end, i) = mod(-inv_mat(i+1:end, i)*mat(i+1:end, i), q); end for i = n:-1:2 inv_mat(i, 1:i-1) = mod(-mat(i, 1:i-1)*inv_mat(1:i-1, 1:i-1), q); inv_mat(1:i-1, i) = mod(-inv_mat(1:i-1, i)*mat(1:i-1, i), q); end inv_mat = mod(inv_mat*mat_inv(1:n, 1:n), q); end % NTRU数字签名 function [s, e] = ntru_sign(m, f, g, p, q) % 生成随机向量r n = numel(f); r = randi([0, p-1], n, 1); % 计算e = r * f mod p + g * f^-1 · H(m) mod p h = double(dec2bin(m)); h = [zeros(1, n-numel(h)), flip(h-'0')]; f_inv = mat_inv([f, eye(n); zeros(n), f], p); e = mod(r'*f, p) + mod(g*f_inv*h', p); % 计算s = r + e * f^-1 · g^-1 mod q g_inv = mat_inv([g, eye(n); zeros(n), g], q); s = mod(r + mod(e*f_inv*g_inv, q), q); end % 测试NTRU数字签名 f = [1, 1, 0, 1]; % NTT模数 g = [1, 0, 0, 1]; % 非对称多项式 p = 7; % 模数 q = 17; % 素数模数 m = 1234; % 消息 [s, e] = ntru_sign(m, f, g, p, q) ``` 代码的注释已经说明了每个步骤。其中,`mat_inv`函数用于计算矩阵的逆,`ntru_sign`函数是NTRU数字签名的主算法。最后,测试代码对消息"1234"进行签名。 ### 回答2: NTRU(Nth degree Truncated Polynomial Ring)是一种基于多项式环的非对称加密算法。它的数字签名部分实现了一种基于格的数字签名方案。下面是一段简单的NTRU数字签名的MATLAB代码: function [sig] = ntru_sign(message, private_key) N = length(private_key); sigma = 3; % 调整该值可以改变签名的安全性与签名长度 d = private_key(1); f = private_key(2); h = private_key(3); r = randi([-sigma, sigma], N, 1); % 随机选择一个密钥密文 t = mod(d*r - f*r^2, N); % 计算签名 hash = mod(message*h, N); s = mod(t + hash, N); % 计算最终签名 sig = [t; s]; % 返回签名 end 该函数接受两个参数:message代表要签名的消息,private_key代表私钥。私钥由d、f和h三个参数组成。函数首先生成一个随机数r作为密钥密文,然后根据私钥参数计算出签名。签名中的t部分通过公式d*r - f*r^2计算得到,s部分通过将消息的哈希值与t相加得到。最后,函数返回签名。 需要注意的是,该代码只是NTRU数字签名算法的简单实现,并且没有涉及到密钥的生成、公钥的计算以及验签等部分。如果要完整地使用NTRU数字签名算法,还需要进一步的实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值