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("生成的公鑰內容為_____:\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 運行結果如下

 
運行結果


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM