奇妙的安全旅行之DSA算法
hi,大家好,我是開發者FTD。今天我們來介紹一下非對稱加密算法中的DSA算法。
DSA 算法簡介
DSA(Digital Signature Algorithm)是Schnorr和ElGamal簽名算法的變種,被美國NIST作為DSS(DigitalSignature Standard) 數字簽名的標準。
DSA是一種更高級的驗證方式,它是一種公開密鑰算法,不能用來加密數據,一般用于數字簽名和認證。DSA 不單單只有公鑰、私鑰,還有數字簽名。私鑰加密生成數字簽名,公鑰驗證數據及簽名。在DSA數字簽名和認證中,發送者使用自己的私鑰對文件或消息進行簽名,接受者收到消息后使用發送者的公鑰來驗證簽名的真實性,包括數據的完整性以及數據發送者的身份。如果數據和簽名不匹配則認為驗證失敗!數字簽名的作用就是校驗數據在傳輸過程中不被修改。
DSA數字簽名可以理解為是單向加密的升級,不僅校驗數據完整性,還校驗發送者身份,同時還由于使用了非對稱的密鑰來保證密鑰的安全,所以相比消息摘要算法更安全。
DSA只是一種算法,和RSA不同之處在于它不能用作加密和解密,也不能進行密鑰交換,只用于簽名,它比RSA要快很多。
DSA 算法簽名過程
DSA 算法原理
DSA是基于整數有限域離散對數難題的,其安全性與RSA相比差不多。DSA的一個重要特點是兩個素數公開,這樣,當使用別人的p和q時,即使不知道私鑰,你也能確認它們是否是隨機產生的,還是作了手腳。
DSA 算法參數定義
- p:一個素模數,其值滿足:2^(L-1) < p < 2^L,其中L是64的倍數,且滿足512≤ L ≤ 1024
- q:(p-1)的素因子,其值滿足2^159 < q < 2^160,即q長度為160位。
- g:g = powm(h,(p-1)/q,p)。h為滿足1 < h < p-1 的任意整數,從而有powm(h,(p-1)/q,p) > 1
- x:私鑰。x為一個隨機或偽隨機生成的整數,其值滿足 0 < x < q。
- y:公鑰。y = powm(g,x,p)
注:
DSA 簽名過程:
注:
k^(-1) 表示整數k關于某個模數的逆元,并非指k的倒數。k在每次簽名時都要重新生成,用于不要將同樣的k用于進行其他的簽名運算!
- 逆元:滿足(a * b) mod m = 1 的a 和 b 互為關于模數 m 的逆元,表示為 a = b^(-1) 或 b = a^(-1)。如(2 * 5) mod 3 = 1,則 2 和 5 互為模數 3 的逆元。
SHA(M): M 的 hash 值,M為待簽名的明文。SHA 是一個單向散列函數。DSS中選用SHA1算法,此時SHA(M) 為160 bits長的數字串,其滿足不可逆和抗碰撞性。
最終的簽名就是證書對(r, s),它們和 M 一起發送到驗證方。
盡管 r 和 s 為 0 的概率相當小,但只要有任何一個為 0 ,必須重新生成 k,并重新計算 r 和 s 。
DSA 驗證簽名過程:
我們用(r’, s’, M’) 來表示驗證方通過某種途徑獲得的簽名結果,之所以這樣表示是因為你不能保證你這個簽名的結果一定是發送方生成的真簽名相反有可能被人篡改過,甚至掉了包。為了描述簡便,下面仍用(r, s, M) 代替(r’, s’, M’)。
為了驗證(r, s, M) 的簽名是否確由發送方所簽,驗證方需要有(g, p, q, y),驗證過程如下:
注:
DSA 算法實現
DSA密鑰生成:
public static Map<String, Object> initKey(String seed) throws Exception {KeyPairGenerator keygen = KeyPairGenerator.getInstance(KEY_ALGORITHM);// 初始化隨機產生器 SecureRandom secureRandom = new SecureRandom();secureRandom.setSeed(seed.getBytes());keygen.initialize(1024, secureRandom);KeyPair keys = keygen.genKeyPair();PublicKey publicKey = keys.getPublic();PrivateKey privateKey = keys.getPrivate();Map<String, Object> map = new HashMap<String, Object>(2);map.put(PUBLIC_KEY, publicKey);map.put(PRIVATE_KEY, privateKey);return map; }用私鑰對信息生成數字簽名:
public static String sign(byte[] data, String privateKey) throws Exception {// 解密由base64編碼的私鑰 byte[] keyBytes = Base64.decodeBase64(privateKey);// 構造PKCS8EncodedKeySpec對象 PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);// 取私鑰匙對象 PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);// 用私鑰對信息生成數字簽名 Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initSign(priKey);signature.update(data);return Base64.encodeBase64String(signature.sign()); }校驗數字簽名:
public static boolean verify(byte[] data, String publicKey, String sign)throws Exception {// 解密由base64編碼的公鑰 byte[] keyBytes = Base64.decodeBase64(publicKey);// 構造X509EncodedKeySpec對象 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);// KEY_ALGORITHM 指定的加密算法 KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);// 取公鑰匙對象 PublicKey pubKey = keyFactory.generatePublic(keySpec);Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);signature.initVerify(pubKey);signature.update(data);// 驗證簽名是否正常 return signature.verify(Base64.decodeBase64(sign)); }查看完整代碼請訪問:
https://github.com/ForTheDevelopers/JavaSecurity
總結
DSA 算法應該屬于數字簽名屆的翹楚了,非對稱密鑰大大增強了算法的安全性,目前已經被廣泛應用到數字簽名領域。
創作不易,如果大家喜歡本文,歡迎點贊,轉發,你的關注是我們繼續前進的動力_
com/ForTheDevelopers/JavaSecurity)
總結
DSA 算法應該屬于數字簽名屆的翹楚了,非對稱密鑰大大增強了算法的安全性,目前已經被廣泛應用到數字簽名領域。
創作不易,如果大家喜歡本文,歡迎點贊,轉發,你的關注是我們繼續前進的動力_
關于作者
-
GitHub:https://github.com/ForTheDevelopers
-
掘金:https://juejin.cn/user/1204720472953022/posts
-
CSDN:https://blog.csdn.net/ForTheDevelopers
-
segmentfault:https://segmentfault.com/u/for_the_developers
聯系作者
-
微信號:ForTheDeveloper
-
公眾號:ForTheDevelopers
總結
以上是生活随笔為你收集整理的奇妙的安全旅行之DSA算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java中final是修饰符么_Java
- 下一篇: 信息摘要算法之三:SHA256算法分析与