codecamp

密码学 DSA算法

Digital Signature Algorithm (DSA)是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。

算法步骤

算法中应用了下述参数: 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(FIPS186-4)中选用SHA-1或者SHA-2( Secure Hash Algorithm系列中的2个较新版本,其中SHA-2有4个,SHA-224,SHA-256,SHA-384,SHA-512,最原始的SHA已经不再被使用)。 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,则认为签名有效。 DSA是基于整数有限域离散对数难题的,其安全性与RSA相比差不多。DSA的一个重要特点是两个素数公开,这样,当使用别人的p和q时,即使不知道私钥,你也能确认它们是否是随机产生的,还是作了手脚。RSA算法却做不到。

JAVA代码实现

(1)编码实现DSA算法,源代码如下:

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.xml.bind.DatatypeConverter;
public class DSAUtil {
    private static String src = "I LOVE CHINA!";


    public static void main(String[] args) {
        jdkDSA();
    }


    public static void jdkDSA() {
        // 1. 初始化 秘钥
        try {
            KeyPairGenerator generator = KeyPairGenerator.getInstance("DSA");
            generator.initialize(512);


            KeyPair keyPair = generator.generateKeyPair();
            DSAPublicKey dsaPublicKey = (DSAPublicKey) keyPair.getPublic();
            DSAPrivateKey dsaPrivateKey = (DSAPrivateKey) keyPair.getPrivate();
            System.out.println("public="+dsaPublicKey);

         
            System.out.println("x="+dsaPrivateKey.getX());

       


            // 2。 执行签名
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(dsaPrivateKey.getEncoded());
            KeyFactory factory = KeyFactory.getInstance("DSA");
            PrivateKey privateKey = factory.generatePrivate(pkcs8EncodedKeySpec);


            Signature signature = Signature.getInstance("SHA1withDSA");
            signature.initSign(privateKey);
            signature.update(src.getBytes());
            byte[] sign = signature.sign();
    System.out.println("sign=\n"+DatatypeConverter.printHexBinary(sign));
            // 验证签名
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey.getEncoded());


            factory = KeyFactory.getInstance("DSA");
            PublicKey publicKey = factory.generatePublic(x509EncodedKeySpec);


            signature = Signature.getInstance("SHA1withDSA");
            signature.initVerify(publicKey);
            signature.update(src.getBytes());


            boolean verify = signature.verify(sign);


            System.out.println(verify);


        } catch (Exception e) {
            e.printStackTrace();
        }


    }


}

解析

1、KeyPairGenerator KeyPairGenerator 类用于生成公钥和私钥对。密钥对生成器是使用 getInstance 工厂方法(返回一个给定类的实例的静态方法)构造的。 特定算法的密钥对生成器可以创建能够与此算法一起使用的公钥/私钥对。它还可以将特定于算法的参数与每个生成的密钥关联。 有两种生成密钥对的方式:与算法无关的方式和特定于算法的方式。 下面我们将按照指定RSA算法去生成秘钥KeyPairGenerator.getInstance("RSA"); 2、DSAPublicKey DSA 公用密钥的接口 3、DSAPublicKey DSA 专用密钥的接口 4、PKCS8EncodedKeySpec PKCS8EncodedKeySpec类继承EncodedKeySpec类,以编码格式来表示私钥。 PKCS8EncodedKeySpec类使用PKCS#8标准作为密钥规范管理的编码格式 5、Signature Signature 类用来为应用程序提供数字签名算法功能。数字签名用于确保数字数据的验证和完整性。 在所有算法当中,数字签名可以是 NIST 标准的 DSA,它使用 DSA 和 SHA-1。可以将使用 SHA-1 消息摘要算法的 DSA 算法指定为 SHA1withDSA。

实验例子

①选取密钥

q= fca682ce 8e12caba 26efccf7 110e526d b078b05e decbcd1e b4a208f3 ae1617ae 01f35b91 a47e6df6 3413c5e1 2ed0899b cd132acd 50d99151 bdc43ee7 37592e17 ,

p= 962eddcc 369cba8e bb260ee6 b6a126d9 346e38c5
, g= 678471b2 7a9cf44e e91a49c5 147db1a9 aaf244f0 5a434d64 86931d2d 14271b9e

35030b71 fd73da17 9069b32e 2935630e 1c206235 4d0da20a 6c416e50 be794ca4 ;

x=138516119351592938244070748724284462948007803693 ,

y= 49db7b9c a9183fbb 00a501e7 6daf9d92 860858cd adf45cfb 9d872326 3dd7c6b5 4fc5f98e adba02dc f3ba65c3 5f3514d8 4c9c9425 ee761ceb a54a05ed 084e3e7c 。

对明文“I LOVE CHINA.”生成签名消息

302D021500833DF27D1E55304611F1E82AF7602747D85F01DA0214711A399689EF29756E3D46A59CBE219C9E590A67

密码学 签名方案简介
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

第六章 公钥密码学和离散对数

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }