最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解RSA加密算法的原理與Java實(shí)現(xiàn)

 更新時(shí)間:2022年10月21日 08:43:31   作者:鴨血粉絲Tang  
這篇文章主要和大家分享非對(duì)稱加密中的一種算法,那就是 RSA 加密算法。本文介紹了RSA算法的原理與Java實(shí)現(xiàn),感興趣的小伙伴可以嘗試一下

前幾天阿粉剛剛說(shuō)了這個(gè) MD5 加密的前世今生,因?yàn)?MD5 也確實(shí)用的人不是很多了,阿粉就不再繼續(xù)的一一贅述了,今天阿粉想給大家分享的,是非對(duì)稱加密中的一種,那就是 RSA 加密算法。

對(duì)稱加密和非對(duì)稱加密

在說(shuō) RSA 之前,我們得先來(lái)說(shuō)說(shuō)這個(gè)什么事對(duì)稱加密,什么又是非對(duì)稱加密?

對(duì)稱加密指的就是加密和解密使用同一個(gè)秘鑰,所以叫對(duì)稱加密。對(duì)稱加密只有一個(gè)秘鑰,作為私鑰。

非對(duì)稱加密指的是:加密和解密使用不同的秘鑰,一把作為公開(kāi)的公鑰,另一把作為私鑰。公鑰加密的信息,只有私鑰才能解密。

那么對(duì)稱加密和非對(duì)稱加密之間又有什么區(qū)別呢?

  • 對(duì)稱加密中加密和解密使用的秘鑰是同一個(gè);非對(duì)稱加密中采用兩個(gè)密鑰,一般使用公鑰進(jìn)行加密,私鑰進(jìn)行解密。
  • 對(duì)稱加密解密的速度比較快,非對(duì)稱加密和解密花費(fèi)的時(shí)間長(zhǎng)、速度相對(duì)較慢。
  • 對(duì)稱加密的安全性相對(duì)較低,非對(duì)稱加密的安全性較高。

今天我們來(lái)講的就是非對(duì)稱加密中的 RSA 加密。

RSA加密是什么

RSA加密是一種非對(duì)稱加密??梢栽诓恢苯觽鬟f密鑰的情況下,完成解密。這能夠確保信息的安全性,避免了直接傳遞密鑰所造成的被破解的風(fēng)險(xiǎn)。是由一對(duì)密鑰來(lái)進(jìn)行加解密的過(guò)程,分別稱為公鑰和私鑰。

通常情況下個(gè)人保存私鑰,公鑰是公開(kāi)的(可能同時(shí)多人持有)。

雖然私鑰是根據(jù)公鑰決定的, 但是,我們是沒(méi)有辦法根據(jù)公鑰來(lái)推算出私鑰來(lái)的。

為提高保密強(qiáng)度,RSA密鑰至少為500位長(zhǎng)。這就使加密的計(jì)算量很大。為減少計(jì)算量,在傳送信息時(shí),常采用傳統(tǒng)加密方法與公開(kāi)密鑰加密方法相結(jié)合的方式,即信息采用改進(jìn)的DES或IDEA對(duì)話密鑰加密,然后使用RSA密鑰加密對(duì)話密鑰和信息摘要。對(duì)方收到信息后,用不同的密鑰解密并可核對(duì)信息摘要

RSA的加密過(guò)程

RSA的加密過(guò)程其實(shí)并不復(fù)雜,

(1)A生成一對(duì)密鑰(公鑰和私鑰),私鑰不公開(kāi),A自己保留。公鑰為公開(kāi)的,任何人可以獲取。

(2)A傳遞自己的公鑰給B,B用A的公鑰對(duì)消息進(jìn)行加密。

(3)A接收到B加密的消息,利用A自己的私鑰對(duì)消息進(jìn)行解密。

在這個(gè)過(guò)程中,只有2次傳遞過(guò)程,第一次是A傳遞公鑰給B,第二次是B傳遞加密消息給A,即使都被其他人截獲,也沒(méi)有危險(xiǎn)性,因?yàn)橹挥蠥的私鑰才能對(duì)消息進(jìn)行解密,防止了消息內(nèi)容的泄露。

但是大家有沒(méi)有想過(guò),如果我們的消息被截獲了,雖然沒(méi)有被解密出來(lái),但是如果說(shuō)我們的公鑰被攔截,然后將假指令進(jìn)行加密,然后傳遞給A,這不就涼涼了?那數(shù)據(jù)是不是就不能稱之為安全了?

不,RSA還有簽名的過(guò)程。

簽名過(guò)程如下:

(1)A生成一對(duì)密鑰(公鑰和私鑰),私鑰不公開(kāi),A自己保留。公鑰為公開(kāi)的,任何人可以獲取。

(2)A用自己的私鑰對(duì)消息加簽,形成簽名,并將加簽的消息和消息本身一起傳遞給B。

(3)B收到消息后,在獲取A的公鑰進(jìn)行驗(yàn)簽,如果驗(yàn)簽出來(lái)的內(nèi)容與消息本身一致,證明消息是A回復(fù)的。

但是問(wèn)題又來(lái)了,雖然截獲的消息不能被篡改,但是消息的內(nèi)容可以利用公鑰驗(yàn)簽來(lái)獲得,并不能防止泄露。

那么應(yīng)該怎么用呢?

其實(shí)這就顯的并不是很好理解了 我們是不是可以這么設(shè)計(jì):

A和B都有一套自己的公鑰和私鑰,當(dāng)A要給B發(fā)送消息時(shí),先用B的公鑰對(duì)消息加密,再對(duì)加密的消息使用A的私鑰加簽名,達(dá)到既不泄露也不被篡改,更能保證消息的安全性。

那么 Java 代碼怎么實(shí)現(xiàn) RSA 的呢?代碼如下:

import?java.io.ByteArrayOutputStream;
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.spec.PKCS8EncodedKeySpec;
import?java.security.spec.X509EncodedKeySpec;
import?javax.crypto.Cipher;
import?org.apache.commons.codec.binary.Base64;

public?class?TestRSA?{

????/**
?????*?RSA最大加密明文大小
?????*/
????private?static?final?int?MAX_ENCRYPT_BLOCK?=?117;

????/**
?????*?RSA最大解密密文大小
?????*/
????private?static?final?int?MAX_DECRYPT_BLOCK?=?128;

????/**
?????*?獲取密鑰對(duì)
?????*
?????*?@return?密鑰對(duì)
?????*/
????public?static?KeyPair?getKeyPair()?throws?Exception?{
????????KeyPairGenerator?generator?=?KeyPairGenerator.getInstance("RSA");
????????generator.initialize(1024);
????????return?generator.generateKeyPair();
????}

????/**
?????*?獲取私鑰
?????*
?????*?@param?privateKey?私鑰字符串
?????*?@return
?????*/
????public?static?PrivateKey?getPrivateKey(String?privateKey)?throws?Exception?{
????????KeyFactory?keyFactory?=?KeyFactory.getInstance("RSA");
????????byte[]?decodedKey?=?Base64.decodeBase64(privateKey.getBytes());
????????PKCS8EncodedKeySpec?keySpec?=?new?PKCS8EncodedKeySpec(decodedKey);
????????return?keyFactory.generatePrivate(keySpec);
????}

????/**
?????*?獲取公鑰
?????*
?????*?@param?publicKey?公鑰字符串
?????*?@return
?????*/
????public?static?PublicKey?getPublicKey(String?publicKey)?throws?Exception?{
????????KeyFactory?keyFactory?=?KeyFactory.getInstance("RSA");
????????byte[]?decodedKey?=?Base64.decodeBase64(publicKey.getBytes());
????????X509EncodedKeySpec?keySpec?=?new?X509EncodedKeySpec(decodedKey);
????????return?keyFactory.generatePublic(keySpec);
????}

????/**
?????*?RSA加密
?????*
?????*?@param?data?待加密數(shù)據(jù)
?????*?@param?publicKey?公鑰
?????*?@return
?????*/
????public?static?String?encrypt(String?data,?PublicKey?publicKey)?throws?Exception?{
????????Cipher?cipher?=?Cipher.getInstance("RSA");
????????cipher.init(Cipher.ENCRYPT_MODE,?publicKey);
????????int?inputLen?=?data.getBytes().length;
????????ByteArrayOutputStream?out?=?new?ByteArrayOutputStream();
????????int?offset?=?0;
????????byte[]?cache;
????????int?i?=?0;
????????//?對(duì)數(shù)據(jù)分段加密
????????while?(inputLen?-?offset?>?0)?{
????????????if?(inputLen?-?offset?>?MAX_ENCRYPT_BLOCK)?{
????????????????cache?=?cipher.doFinal(data.getBytes(),?offset,?MAX_ENCRYPT_BLOCK);
????????????}?else?{
????????????????cache?=?cipher.doFinal(data.getBytes(),?offset,?inputLen?-?offset);
????????????}
????????????out.write(cache,?0,?cache.length);
????????????i++;
????????????offset?=?i?*?MAX_ENCRYPT_BLOCK;
????????}
????????byte[]?encryptedData?=?out.toByteArray();
????????out.close();
????????//?獲取加密內(nèi)容使用base64進(jìn)行編碼,并以UTF-8為標(biāo)準(zhǔn)轉(zhuǎn)化成字符串
????????//?加密后的字符串
????????return?new?String(Base64.encodeBase64String(encryptedData));
????}

????/**
?????*?RSA解密
?????*
?????*?@param?data?待解密數(shù)據(jù)
?????*?@param?privateKey?私鑰
?????*?@return
?????*/
????public?static?String?decrypt(String?data,?PrivateKey?privateKey)?throws?Exception?{
????????Cipher?cipher?=?Cipher.getInstance("RSA");
????????cipher.init(Cipher.DECRYPT_MODE,?privateKey);
????????byte[]?dataBytes?=?Base64.decodeBase64(data);
????????int?inputLen?=?dataBytes.length;
????????ByteArrayOutputStream?out?=?new?ByteArrayOutputStream();
????????int?offset?=?0;
????????byte[]?cache;
????????int?i?=?0;
????????//?對(duì)數(shù)據(jù)分段解密
????????while?(inputLen?-?offset?>?0)?{
????????????if?(inputLen?-?offset?>?MAX_DECRYPT_BLOCK)?{
????????????????cache?=?cipher.doFinal(dataBytes,?offset,?MAX_DECRYPT_BLOCK);
????????????}?else?{
????????????????cache?=?cipher.doFinal(dataBytes,?offset,?inputLen?-?offset);
????????????}
????????????out.write(cache,?0,?cache.length);
????????????i++;
????????????offset?=?i?*?MAX_DECRYPT_BLOCK;
????????}
????????byte[]?decryptedData?=?out.toByteArray();
????????out.close();
????????//?解密后的內(nèi)容
????????return?new?String(decryptedData,?"UTF-8");
????}

????/**
?????*?簽名
?????*
?????*?@param?data?待簽名數(shù)據(jù)
?????*?@param?privateKey?私鑰
?????*?@return?簽名
?????*/
????public?static?String?sign(String?data,?PrivateKey?privateKey)?throws?Exception?{
????????byte[]?keyBytes?=?privateKey.getEncoded();
????????PKCS8EncodedKeySpec?keySpec?=?new?PKCS8EncodedKeySpec(keyBytes);
????????KeyFactory?keyFactory?=?KeyFactory.getInstance("RSA");
????????PrivateKey?key?=?keyFactory.generatePrivate(keySpec);
????????Signature?signature?=?Signature.getInstance("MD5withRSA");
????????signature.initSign(key);
????????signature.update(data.getBytes());
????????return?new?String(Base64.encodeBase64(signature.sign()));
????}

????/**
?????*?驗(yàn)簽
?????*
?????*?@param?srcData?原始字符串
?????*?@param?publicKey?公鑰
?????*?@param?sign?簽名
?????*?@return?是否驗(yàn)簽通過(guò)
?????*/
????public?static?boolean?verify(String?srcData,?PublicKey?publicKey,?String?sign)?throws?Exception?{
????????byte[]?keyBytes?=?publicKey.getEncoded();
????????X509EncodedKeySpec?keySpec?=?new?X509EncodedKeySpec(keyBytes);
????????KeyFactory?keyFactory?=?KeyFactory.getInstance("RSA");
????????PublicKey?key?=?keyFactory.generatePublic(keySpec);
????????Signature?signature?=?Signature.getInstance("MD5withRSA");
????????signature.initVerify(key);
????????signature.update(srcData.getBytes());
????????return?signature.verify(Base64.decodeBase64(sign.getBytes()));
????}

????public?static?void?main(String[]?args)?{
????????try?{
????????????//?生成密鑰對(duì)
????????????KeyPair?keyPair?=?getKeyPair();
????????????String?privateKey?=?new?String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
????????????String?publicKey?=?new?String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
????????????System.out.println("私鑰:"?+?privateKey);
????????????System.out.println("公鑰:"?+?publicKey);
????????????//?RSA加密
????????????String?data?=?"待加密的文字內(nèi)容";
????????????String?encryptData?=?encrypt(data,?getPublicKey(publicKey));
????????????System.out.println("加密后內(nèi)容:"?+?encryptData);
????????????//?RSA解密
????????????String?decryptData?=?decrypt(encryptData,?getPrivateKey(privateKey));
????????????System.out.println("解密后內(nèi)容:"?+?decryptData);

????????????//?RSA簽名
????????????String?sign?=?sign(data,?getPrivateKey(privateKey));
????????????//?RSA驗(yàn)簽
????????????boolean?result?=?verify(data,?getPublicKey(publicKey),?sign);
????????????System.out.print("驗(yàn)簽結(jié)果:"?+?result);
????????}?catch?(Exception?e)?{
????????????e.printStackTrace();
????????????System.out.print("加解密異常");
????????}
????}
}

同樣,當(dāng)我們看到 RSA 的 Java實(shí)現(xiàn)的時(shí)候,我們就看到了他的缺點(diǎn),上來(lái)就先定義最大加密明文大小和最大解密密文大小,那么這個(gè) 117 是怎么來(lái)的?

Java 默認(rèn)的 RSA 加密實(shí)現(xiàn)不允許明文長(zhǎng)度超過(guò)密鑰長(zhǎng)度減去 11(單位是字節(jié),也就是 byte)。也就是說(shuō),如果我們定義的密鑰(我們可以通過(guò) java.security.KeyPairGenerator.initialize(int keysize) 來(lái)定義密鑰長(zhǎng)度)長(zhǎng)度為 1024(單位是位,也就是 bit),生成的密鑰長(zhǎng)度就是 1024位 / 8位/字節(jié) = 128字節(jié),那么我們需要加密的明文長(zhǎng)度不能超過(guò) 128字節(jié) -11 字節(jié) = 117字節(jié)。也就是說(shuō),我們最大能將 117 字節(jié)長(zhǎng)度的明文進(jìn)行加密,否則會(huì)出問(wèn)題( javax.crypto.IllegalBlockSizeException: Data must not be longer than 53 bytes 的異常)。

那么我們使用 RSA 的時(shí)候應(yīng)該注意什么內(nèi)容呢?

1.加密的系統(tǒng)不要具備解密的功能,否則 RSA 可能不太合適,

因?yàn)檫@樣即使黑客攻破了加密系統(tǒng),他拿到的也只是一堆無(wú)法破解的密文數(shù)據(jù)。

2.生成密文的長(zhǎng)度和明文長(zhǎng)度無(wú)關(guān),但明文長(zhǎng)度不能超過(guò)密鑰長(zhǎng)度

不管明文長(zhǎng)度是多少,RSA 生成的密文長(zhǎng)度總是固定的。但是明文長(zhǎng)度不能超過(guò)密鑰長(zhǎng)度。

也就是阿粉上面說(shuō)的那個(gè)117字節(jié)數(shù),不然就只能等著出現(xiàn)異常了。

到此這篇關(guān)于詳解RSA加密算法的原理與Java實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java RSA加密算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 帶你深入概括Java!六、方法和方法重載?。ㄍ扑])

    帶你深入概括Java!六、方法和方法重載?。ㄍ扑])

    這篇文章主要介紹了Java方法和方法重載,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 解決@Autowired報(bào)錯(cuò)Could not autowire. No beans of ‘XXX‘ type found問(wèn)題

    解決@Autowired報(bào)錯(cuò)Could not autowire. No bea

    介紹了在IDEA中使用@Autowired報(bào)錯(cuò)Couldnot autowire. No beans of 'XXX' type found的解決方法,原因是@Autowired在注入service時(shí),由于service接口沒(méi)有實(shí)現(xiàn)類,而mybatis僅需提供Dao接口,導(dǎo)致@Autowired無(wú)法識(shí)別
    2024-12-12
  • Java的函數(shù)式編程詳解

    Java的函數(shù)式編程詳解

    用了這么久的Java8,我尋思這種話也好意思說(shuō)出來(lái)嗎,難道自己是PythonBoy出身就是看不懂Java的理由嗎,身為一個(gè)合格的后端Boy不會(huì)還有人看不明白Java的函數(shù)式編程吧,接下來(lái)小編和大家淺聊一下Java的函數(shù)式編程,需要的朋友可以參考下
    2023-10-10
  • Spring Data Jpa實(shí)現(xiàn)自定義repository轉(zhuǎn)DTO

    Spring Data Jpa實(shí)現(xiàn)自定義repository轉(zhuǎn)DTO

    這篇文章主要介紹了Spring Data Jpa實(shí)現(xiàn)自定義repository轉(zhuǎn)DTO,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Springboot整合spring-boot-starter-data-elasticsearch的過(guò)程

    Springboot整合spring-boot-starter-data-elasticsearch的過(guò)程

    本文詳細(xì)介紹了Springboot整合spring-boot-starter-data-elasticsearch的過(guò)程,包括版本要求、依賴添加、實(shí)體類添加、索引的名稱、分片、副本設(shè)置等,同時(shí),還介紹了如何使用ElasticsearchRepository類進(jìn)行增刪改查操作
    2024-10-10
  • java 一鍵部署 jar 包和 war 包

    java 一鍵部署 jar 包和 war 包

    這篇文章主要介紹了Java創(chuàng)建打包命令、創(chuàng)建啟動(dòng)文件等功能實(shí)現(xiàn)Java一鍵部署 jar 包和 war 包,感興趣的下伙伴可以參考下文
    2021-09-09
  • Java?windows環(huán)境構(gòu)建圖文教程

    Java?windows環(huán)境構(gòu)建圖文教程

    這篇文章主要為大家介紹了Java?windows環(huán)境構(gòu)建圖文教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>
    2023-12-12
  • mybatis where 標(biāo)簽使用

    mybatis where 標(biāo)簽使用

    where標(biāo)記的作用類似于動(dòng)態(tài)sql中的set標(biāo)記,本文主要介紹了mybatis where 標(biāo)簽使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 流式圖表拒絕增刪改查之框架搭建過(guò)程

    流式圖表拒絕增刪改查之框架搭建過(guò)程

    這篇文章主要為大家介紹了流式圖表拒絕增刪改查之框架搭建過(guò)程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Mybatis在注解上如何實(shí)現(xiàn)動(dòng)態(tài)SQL

    Mybatis在注解上如何實(shí)現(xiàn)動(dòng)態(tài)SQL

    這篇文章主要介紹了Mybatis在注解上如何實(shí)現(xiàn)動(dòng)態(tài)SQL,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06

最新評(píng)論

宁国市| 建湖县| 澄迈县| 嘉鱼县| 金寨县| 淳安县| 湾仔区| 鞍山市| 巫溪县| 吴江市| 苍南县| 涟源市| 新泰市| 兴化市| 麟游县| 阳谷县| 黔东| 阿拉善盟| 宜州市| 南投市| 鄄城县| 扎囊县| 莱芜市| 秀山| 开远市| 连江县| 新蔡县| 法库县| 武邑县| 金堂县| 拉孜县| 双辽市| 胶州市| 虎林市| 德钦县| 武宣县| 比如县| 灌阳县| 涪陵区| 孝昌县| 岐山县|