Java的非對稱加密(RSA、數(shù)字簽名、數(shù)字證書)詳解
1. 什么是非對稱加密
(1)公鑰和私鑰成對出現(xiàn)
(2)公鑰加密、私鑰解密,私鑰加密、公鑰解密
(3)公鑰一般對外公開,私鑰保密
(4)主要用于防止通信數(shù)據(jù)被篡改,保證數(shù)據(jù)的完整性,也可對明文來實現(xiàn)保密
對稱加密:加密和解密使用同一個密鑰
非對稱加密:加密、解密使用不同的兩把密鑰,這兩把密鑰成對
一般通信開始時通過非對稱加密將對稱加密的密鑰發(fā)送給另一方,然后雙方通過對稱加密來進行溝通
2. 常用的非對稱加密算法
常用的非對稱加密算法有:RSA、ECC 對比:
(1) RSA簽名算法適合于:Verify操作頻度高,而Sign操作頻度低的應(yīng)用場景。
比如,分布式系統(tǒng)中基于capability的訪問控制就是這樣的一種場景。
(2) ECC簽名算法適合于:Sign和Verify操作頻度相當?shù)膽?yīng)用場景。
比如,點對點的安全信道建立?!疽苿踊ヂ?lián)網(wǎng)用的比較多】
3. 數(shù)字簽名(digital signature)
數(shù)字簽名: 數(shù)字簽名由數(shù)字摘要和非對稱加密技術(shù)組成
(1)明文數(shù)據(jù)通過摘要算法得到固定長度的摘要信息
(2)用私鑰加密摘要信息即可得到數(shù)字簽名,將明文數(shù)據(jù)和簽名發(fā)送到另一方
(3)另一方用公鑰解密簽名后得到摘要信息,摘要算法提取明文的摘要信息后與解密的摘要信息進行比對,如果相同則證明明文數(shù)據(jù)完整,未被篡改
4. 數(shù)字證書(digital certificate)
(1)證書認證中心(certificate authority,簡稱CA )用私鑰加密被認證網(wǎng)站的公鑰和其他網(wǎng)站信息(如網(wǎng)址),生成數(shù)字證書,網(wǎng)站用公鑰加密明文數(shù)據(jù)后,附帶數(shù)字證書,發(fā)送給訪問方【客戶端】。
(2)本地客戶端(瀏覽器)的"證書管理器",有"受信任的根證書頒發(fā)機構(gòu)"列表。客戶端會根據(jù)這張列表,查看解開數(shù)字證書的公鑰。客戶端使用CA的公鑰解密數(shù)字證書后獲取到網(wǎng)站的公鑰,再用公鑰解密數(shù)據(jù),獲取明文
5. java實現(xiàn)RSA加解密
import org.apache.tomcat.util.codec.binary.Base64; import javax.crypto.Cipher; import java.nio.charset.StandardCharsets; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; public class RSAEncrypt { //用于封裝隨機產(chǎn)生的公鑰與私鑰 private static Map<Integer, String> keyMap = new HashMap<Integer, String>(); public static void main(String[] args) throws Exception { //生成公鑰和私鑰 genKeyPair(); //加密字符串 String message = "123456"; System.out.println("隨機生成的公鑰為:" + keyMap.get(0)); System.out.println("隨機生成的私鑰為:" + keyMap.get(1)); String messageEn = encrypt(message, keyMap.get(0)); System.out.println(message + "\t加密后的字符串為:" + messageEn); String messageDe = decrypt(messageEn, keyMap.get(1)); System.out.println("還原后的字符串為:" + messageDe); } /** * 隨機生成密鑰對 * * @throws NoSuchAlgorithmException */ public static void genKeyPair() throws NoSuchAlgorithmException { // KeyPairGenerator類用于生成公鑰和私鑰對,基于RSA算法生成對象 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); // 初始化密鑰對生成器,密鑰大小為96-1024位 keyPairGen.initialize(1024, new SecureRandom()); // 生成一個密鑰對,保存在keyPair中 KeyPair keyPair = keyPairGen.generateKeyPair(); // 得到私鑰 RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到公鑰 RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); //得到公鑰字符串 String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()), StandardCharsets.UTF_8); // 得到私鑰字符串 String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())), StandardCharsets.UTF_8); // 將公鑰和私鑰保存到Map keyMap.put(0, publicKeyString); //0表示公鑰 keyMap.put(1, privateKeyString); //1表示私鑰 } /** * RSA公鑰加密 * * @param str 加密字符串 * @param publicKey 公鑰 * @return 密文 * @throws Exception 加密過程中的異常信息 */ public static String encrypt(String str, String publicKey) throws Exception { //base64編碼的公鑰 byte[] decoded = Base64.decodeBase64(publicKey); RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded)); //RSA加密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, pubKey); return Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8))); } /** * RSA私鑰解密 * * @param str 加密字符串 * @param privateKey 私鑰 * @return 銘文 * @throws Exception 解密過程中的異常信息 */ public static String decrypt(String str, String privateKey) throws Exception { //64位解碼加密后的字符串 byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8)); //base64編碼的私鑰 byte[] decoded = Base64.decodeBase64(privateKey); RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded)); //RSA解密 Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, priKey); return new String(cipher.doFinal(inputByte)); } }
到此這篇關(guān)于Java的非對稱加密(RSA、數(shù)字簽名、數(shù)字證書)詳解的文章就介紹到這了,更多相關(guān)Java的非對稱加密內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java處理科學(xué)計數(shù)法數(shù)字方式
這篇文章主要介紹了Java處理科學(xué)計數(shù)法數(shù)字方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07Spring自帶定時任務(wù)@Scheduled注解實例講解
這篇文章主要介紹了Spring自帶定時任務(wù)@Scheduled注解的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧2024-06-06MyBatis-Plus集成Druid環(huán)境搭建的詳細教程
這篇文章主要介紹了MyBatis-Plus集成Druid環(huán)境搭建的詳細教程,需要的朋友可以參考下2020-08-08java實現(xiàn)String類型和Date類型相互轉(zhuǎn)換
很多人表示,java將string類型轉(zhuǎn)為date類型不知道應(yīng)該怎樣做,本文就來介紹一下java實現(xiàn)String類型和Date類型相互轉(zhuǎn)換,具有一定的參考價值,感興趣的可以了解一下2023-10-10SpringBoot整合SpringSecurity實現(xiàn)JWT認證的項目實踐
本文會通過創(chuàng)建SpringBoot項目整合SpringSecurity,實現(xiàn)完整的JWT認證機制,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07