深圳 服裝 網(wǎng)站建設(shè)青島百度網(wǎng)站排名
Rsa加解密
- 概述
- 聚合算法名稱(用于創(chuàng)建加密器)
- 基本概念
- 填充方式
- 分塊加密
- 基本使用
- 生成密鑰
- 加解密
- 創(chuàng)建加密器
- 設(shè)置模式(加密)、公鑰
- 對明文加密,并對結(jié)果進行Base64編碼
- 對以上結(jié)果,進行解密 設(shè)置模式(解密)、私鑰
- 簽名 + 驗簽
- 創(chuàng)建簽名器
- 初始化簽名器,加載簽名明文
- 生成簽名
- 初始化驗簽參數(shù),加載簽名明文
- 驗簽
- 關(guān)于初始化加密器和簽名器的重載方法
概述
RSA 是一種非對稱加密算法,它使用一對密鑰:公鑰和私鑰。公鑰用于加密數(shù)據(jù),私鑰用于解密數(shù)據(jù),或者私鑰用于簽名,公鑰用于驗證簽名。
聚合算法名稱(用于創(chuàng)建加密器)
JDK官方文檔
常用名稱:
- 加密算法名
- RSA/ECB/NoPadding
- RSA/None/NoPadding
- RSA/ECB/PKCS1Padding
- RSA/ECB/OAEPWithSHA-1AndMGF1Padding
- RSA/ECB/OAEPWithSHA-256AndMGF1Padding
- 簽名算法
- SHA1withRSA(早期使用,現(xiàn)不推薦)
- SHA256withRSA(滿足日常需要,一般情況用得最多)
- SHA384withRSA(安全性要求更高,計算成本隨著變高)
- SHA512withRSA(安全性要求極高)
- MD5withRSA(目前已不推薦使用,MD5被證明存在安全漏洞)
基本概念
RSA需要一對密鑰對,通常需要代碼或工具生成。
原始密鑰數(shù)據(jù)是字節(jié)數(shù)組,因此如果需要分發(fā)或者存儲,通常也會進行Base64編碼。
填充方式
RSA對明文同樣有要求,明文塊不能大于密鑰長度。因此,通常情況下,也需要進行明文填充,如果選擇無填充,那么明文長度如果不是密鑰長度倍數(shù),那么可能會報錯。
- PKCS1Padding
這是最常用的填充方式,基本滿足日常使用 - OAEP(OAEPWithSHA-1AndMGF1Padding 和 OAEPWithSHA-256AndMGF1Padding)
OAEP 是一種更安全的填充方式,主要用于防止選擇明文攻擊(CPA)等高級攻擊方式。它基于哈希函數(shù)和掩碼生成函數(shù)來構(gòu)建填充結(jié)構(gòu)。多用于安全要求較高的場景,如金融等場景。雖然安全性更高,但是計算成本也更高。 - NoPadding
不進行填充,此時對明文有要求,長度須是密鑰整數(shù)倍。
分塊加密
RSA算法要求:單次加密明文長度不能超出密鑰長度;如果明文可能超出密鑰長度,要么使用ECB分塊模式加密,要么手動分塊后逐個塊加密。
分塊模式:ECB(按密鑰長度分塊)、NONE(不分塊)
基本使用
生成密鑰
支持密鑰長度:512及以下(早期使用,現(xiàn)在少用)、1024(用得較多)、2048(目前使用最多)、3072 位和 4096 位(對安全要求極高的場景,但會增加計算成本)
- 生成密鑰對象
KeyPairGenerator pairGenerator = KeyPairGenerator.getInstance("RSA");
pairGenerator.initialize(2048);
KeyPair keyPair = pairGenerator.genKeyPair();
- 解析出公私鑰(可以從密鑰對象中獲取公私鑰)
// 私鑰
PrivateKey privateKey = keyPair.getPrivate();
// 公鑰
PublicKey publicKey = keyPair.getPublic();
- 此時的公私鑰是以字節(jié)數(shù)組存在,如果要進行存儲和分發(fā)。通常使用Base64編碼
// 私鑰字符串
String privateEncode = Base64.getEncoder().encodeToString(privateKey.getEncoded());// 公鑰字符串
String publicEncode = Base64.getEncoder().encodeToString(publicKey.getEncoded())
加解密
創(chuàng)建加密器
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
設(shè)置模式(加密)、公鑰
cipher.init(Cipher.ENCRYPT_MODE, keyPair.getPublic());
對明文加密,并對結(jié)果進行Base64編碼
byte[] bytes = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));System.out.println("加密后的內(nèi)容:" + Base64.getEncoder().encodeToString(bytes));
對以上結(jié)果,進行解密 設(shè)置模式(解密)、私鑰
cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
byte[] bytes1 = cipher.doFinal(bytes);
System.out.println("解密后的內(nèi)容:" + new String(bytes1));
簽名 + 驗簽
我們通常說的RSA簽名實際上是一種簡略的說法。
RSA簽名實際是:簽名 + 加密 2個過程。
其中散列算法(或者叫摘要算法,簽名算法等等)常用的有:
- SHA256(大部分場景使用,平衡安全和性能)
- SHA384
- SHA512
- MD5(MD5被證明存在漏洞,不推薦使用)
- SHA1(早期使用,目前已不推薦使用)
這些散列算法,是獨立于RSA的,RSA簽名算法名稱就是在它們后面增加 withRSA 而已。
所謂RSA簽名,只是對散列算法得到的散列值進行RSA加密而已。這一點要明確。
接著上面創(chuàng)建RSA密鑰后,開始進行簽名與驗簽
創(chuàng)建簽名器
與加解密不同,簽名器由Signature這個類提供支持
Signature signature = Signature.getInstance("SHA256withRSA");
初始化簽名器,加載簽名明文
signature.initSign(keyPair.getPrivate());
signature.update(str.getBytes(StandardCharsets.UTF_8));
生成簽名
byte[] byteSign = signature.sign();
System.out.println("簽名:" + Base64.getEncoder().encodeToString(byteSign));
初始化驗簽參數(shù),加載簽名明文
signature.initVerify(keyPair.getPublic());
signature.update(str.getBytes(StandardCharsets.UTF_8));
驗簽
boolean verify = signature.verify(byteSign);
System.out.println("驗簽結(jié)果:" + verify);
關(guān)于初始化加密器和簽名器的重載方法
在RSA加密場景,除了模式,公鑰外,還有個參數(shù)SecureRandom random,它用于在一些填充模式(OAEP)下,生成一個隨機掩碼,提高加密安全性。