zoukankan      html  css  js  c++  java
  • DSA算法——本质上和RSA是一样的 有公钥和私钥

    DSA算法

     

    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("生成的公钥内容为_____:
     "+publicKey);
                //直接写入私钥
                ObjectOutputStream out_pri = new ObjectOutputStream(new FileOutputStream("privateKey.key"));
                out_pri.writeObject(privateKey);
                out_pri.close();
                System.out.println("生成的私钥内容为_____:
     "+privateKey);
                System.out.println("
    生成密钥对成功...");
                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 运行结果如下

     
    运行结果
  • 相关阅读:
    (二)Maven的使用--安装配置
    (一)Maven介绍
    (二)Monkey自动化脚本
    App测试--专项测试
    Java基础--(三)运算符
    Vue.js 介绍入门
    NodeJS 入门第三天(Express框架)
    NodeJS 入门第二天(EJS模板)
    《前端架构设计》读后感
    NodeJS 入门第一天
  • 原文地址:https://www.cnblogs.com/bonelee/p/12931317.html
Copyright © 2011-2022 走看看