Java的非對(duì)稱加密(RSA、數(shù)字簽名、數(shù)字證書(shū))詳解
1. 什么是非對(duì)稱加密
(1)公鑰和私鑰成對(duì)出現(xiàn)
(2)公鑰加密、私鑰解密,私鑰加密、公鑰解密
(3)公鑰一般對(duì)外公開(kāi),私鑰保密
(4)主要用于防止通信數(shù)據(jù)被篡改,保證數(shù)據(jù)的完整性,也可對(duì)明文來(lái)實(shí)現(xiàn)保密
對(duì)稱加密:加密和解密使用同一個(gè)密鑰
非對(duì)稱加密:加密、解密使用不同的兩把密鑰,這兩把密鑰成對(duì)
一般通信開(kāi)始時(shí)通過(guò)非對(duì)稱加密將對(duì)稱加密的密鑰發(fā)送給另一方,然后雙方通過(guò)對(duì)稱加密來(lái)進(jìn)行溝通
2. 常用的非對(duì)稱加密算法
常用的非對(duì)稱加密算法有:RSA、ECC 對(duì)比:
(1) RSA簽名算法適合于:Verify操作頻度高,而Sign操作頻度低的應(yīng)用場(chǎng)景。
比如,分布式系統(tǒng)中基于capability的訪問(wèn)控制就是這樣的一種場(chǎng)景。
(2) ECC簽名算法適合于:Sign和Verify操作頻度相當(dāng)?shù)膽?yīng)用場(chǎng)景。
比如,點(diǎn)對(duì)點(diǎn)的安全信道建立?!疽苿?dòng)互聯(lián)網(wǎng)用的比較多】
3. 數(shù)字簽名(digital signature)
數(shù)字簽名: 數(shù)字簽名由數(shù)字摘要和非對(duì)稱加密技術(shù)組成
(1)明文數(shù)據(jù)通過(guò)摘要算法得到固定長(zhǎng)度的摘要信息
(2)用私鑰加密摘要信息即可得到數(shù)字簽名,將明文數(shù)據(jù)和簽名發(fā)送到另一方
(3)另一方用公鑰解密簽名后得到摘要信息,摘要算法提取明文的摘要信息后與解密的摘要信息進(jìn)行比對(duì),如果相同則證明明文數(shù)據(jù)完整,未被篡改
4. 數(shù)字證書(shū)(digital certificate)
(1)證書(shū)認(rèn)證中心(certificate authority,簡(jiǎn)稱CA )用私鑰加密被認(rèn)證網(wǎng)站的公鑰和其他網(wǎng)站信息(如網(wǎng)址),生成數(shù)字證書(shū),網(wǎng)站用公鑰加密明文數(shù)據(jù)后,附帶數(shù)字證書(shū),發(fā)送給訪問(wèn)方【客戶端】。
(2)本地客戶端(瀏覽器)的"證書(shū)管理器",有"受信任的根證書(shū)頒發(fā)機(jī)構(gòu)"列表??蛻舳藭?huì)根據(jù)這張列表,查看解開(kāi)數(shù)字證書(shū)的公鑰??蛻舳耸褂肅A的公鑰解密數(shù)字證書(shū)后獲取到網(wǎng)站的公鑰,再用公鑰解密數(shù)據(jù),獲取明文
5. java實(shí)現(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 { //用于封裝隨機(jī)產(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("隨機(jī)生成的公鑰為:" + keyMap.get(0)); System.out.println("隨機(jī)生成的私鑰為:" + 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); } /** * 隨機(jī)生成密鑰對(duì) * * @throws NoSuchAlgorithmException */ public static void genKeyPair() throws NoSuchAlgorithmException { // KeyPairGenerator類用于生成公鑰和私鑰對(duì),基于RSA算法生成對(duì)象 KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA"); // 初始化密鑰對(duì)生成器,密鑰大小為96-1024位 keyPairGen.initialize(1024, new SecureRandom()); // 生成一個(gè)密鑰對(duì),保存在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 加密過(guò)程中的異常信息 */ 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 解密過(guò)程中的異常信息 */ 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的非對(duì)稱加密(RSA、數(shù)字簽名、數(shù)字證書(shū))詳解的文章就介紹到這了,更多相關(guān)Java的非對(duì)稱加密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于JavaMail實(shí)現(xiàn)簡(jiǎn)單郵件發(fā)送
這篇文章主要為大家詳細(xì)介紹了基于JavaMail實(shí)現(xiàn)簡(jiǎn)單郵件發(fā)送,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08Java處理科學(xué)計(jì)數(shù)法數(shù)字方式
這篇文章主要介紹了Java處理科學(xué)計(jì)數(shù)法數(shù)字方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07Spring自帶定時(shí)任務(wù)@Scheduled注解實(shí)例講解
這篇文章主要介紹了Spring自帶定時(shí)任務(wù)@Scheduled注解的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-06-06MyBatis-Plus集成Druid環(huán)境搭建的詳細(xì)教程
這篇文章主要介紹了MyBatis-Plus集成Druid環(huán)境搭建的詳細(xì)教程,需要的朋友可以參考下2020-08-08java實(shí)現(xiàn)String類型和Date類型相互轉(zhuǎn)換
很多人表示,java將string類型轉(zhuǎn)為date類型不知道應(yīng)該怎樣做,本文就來(lái)介紹一下java實(shí)現(xiàn)String類型和Date類型相互轉(zhuǎn)換,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10spring boot 2整合swagger-ui過(guò)程解析
這篇文章主要介紹了spring boot 2整合swagger-ui過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12SpringBoot整合SpringSecurity實(shí)現(xiàn)JWT認(rèn)證的項(xiàng)目實(shí)踐
本文會(huì)通過(guò)創(chuàng)建SpringBoot項(xiàng)目整合SpringSecurity,實(shí)現(xiàn)完整的JWT認(rèn)證機(jī)制,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Java?Zookeeper分布式分片算法超詳細(xì)講解流程
ZooKeeper是一個(gè)分布式的,開(kāi)放源碼的分布式應(yīng)用程序協(xié)調(diào)服務(wù),是Google的Chubby一個(gè)開(kāi)源的實(shí)現(xiàn),是Hadoop和Hbase的重要組件。它是一個(gè)為分布式應(yīng)用提供一致性的軟件,提供的功能包括:配置維護(hù)、域名服務(wù)、分布式同步、組服務(wù)等2023-03-03