一句柠、什么是非對稱加密算法么库?
非對稱主要是相對于對稱加密算法而言的傻丝。對稱加密算法加解密使用同一個秘鑰;非對稱算法則有一個公鑰和一個私鑰诉儒,公鑰與私鑰是一對的葡缰。一般,我們利用公鑰加密忱反,私鑰解密泛释。
RSA是可以雙向加密的:私鑰加密,公鑰解密温算;公鑰加密怜校,私鑰解密。
二注竿、非對稱加密算法的特點
算法強度復(fù)雜茄茁、安全性依賴于算法與密鑰。但是由于算法復(fù)雜巩割,使得非對稱算法加解密速度沒有對稱算法加解密的速度快裙顽。
對稱密鑰體制中只有一種密鑰,并且是非公開的宣谈,如果要解密就得讓對方知道密鑰愈犹。所以保證其安全性就是保證密鑰的安全。
非對稱密鑰體制有兩種密鑰闻丑,其中一個是公開的漩怎,這樣就可以不需要像對稱密碼那樣向?qū)Ψ絺鬏斆荑€了。因此安全性就大了很多嗦嗡。
算法復(fù)雜度:對稱密鑰 < 非對稱密鑰
加解密速度:對稱密鑰 > 非對稱密鑰
安全性:對稱密鑰 < 非對稱密鑰
三勋锤、RSA 算法簡介
RSA算法1978年就出現(xiàn)了,算法的名字以發(fā)明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman侥祭。
它是第一個既能用于數(shù)據(jù)加密也能用于數(shù)字簽名的算法叁执。
它易于理解和操作,也很流行卑硫。
這種加密算法的特點主要是密鑰的變化,密鑰長度越長蚕断,安全性越高欢伏。
RSA算法的JDK實現(xiàn)默認密鑰長度是1024,BC則是2048亿乳,密鑰長度必須是64的倍數(shù)硝拧,在512到65536位之間径筏。
有些算法只規(guī)定了公鑰加密、私鑰解密障陶,RSA算法則支持公鑰加密滋恬、私鑰解密.私鑰加密、公鑰解密抱究。
四恢氯、RSA加密算法使用到的接口、類鼓寺、相關(guān)方法和參數(shù)
- KeyPairGenerator
密鑰對生成器勋拟,用于生成密鑰對
- KeyPair
密鑰對,可以用于生成公私鑰
- KeyFactory
密鑰工廠妈候,作用是生成密鑰敢靡,包括公鑰和私鑰
????- generatePublic()方法 用來生成公鑰
????- generatePrivate()方法 用來生成私鑰
- PublicKey
公鑰
- PrivateKey
私鑰
- RSAPublicKey
RSA公鑰,繼承自 PublicKey 與 RSAKey
- RSAPrivateKey
RSA私鑰苦银,繼承自 PrivateKey 與 RSAKey
- RSAPublicKeySpec
此類指定 RSA 公用密鑰
????- RSAPublicKeySpec(BigInteger modulus,BigInteger publicExponent) 構(gòu)造方法
????????modulus - 系數(shù) , publicExponent - 公用指數(shù)
????- getModulus() 方法 返回改系數(shù)
????- getPublicExponent() 方法 返回改公用指數(shù)
- RSAPrivateKeySpec
類比 RSAPublicKeySpec 類啸胧,構(gòu)造方法與屬性方法類似
- SecureRandom
強加密隨機數(shù)生成器
- Cipher
提供加解密的功能
五、java 實現(xiàn)簡單的 RSA 加解密
public static void rsa() {
try {
/* step1 : 生成密鑰對生成器
*
* 如果默認的提供程序(procider)提供RSA算法的實現(xiàn)幔虏,則返回包含該實現(xiàn)的 KeyPairGenerator 的實例纺念。
* 如果默認包中不存在該算法,則搜索其他包所计。
*
* 也可以指定其它加密算法提供程序 柠辞, 如 BC:
* KeyPairGenerator.getInstance("RSA", new BouncyCastleProvider());
*/
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
//KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA", new BouncyCastleProvider());
/* step2:初始化密鑰對生成器 , 確定密鑰長度大小與隨機源
*
* 使用默認的參數(shù)集合并使用提供程序(以最高優(yōu)先級安裝)的 SecureRandom 實現(xiàn)作為隨機源主胧。
* 如果任何安裝的提供程序都不提供 SecureRandom 的實現(xiàn)叭首,則使用系統(tǒng)提供的隨機源。
*
* 當然也可以指定隨機源踪栋,如下:
* keyPairGenerator.initialize(1024,new SecureRandom(byte[] bytes));
*/
keyPairGenerator.initialize(1024);
//keyPairGenerator.initialize(1024,new SecureRandom(DateFormatUtils.format(new Date(),"yyyyMMdd").getBytes()));
// step3:獲取密鑰對
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// step4:獲取密鑰
RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();
// step5:創(chuàng)建 Cipher 對象
Cipher cipher = Cipher.getInstance("RSA");
// step6:加密
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encodeByte = cipher.doFinal(str.getBytes());
String encodeStr = Hex.encodeHexString(encodeByte);
System.out.println("加密數(shù)據(jù):" + encodeStr);
// step7:解密
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decodeByte = cipher.doFinal(Hex.decodeHex(encodeStr.toCharArray()));
String decodeStr = new String(decodeByte);
System.out.println("解密數(shù)據(jù):"+decodeStr);
} catch (Exception e) {
}
}
- KeyPairGenerator 密鑰對生成器在創(chuàng)建時可以指定加密算法提供程序焙格,一般使用 BouncyCastle(簡稱 BC);也可以使用 JDK 自帶的默認加密算法提供程序夷都。
初始化 KeyPairGenerator 時可以指定隨機源 SecureRandom眷唉;如果不指定,則使用提供程序(以最高優(yōu)先級安裝)的 SecureRandom 實現(xiàn)作為隨機源囤官。 - SecureRandom 強隨機數(shù)生成器冬阳;在 new 對象時可以傳參 byte[] ,參數(shù)稱為 "種子" 党饮。如果選擇無參構(gòu)造肝陪,則自供種子。
/**
* 加密方法返回 encodeByteArray ;
* Hex.encodeHexString 將encodeByteArray數(shù)組轉(zhuǎn)換為 encodeString ;
*/
byte[] encodeByte = cipher.doFinal(str.getBytes());
String encodeStr = Hex.encodeHexString(encodeByte);
System.out.println("加密數(shù)據(jù):" + encodeStr);
// step7:解密
/**
* Hex.decodeHex(encodeStr.toCharArray()) 將 encodeString 轉(zhuǎn)換為 byteArray ;
*/
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decodeByte = cipher.doFinal(Hex.decodeHex(encodeStr.toCharArray()));
String decodeStr = new String(decodeByte);
注意:
如果使用 BC 作為算法提供者刑顺,BouncyCastleProvider 對象應(yīng)使用單例模式氯窍。
因為這個類里面有較多靜態(tài)的屬性與方法饲常, new一個多一個, GC不回收 狼讨。
必然會造成內(nèi)存上升贝淤,直至內(nèi)存溢出,服務(wù)宕機
六政供、實現(xiàn)簡單的 js 加密 + java 解密
1. 后臺 java 生成加密模(modulus)
與公鑰指數(shù)(exponent)
提供給前端
RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
String modulus =
new String(Hex.encodeHex(publicKey.getModulus().toByteArray()));
String exponent =
new String(Hex.encodeHex(publicKey.getPublicExponent().toByteArray()));
- 加密模與公鑰指數(shù)由 RSA公鑰
RSAPublicKey
生成
2. 前端 js 進行 RSA 加密播聪,此例引用第三類庫 security.js
,示例代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RSA加密demo</title>
<script src="./security.js"></script>
<script>
window.onload = function () {
// 加密模
let modulus = '009792706f90962e037126c0c0deeccd38d55fabcae6470fe049327f' +
'53f84045882d7217581b6bd86c759d647e585486b0f708cc6cedf1a521752ba9c89bc' +
'ff1d9d356b802984ca538e0a6f689ace76ee7f5087663637239eefbc95bca7afaabd3e' +
'22cf7acaeec36cf3febd2240bb25656a2cce0eacee73fb9a95b091d0f038049';
// 公鑰指數(shù)
let exponent = '010001';
/**
* 選擇使用 encodeURIComponent 方法
*
* 若采用 encodeURI 方法編碼鲫骗,java 用 URLDecoder.decode(pwd,"UTF-8") 解碼時犬耻,
* 會出現(xiàn)部分符號丟失,例如 '+' 执泰;
*
* 使用 encodeURIComponent 枕磁, 可以避免此問題
*/
// let strOld = encodeURI('我+Admin@1234');
let strOld = encodeURIComponent('我+Admin@1234');
/**
* 當exponent、modulus為''時可能會導(dǎo)致瀏覽器卡死术吝,通常出現(xiàn)在ajax異步請求時计济。
*/
let publicKey = RSAUtils.getKeyPair(exponent, '', modulus);
let encodeStr = RSAUtils.encryptedString(publicKey, strOld);
console.log('原文:' + strOld + '\n密文:' + encodeStr)
}
</script>
</head>
<body>
</body>
</html>
-
RSAUtils.getKeyPair(exponent, '', modulus)
方法
其中,exponent(公鑰指數(shù))
與modulus(加密模)
生成代碼參考上面步驟排苍。 -
RSAUtils.encryptedString(publicKey, strOld)
加密方法
注意:
- 當
exponent沦寂、modulus
為''
空時,可能會導(dǎo)致瀏覽器卡死淘衙;- 使用
encodeURIComponent
方法對明文進行編碼轉(zhuǎn)換传藏,使用encodeURI
必然會造成 特殊符號+
丟失(如果原明文中存在+
的話);
后臺java
程序可使用URLDecoder.decode(pwd,"UTF-8")
進行解碼彤守;
3. 后臺解密
// step1 : 將密文轉(zhuǎn)換為16進制 byte 數(shù)組
byte[] en_data = Hex.decodeHex(encrypttext.toCharArray());
// step2:解密得到 decryptByteArray
Cipher ci = Cipher.getInstance("RSA", DEFAULT_PROVIDER);
ci.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptByteArray = ci.doFinal(data);
// step3:將 decryptByteArray 轉(zhuǎn)換為 decryptString
String decryptString = new String(decryptByteArray);
// step4:將 decryptString 反轉(zhuǎn)
decryptString = StringUtils.reverse(decryptString);
// step5:對 decryptString 進行 URLDecoder 解碼毯侦,并得到解密后明文
decryptString = URLDecoder.decode(decryptString ,"UTF-8");
至此,完成的前端 js 進行 RSA 加密具垫,后臺 java 解密的流程已經(jīng)結(jié)束侈离。
demo 源碼下載
下載連接 ??????? 密碼:bqxq
-
或者直接掃下面二維碼下載
掃一掃可直接下載源碼