、數字簽名算法概述
簽名認證是對非對稱加密技術與數字摘要技術的綜合運用,指的是將通信內容的摘要信息使用發送者的私鑰進行加密,然后將密文與原文一起傳輸給信息的接收者,接收者通過發送者的公鑰信息來解密被加密的摘要作息,然后使用與發送者相同的摘要算法,對接收到的內容采用相同的方式方式產生摘要串,與解密的摘要串進行對比,如果相同,則說明接收到的內容是完整的,在傳輸過程中沒有受到第三方的篡改,否則說明通信內容已被第三方修改。
我們知道,每個人都有其特有的私鑰,且都是對外界保密的,而通過私鑰加密的信息,只能通過其對應的公鑰來進行解密。因此,私鑰可以代表私鑰持有者的身份,可以通過私鑰對應的公鑰來對私鑰擁有者的身份進行校驗。通過數字簽名,能夠確認消息是消息發送方簽名並發送過來的,因為其他人根本假冒不了消息發送方的簽名,他們沒有消息發送者的私鑰。而不同的內容,摘要信息千差萬別,通過數字摘要算法,可以確保傳輸內容的完整性,如果傳輸內容在中途被篡改了,對應的數字簽名的值也將發生改變。
數字簽名:帶有密鑰(公鑰,私鑰)的消息摘要算法。私鑰用於簽名,公鑰用於驗證。
數字簽名的作用:
驗證數據的完整性,認證數據來源,抗否認。
數字簽名實現的具體原理:
1、 將報文按雙方約定的HASH算法計算得到一個固定位數的報文摘要。在數學上保證,只要改動報文中任何一位,重新計算出的報文摘要值就會與原先的值不相符。這樣就保證了報文的不可更改性。(詳見參考資料的"公鑰密碼技術原理"章節)
2、 將該報文摘要值用發送者的私人密鑰加密,然后連同原報文和數字證書(包含公鑰)一起發送給接收者而產生的報文即稱數字簽名。
3、接收方收到數字簽名后,用同樣的HASH算法對報文計算摘要值,然后與用發送者的公開密鑰進行解密解開的報文摘要值相比較,如相等則說明報文確實來自所稱的發送者。
4、同時通過證書頒發機構CA確認證書的有效性即可確認發送的真實身份。
數字簽名的產生過程如圖如示:

數字簽名的校驗過程:
常用的數字簽名有:RSA、DSA、ECDSA
常用的數字簽名有:RSA、DSA、ECDSA
二、數字簽名算法—RSA
RSA是目前最有影響力的公鑰加密算法,它能夠抵抗到目前為止已知的絕大多數密碼攻擊,已被ISO推薦為公鑰數據加密標准。
特性:安全性抗和否認性
主要包括兩類:MD、SHA
具體算法如下圖:

例子:
package rmd_intl_app.Test; 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.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import org.apache.commons.codec.binary.Hex; public class ImoocRSA { private static String src = "imooc security rsa"; public static void main(String[] args) { jdkRSA(); } public static void jdkRSA() { try { //1.初始化密鑰 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(512); KeyPair keyPair = keyPairGenerator.generateKeyPair(); RSAPublicKey rsaPublicKey = (RSAPublicKey)keyPair.getPublic(); RSAPrivateKey rsaPrivateKey = (RSAPrivateKey)keyPair.getPrivate(); //2.執行簽名 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded()); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Signature signature = Signature.getInstance("MD5withRSA"); signature.initSign(privateKey); signature.update(src.getBytes()); byte[] result = signature.sign(); System.out.println("jdk rsa sign : " + Hex.encodeHexString(result)); //3.驗證簽名 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(rsaPublicKey.getEncoded()); keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); signature = Signature.getInstance("MD5withRSA"); signature.initVerify(publicKey); signature.update(src.getBytes()); boolean bool = signature.verify(result); System.out.println("jdk rsa verify : " + bool); } catch (Exception e) { e.printStackTrace(); } } }
三、數字簽名算法—DSA
DSA是Schnorr和ElGamal簽名算法的變種,被美國NIST作為DSfS(DigitalSignature Standard)。
DSA是基於整數有限域離散對數難題的,其安全性與RSA相比差不多。DSA的一個重要特點是兩個素數公開,這樣,當使用別人的p和q時,即使不知道私鑰,你也能確認它們是否是隨機產生的,還是作了手腳。RSA卻做不到。
DSA僅包含數字簽名
具體算法如下圖:
例子:
package com.imooc.security.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 org.apache.commons.codec.binary.Hex; public class ImoocDSA { private static String src = "imooc security dsa"; public static void main(String[] args) { jdkDSA(); } public static void jdkDSA() { try { //1.初始化密鑰 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DSA"); keyPairGenerator.initialize(512); KeyPair keyPair = keyPairGenerator.generateKeyPair(); DSAPublicKey dsaPublicKey = (DSAPublicKey) keyPair.getPublic(); DSAPrivateKey dsaPrivateKey = (DSAPrivateKey)keyPair.getPrivate(); //2.執行簽名 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(dsaPrivateKey.getEncoded()); KeyFactory keyFactory = KeyFactory.getInstance("DSA"); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Signature signature = Signature.getInstance("SHA1withDSA"); signature.initSign(privateKey); signature.update(src.getBytes()); byte[] result = signature.sign(); System.out.println("jdk dsa sign : " + Hex.encodeHexString(result)); //3.驗證簽名 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(dsaPublicKey.getEncoded()); keyFactory = KeyFactory.getInstance("DSA"); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); signature = Signature.getInstance("SHA1withDSA"); signature.initVerify(publicKey); signature.update(src.getBytes()); boolean bool = signature.verify(result); System.out.println("jdk dsa verify : " + bool); } catch (Exception e) { e.printStackTrace(); } } }
四、數字簽名算法—ECDSA
ECDSA: 橢圓曲線數字簽名算法(Elliptic Curve Digital Signatrue Algorithm)
特點:速度快,強度高,簽名短
具體算法如下圖:

例子:
package com.imooc.security.ecdsa; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import org.apache.commons.codec.binary.Hex; public class ImoocECDSA { private static String src = "imooc security ecdsa"; public static void main(String[] args) { jdkECDSA(); } public static void jdkECDSA() { try { //1.初始化密鑰 KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); keyPairGenerator.initialize(256); KeyPair keyPair = keyPairGenerator.generateKeyPair(); ECPublicKey ecPublicKey = (ECPublicKey)keyPair.getPublic(); ECPrivateKey ecPrivateKey = (ECPrivateKey)keyPair.getPrivate(); //2.執行簽名 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ecPrivateKey.getEncoded()); KeyFactory keyFactory = KeyFactory.getInstance("EC"); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Signature signature = Signature.getInstance("SHA1withECDSA"); signature.initSign(privateKey); signature.update(src.getBytes()); byte[] result = signature.sign(); System.out.println("jdk ecdsa sign : " + Hex.encodeHexString(result)); //3.驗證簽名 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(ecPublicKey.getEncoded()); keyFactory = KeyFactory.getInstance("EC"); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); signature = Signature.getInstance("SHA1withECDSA"); signature.initVerify(publicKey); signature.update(src.getBytes()); boolean bool = signature.verify(result); System.out.println("jdk ecdsa verify : " + bool); } catch (Exception e) { e.printStackTrace(); } } }
原文鏈接:https://blog.csdn.net/lovelichao12/article/details/75007189
