DSA算法

作者 : 开心源码 本文共4257个字,预计阅读时间需要11分钟 发布时间: 2022-05-12 共193人阅读

DSA(Digital Signature Algorithm)是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。
DSA加密算法主要依赖于整数有限域离散对数难题,素数P必需足够大,且p-1至少包含一个大素数因子以抵抗Pohlig &Hellman算法的攻击。M一般都应采用信息的HASH值。DSA加密算法的安全性主要依赖于p和g,若选取不当则签名容易伪造,应保证g对于p-1的大素数因子不可约。其安全性与RSA相比差不多。

DSA 一般用于数字签名和认证。在DSA数字签名和认证中,发送者使用自己的私钥对文件或者消息进行签名,接受者收到消息后使用发送者的公钥来验证签名的真实性。DSA只是一种算法,和RSA不同之处在于它不能用作加密和解密,也不能进行密钥交换,只用于签名,它比RSA要快很多.

1. DSA签名及验证

DSA算法中应用了下述参数:

p:L bits长的素数。L是64的倍数,范围是512到1024;

q:p – 1的160bits的素因子;

g:g = h^((p-1)/q) mod p,h满足h < p – 1, h^((p-1)/q) mod p > 1;

x:x < q,x为私钥 ;

y:y = g^x mod p ,( p, q, g, y )为公钥;

H( x ):One-Way Hash函数。DSS中选用SHA( Secure Hash Algorithm )。

p, q, g可由一组客户共享,但在实际应用中,使用公共模数可能会带来肯定的威胁。

签名及验证协议:

  • 1.P产生随机数k,k < q;
  • 2.P计算 r = ( g^k mod p ) mod q
    s = ( k^(-1) (H(m) xr)) mod q
    签名结果是( m, r, s )。
  • 3.验证时计算 w = s^(-1)mod q
    u1 = ( H( m ) w ) mod q
    u2 = ( r w ) mod q
    v = (( g^u1 * y^u2 ) mod p ) mod q
    若v = r,则认为签名有效。

举例:B 发消息给A,使用DSA算法进行签名

1.生成素数p=59、素数q=29、h=11、私钥x=7,临时密钥k=10,消息摘要H(M)=26

2.生成g:

g=h^(p-1)/qmod p → g=11^2 mod 59 → g=3

3.计算公钥y

y=g^xmod p → y=3^7 mod 59 →y=2187 mod 59 →y=4

4.进行签名计算

r = (g^k mod p) mod q → r=(59049 mod 59) mod 29 →r=20

s = [k^-1 (H(M) + xr) ] mod q → s=3·(26+140)mod 29 → s=5

5.A收到消息后进行签名验证

w=(s’)^-1mod q → w=6 mod 29 =6

u1=[H(M’)w] mod q → u1=156 mod 29 = 11

u2=(r’)wmod q → u2=120 mod 29=4

v=[(g^u1 · y^u2) mod p] mod q → v= (45349632 mod 59) mod 29 =20

v=r=20

6.验证成功;

2.DSA使用过程

过程:

     构建密钥对:        发送方:  1.构建密钥对              2.公布密钥     发送数据 :        发送方:  1.使用私钥对数据签名              2.发送签名,数据               3.使用公钥,签名验证数据

3. Java实现DSA生成公私钥并加解密

3.1代码如下

package com.tencent.blue.utils;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.security.*;/** * Created by cuiran on 19/1/11. * 生成一对文件 publicKey.key 和 privateKey.key , * 公钥要客户发送 ( 文件 , 网络等方法 ) 给其它客户 , 私钥保存在本地 * 1.生成秘钥对 * 2.使用私钥进行签名 * 3.使用公钥校验签名 * 意义上的加密解密 非内容型的加密解密 */public class DSA {    public static void main(String[] args) {        //初始化秘钥对写入到文件 生成的是X.509编码格式的 生成的私钥是PKCS#8编码格式        getKeyPairs();        //明文签名        SignatureData("我是cayden,银行账户为622XXXX");        //校验签名文件        checkSignature();    }    /**     * 生成秘钥对写入到文件     * @return     */    public static boolean getKeyPairs() {        try {            //初始化秘钥管理器            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA");            keyPairGenerator.initialize(512);            KeyPair keyPair = keyPairGenerator.genKeyPair();            //获取秘钥对            PublicKey publicKey = keyPair.getPublic();            PrivateKey privateKey = keyPair.getPrivate();            //直接写入公钥            ObjectOutputStream out_pub = new ObjectOutputStream(new FileOutputStream("publicKey.key"));            out_pub.writeObject(publicKey);            out_pub.close();            System.out.println("生成的公钥内容为_____:\n "+publicKey);            //直接写入私钥            ObjectOutputStream out_pri = new ObjectOutputStream(new FileOutputStream("privateKey.key"));            out_pri.writeObject(privateKey);            out_pri.close();            System.out.println("生成的私钥内容为_____:\n "+privateKey);            System.out.println("\n生成密钥对成功...");            return true;        } catch (java.lang.Exception e) {            e.printStackTrace();            return false;        }    }    /**     * 使用私钥进行签名     * @return     */    public static boolean SignatureData(String  info){        try {            //1.读取生成的私钥对明文进行签名            ObjectInputStream in_pri = new ObjectInputStream(new java.io.FileInputStream("privateKey.key"));            PrivateKey privateKey = (PrivateKey) in_pri.readObject();            in_pri.close();            //初始化签名 对明文开始签名            Signature signature = Signature.getInstance("DSA");            signature.initSign(privateKey);            signature.update(info.getBytes());            // 对信息的数字签名            byte[] signedbytes = signature.sign();            System.out.println("签名为_____:"+signedbytes);            //把签名的密文存到文件中            ObjectOutputStream out_signature =new ObjectOutputStream(new FileOutputStream("signature.data"));            //把明文和签名一起写入 也可以分别写入            out_signature.writeObject(info);            out_signature.writeObject(signedbytes);            out_signature.close();            System.out.println("秘钥签名完成.......");        } catch (Exception e) {            e.printStackTrace();            System.out.println("私钥签名失败....");        }        return false;    }    /**     * 用公钥进行校验     * @return     */    public static boolean checkSignature(){        try {            //读取公钥            ObjectInputStream in_pub=new ObjectInputStream(new FileInputStream("publicKey.key"));            PublicKey publicKey = (PublicKey) in_pub.readObject();            //读取签名文件            ObjectInputStream in_signature=new ObjectInputStream(new FileInputStream("signature.data"));            //读取签名信息            String info = (String) in_signature.readObject();            //用公钥进行校验            byte[] signedbytes = (byte[]) in_signature.readObject();            Signature signature = Signature.getInstance("DSA");            signature.initVerify(publicKey);            signature.update(info.getBytes());            //签名信息校验            if (signature.verify(signedbytes)) {                System.out.println("签名的内容为____:" + info);                System.out.println("签名文件校验正常....");                return true;            } else{                System.out.println("签名校验失败");                return false;            }        } catch (Exception e) {            e.printStackTrace();            return false;        }    }}

3.2 运行结果如下

运行结果

下面的是我的公众号二维码图片,欢迎扫码关注!

code_cayden

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » DSA算法

发表回复