首页 > 编程知识 正文

DSA数字签名算法,dss数字签名算法

时间:2023-05-06 04:36:26 阅读:216189 作者:4844

一、实验目的

在掌握了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签名算法的实现 实现系统参数的设置:根据书本上的知识, 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; } 实现签名算法: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的区别)。特别要注意的是,要深入地挖掘算法所隐藏的含义,这对我们理解算法和代码实现极其重要。同时在代码的实现过程中一定要细心地到底是模还是模,这关乎着验证过程的正确性。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。