Java的非對(duì)稱加密(RSA、數(shù)字簽名、數(shù)字證書)詳解
1. 什么是非對(duì)稱加密
(1)公鑰和私鑰成對(duì)出現(xiàn)
(2)公鑰加密、私鑰解密,私鑰加密、公鑰解密
(3)公鑰一般對(duì)外公開,私鑰保密
(4)主要用于防止通信數(shù)據(jù)被篡改,保證數(shù)據(jù)的完整性,也可對(duì)明文來實(shí)現(xiàn)保密
對(duì)稱加密:加密和解密使用同一個(gè)密鑰
非對(duì)稱加密:加密、解密使用不同的兩把密鑰,這兩把密鑰成對(duì)
一般通信開始時(shí)通過非對(duì)稱加密將對(duì)稱加密的密鑰發(fā)送給另一方,然后雙方通過對(duì)稱加密來進(jìn)行溝通
2. 常用的非對(duì)稱加密算法
常用的非對(duì)稱加密算法有:RSA、ECC 對(duì)比:
(1) RSA簽名算法適合于:Verify操作頻度高,而Sign操作頻度低的應(yīng)用場(chǎng)景。
比如,分布式系統(tǒng)中基于capability的訪問控制就是這樣的一種場(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ù)通過摘要算法得到固定長(zhǎng)度的摘要信息
(2)用私鑰加密摘要信息即可得到數(shù)字簽名,將明文數(shù)據(jù)和簽名發(fā)送到另一方
(3)另一方用公鑰解密簽名后得到摘要信息,摘要算法提取明文的摘要信息后與解密的摘要信息進(jìn)行比對(duì),如果相同則證明明文數(shù)據(jù)完整,未被篡改
4. 數(shù)字證書(digital certificate)
(1)證書認(rèn)證中心(certificate authority,簡(jiǎn)稱CA )用私鑰加密被認(rèn)證網(wǎng)站的公鑰和其他網(wǎng)站信息(如網(wǎng)址),生成數(shù)字證書,網(wǎng)站用公鑰加密明文數(shù)據(jù)后,附帶數(shù)字證書,發(fā)送給訪問方【客戶端】。
(2)本地客戶端(瀏覽器)的"證書管理器",有"受信任的根證書頒發(fā)機(jī)構(gòu)"列表??蛻舳藭?huì)根據(jù)這張列表,查看解開數(shù)字證書的公鑰??蛻舳耸褂肅A的公鑰解密數(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 加密過程中的異常信息
*/
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的非對(duì)稱加密(RSA、數(shù)字簽名、數(shù)字證書)詳解的文章就介紹到這了,更多相關(guān)Java的非對(duì)稱加密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java基礎(chǔ)鞏固小項(xiàng)目點(diǎn)菜系統(tǒng)的實(shí)現(xiàn)
這篇文章主要介紹了一個(gè)Java小項(xiàng)目點(diǎn)菜系統(tǒng)的實(shí)現(xiàn),主要是用的集合,適合正在學(xué)習(xí)Java的朋友拿來實(shí)戰(zhàn)練手,感興趣的朋友快來看看吧2022-03-03
Java之Spring認(rèn)證使用Profile配置運(yùn)行環(huán)境講解
這篇文章主要介紹了Java之Spring認(rèn)證使用Profile配置運(yùn)行環(huán)境講解,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
Java實(shí)現(xiàn)幀動(dòng)畫的實(shí)例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)幀動(dòng)畫的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05
IntelliJ?IDEA?2022.2?正式發(fā)布新功能體驗(yàn)
IntelliJ?IDEA?2022.2為遠(yuǎn)程開發(fā)功能帶來了多項(xiàng)質(zhì)量改進(jìn),使其更美觀、更穩(wěn)定,新版本還具有多項(xiàng)值得注意的升級(jí)和改進(jìn),下面跟隨小編一起看看IDEA?2022.2新版本吧2022-08-08
java開發(fā)web前端cookie session及token會(huì)話機(jī)制詳解
如果把人體比作一個(gè)web系統(tǒng)的話,cookie、session和token就好像人體的經(jīng)絡(luò)和血管一樣,而web系統(tǒng)中的數(shù)據(jù),就好像人體的血液一樣。血液依靠著血管在人體內(nèi)流動(dòng),就如數(shù)據(jù)根據(jù)cookie和session機(jī)制在web系統(tǒng)中流動(dòng)一樣2021-10-10
JPA添加Pageable實(shí)現(xiàn)翻頁時(shí)報(bào)錯(cuò)的問題
這篇文章主要介紹了解決JPA添加Pageable實(shí)現(xiàn)翻頁時(shí)報(bào)錯(cuò)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
java Executors工具類的相關(guān)方法使用創(chuàng)建
這篇文章主要為大家介紹了java Executors工具類的相關(guān)方法使用創(chuàng)建,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
Json 自定義使用函數(shù)的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)硪黄狫son 自定義使用函數(shù)的簡(jiǎn)單實(shí)例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-10-10

