DSA數字簽名原理及JAVA實現

    DSA數字簽名是Elgamal和Schnorr數字簽名的一個變種,DSA數字簽名優於Elgamal數字簽名的地方在於它的簽名長度較短,而且某些能夠破解Elgamal方案的攻擊不適用DSA數字簽名,DSA數字簽名的原理以下:java

1. 首先生成一個素數p,p知足 2^L-1<p<2^L ;算法

注:關於L的值的範圍看到兩種不一樣的說法數組

a):L是102四、204八、3072三個值中的一個app

b):L知足512<=L<=1024 ,且L是64的倍數dom

 

2. 而後再生成q,再此處,假定L=1024,找到一個素數q,q知足 q能整除p-1,即          (p-1)mod q=0,且2^159< q <2^160;spa

 

3. 而後再生成g;.net

g=h^(p-1)/qmod p,  h知足1<h<(p-1),而且g>1xml

 

4. 最後生成用戶的私鑰x和公鑰y對象

  x是隨機數或者僞隨機數,且知足:0< x <qblog

  y 知足 y=g^x mod p

 

5. 簽名,DSA簽名也是由兩個整數r、s構成,下面是r、s的獲取方式:

  r =(g^k mod p) mod q

  s = [k^-1(H(M) + xr) ] mod q 

注:M是明文消息,H(M)是明文消息的哈希值,k是臨時密鑰

 

6.驗證,假設收到的明文爲M’,收到的簽名爲s’、r’,則驗證方式以下:

  w=(s’)^-1mod q

 u1=[H(M’)w] mod q

  u2=(r’)wmod q

 v=[(g^u1 · y^u2) mod p] mod q

  檢驗 v=r’ 簽名有效,反之則簽名無效;

 

 

 

舉例:B 發消息給A,使用DSA算法進行簽名

1.生成素數p=5九、素數q=2九、h=十一、私鑰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.驗證成功;

 

[java] view plain copy

  1. import java.math.BigInteger;  
  2. import java.security.*;  
  3. import java.security.interfaces.DSAParams;  
  4. import java.security.interfaces.DSAPrivateKey;  
  5. import java.security.spec.*;  
  6. import java.util.HashMap;  
  7. import java.util.Map;  
  8. import java.util.Random;  
  9.   
  10. public class DsaSignCode {  
  11.   
  12.     private static final String SIGNATURE_ALGORITHM="SHA1withDSA";  
  13.     private static final String ALGORITHM = "DSA";  
  14.     private static final int KEY_SIZE = 1024;  
  15.   
  16. //    該方法取一個隨機x,x小於q而且大於0,  
  17.     private static BigInteger randbint(BigInteger n){  
  18.         Random rnd = new Random();  
  19.         int maxNumBitLength = n.bitLength();  
  20.         BigInteger aRandomBigInt;  
  21.         do{  
  22.             aRandomBigInt = new BigInteger(maxNumBitLength, rnd);  
  23.         }while (aRandomBigInt.compareTo(n) > 0);  
  24.         return aRandomBigInt;  
  25.     }  
  26.   
  27.     public Map<String,BigInteger> DsaKey() throws NoSuchAlgorithmException {  
  28.   
  29.         KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);  
  30.         //初始化  
  31.         keyGen.initialize(KEY_SIZE);  
  32.         KeyPair keyPair = keyGen.genKeyPair();  
  33.         //使用KeyPair生成密鑰  
  34.         DSAPrivateKey privateKey = (DSAPrivateKey) keyPair.getPrivate();  
  35. //        DSAPublicKey publicKey = (DSAPublicKey) keyPair.getPublic();  
  36.         DSAParams dsaParams = privateKey.getParams();  
  37.         BigInteger p = dsaParams.getP();  
  38.         BigInteger q = dsaParams.getQ();  
  39.         BigInteger g = dsaParams.getG();  
  40.         BigInteger x = randbint(q);  
  41.         BigInteger y = g.modPow(x, p);  
  42.         //使用HASHMAP存儲p,q,g,x,y  
  43.         Map<String,BigInteger> map = new HashMap<String,BigInteger>(5);  
  44.         map.put("KEY_P",p);  
  45.         map.put("KEY_Q",q);  
  46.         map.put("KEY_G",g);  
  47.         map.put("KEY_X",x);  
  48.         map.put("KEY_Y",y);  
  49.         return map;  
  50.     }  
  51.   
  52.     //獲得標準的公鑰  
  53.     public PublicKey getPublicKey(BigInteger y,BigInteger p,BigInteger q,BigInteger g) throws NoSuchAlgorithmException, InvalidKeySpecException {  
  54.   
  55.         DSAPublicKeySpec dsaPublicKeySpec = new DSAPublicKeySpec(y,p,q,g);  
  56.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
  57.         //根據提供的密鑰規範(密鑰材料)生成公鑰對象  
  58.         return keyFactory.generatePublic(dsaPublicKeySpec);  
  59.     }  
  60.     //獲得標準的私鑰  
  61.     public PrivateKey getPrivateKey(BigInteger x,BigInteger p,BigInteger q,BigInteger g) throws NoSuchAlgorithmException, InvalidKeySpecException {  
  62.   
  63.         DSAPrivateKeySpec dsaPrivateKeySpec = new DSAPrivateKeySpec(x,p,q,g);  
  64.         PrivateKey privateKey =null;  
  65.         KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);  
  66.         //根據提供的密鑰規範(密鑰材料)生成私鑰對象  
  67.         privateKey= keyFactory.generatePrivate(dsaPrivateKeySpec);  
  68.         return privateKey;  
  69.     }  

 

[java] view plain copy

  1. import javax.xml.bind.DatatypeConverter;  
  2. import java.math.BigInteger;  
  3. import java.util.Map;  
  4.   
  5.   
  6. public class DsaSignTest {  
  7.     public static void main(String args[]) throws Exception {  
  8.         String str="123456";  
  9.         byte[] content=str.getBytes();  
  10.   
  11.         //獲取DsaKey()內的HASHMAP裏面的鍵值對  
  12.         DsaSignCode dsaCode= new DsaSignCode();  
  13.         Map keyMap = dsaCode.DsaKey();  
  14.         BigInteger p= (BigInteger)keyMap.get("KEY_P");  
  15.         BigInteger q= (BigInteger)keyMap.get("KEY_Q");  
  16.         BigInteger g= (BigInteger)keyMap.get("KEY_G");  
  17.         BigInteger y= (BigInteger)keyMap.get("KEY_Y");  
  18.         BigInteger x= (BigInteger)keyMap.get("KEY_X");  
  19.   
  20.         DsaSignCode dsaSignCode = new DsaSignCode();  
  21.         //簽名並存儲到數組內,再將其轉爲16進制  
  22.         byte[] dsaSignc = DsaSignCode.sign(content,dsaSignCode.getPrivateKey(x,p,q,g));  
  23.         String stringDate = DatatypeConverter.printHexBinary(dsaSignc);  
  24.         //驗證  
  25.         boolean veriftDsa= DsaSignCode.verify(content,dsaSignCode.getPublicKey(y,p,q,g),dsaSignc);  
  26.   
  27.         System.out.println("P:"+p);  
  28.         System.out.println("Q:"+q);  
  29.         System.out.println("X:"+x);  
  30.         System.out.println("Y:"+y);  
  31.         System.out.println("G:"+g);  
  32.   
  33.         System.out.println("簽名爲:"+stringDate);  
  34.         System.out.println("簽名驗證:"+veriftDsa);  
  35.     }  
  36. }  
相關文章
相關標籤/搜索