1.RSA算法史:
RSA是1977年由羅納德·李維斯特(Ron Rivest)山上、阿迪·薩莫爾(Adi Shamir)和倫納德·阿德曼(Leonard Adleman)三位數(shù)學家提出。在麻省理工學院工作搪缨。RSA就是他們?nèi)诵帐祥_頭字母拼在一起組成的碉哑。
但實際上挚币,在1973年,在英國政府通訊總部工作的數(shù)學家克利福德·柯克斯(Clifford Cocks)在一個內(nèi)部文件中提出了一個相同的算法扣典,但他的發(fā)現(xiàn)被列入機密妆毕,一直到1997年才被發(fā)表。
2.RSA加密簡介:
RSA加密是一種非對稱加密贮尖〉颜常可以在不直接傳遞密鑰的情況下,完成解密湿硝。這能夠確保信息的安全性薪前,避免了直接傳遞密鑰所造成的被破解的風險。是由一對密鑰來進行加解密的過程关斜,分別稱為公鑰和私鑰示括。兩者之間有數(shù)學相關,該加密算法的原理就是對一極大整數(shù)做因數(shù)分解的困難性來保證安全性痢畜。通常個人保存私鑰垛膝,公鑰是公開的(可能同時多人持有)
3.RSA加密、簽名區(qū)別:
加密和簽名都是為了安全性考慮丁稀,但略有不同吼拥。常有人問加密和簽名是用私鑰還是公鑰?其實都是對加密和簽名的作用有所混淆线衫。簡單的說凿可,加密是為了防止信息被泄露,而簽名是為了防止信息被篡改桶雀。這里舉2個例子說明矿酵。
4.使用場景
場景一:
第一個場景:戰(zhàn)場上唬复,B要給A傳遞一條消息,內(nèi)容為某一指令全肮。
RSA的加密過程如下:
@1A生成一對密鑰(公鑰和私鑰)敞咧,私鑰不公開,A自己保留辜腺。公鑰為公開的休建,任何人可以獲取。
@2A傳遞自己的公鑰給B评疗,B用A的公鑰對消息進行加密测砂。
@3A接收到B加密的消息,利用A自己的私鑰對消息進行解密百匆。
在這個過程中砌些,只有2次傳遞過程,第一次是A傳遞公鑰給B加匈,第二次是B傳遞加密消息給A存璃,即使都被敵方截獲,也沒有危險性雕拼,因為只有A的私鑰才能對消息進行解密纵东,防止了消息內(nèi)容的泄露。
場景二:
第二個場景:A收到B發(fā)的消息后啥寇,需要進行回復“收到”偎球。
RSA簽名的過程如下:
(1)A生成一對密鑰(公鑰和私鑰),私鑰不公開辑甜,A自己保留衰絮。公鑰為公開的,任何人可以獲取磷醋。
(2)A用自己的私鑰對消息加簽岂傲,形成簽名,并將加簽的消息和消息本身一起傳遞給B子檀。
(3)B收到消息后,在獲取A的公鑰進行驗簽乃戈,如果驗簽出來的內(nèi)容與消息本身一致褂痰,證明消息是A回復的。
在這個過程中症虑,只有2次傳遞過程缩歪,第一次是A傳遞加簽的消息和消息本身給B,第二次是B獲取A的公鑰谍憔,即使都被敵方截獲匪蝙,也沒有危險性主籍,因為只有A的私鑰才能對消息進行簽名,即使知道了消息內(nèi)容逛球,也無法偽造帶簽名的回復給B千元,防止了消息內(nèi)容的篡改。
項目案例:
第二個場景:A收到B發(fā)的消息后颤绕,需要進行回復“收到”幸海。
RSA簽名的過程如下:
(1)A生成一對密鑰(公鑰和私鑰),私鑰不公開奥务,A自己保留物独。公鑰為公開的,任何人可以獲取氯葬。
(2)A用自己的私鑰對消息加簽挡篓,形成簽名,并將加簽的消息和消息本身一起傳遞給B帚称。
(3)B收到消息后官研,在獲取A的公鑰進行驗簽,如果驗簽出來的內(nèi)容與消息本身一致世杀,證明消息是A回復的阀参。
在這個過程中,只有2次傳遞過程瞻坝,第一次是A傳遞加簽的消息和消息本身給B蛛壳,第二次是B獲取A的公鑰,即使都被敵方截獲所刀,也沒有危險性衙荐,因為只有A的私鑰才能對消息進行簽名,即使知道了消息內(nèi)容浮创,也無法偽造帶簽名的回復給B忧吟,防止了消息內(nèi)容的篡改。
5.RSA項目中加密流程
RSA是一種常用的非對稱加密算法斩披,所謂非對稱加密是指使用一對密鑰(公鑰和私鑰)進行加密和解密溜族,公鑰人人都可以獲得,用于加密數(shù)據(jù)垦沉,私鑰保存在服務器中煌抒,用于解密數(shù)據(jù)。加密解密過程如下:
RSA加密流程.png
使用RSA進行加密解密厕倍,其優(yōu)點是非常不容易破解寡壮,缺點是和對稱加密(如AES)相比,加密速度較慢。因此况既,實際使用中这溅,常常將對稱加密和非對稱加密結(jié)合使用,即使用非對稱加密協(xié)商對稱加密的密鑰棒仍,使用對稱加密密鑰加密傳輸內(nèi)容悲靴。
6.RSA項目中加密源碼
6.1生成隨機公鑰私鑰
隨機生成公鑰和私鑰,用于測試RSA加密解密
/**
* 私鑰
*/
private static RSAPrivateKey privateKey;
/**
* 公鑰
*/
private static RSAPublicKey publicKey;
/**
* 隨機生成密鑰對
*/
public static void genKeyPair() {
KeyPairGenerator keyPairGen = null;
try {
keyPairGen = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
keyPairGen.initialize(1024, new SecureRandom());
KeyPair keyPair = keyPairGen.generateKeyPair();
privateKey = (RSAPrivateKey) keyPair.getPrivate();
publicKey = (RSAPublicKey) keyPair.getPublic();
}
6.2加載公鑰/私鑰
從字符串/文件輸入流中加載公鑰
/**
* 從字符串中加載公鑰
*
* @param publicKeyStr 公鑰數(shù)據(jù)字符串
* @throws Exception 加載公鑰時產(chǎn)生的異常
*/
public static void loadPublicKey(String publicKeyStr) throws Exception {
try {
byte[] buffer = EnDecryptionUtil.base64Decode(publicKeyStr);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("無此算法");
} catch (InvalidKeySpecException e) {
throw new Exception("公鑰非法");
} catch (NullPointerException e) {
throw new Exception("公鑰數(shù)據(jù)為空");
}
}
/**
* 從文件輸入流中加載公鑰
*
* @param in 公鑰輸入流
* @throws Exception 加載公鑰時產(chǎn)生的異常
*/
public static void loadPublicKey(InputStream in) throws Exception {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String readLine = null;
StringBuilder sb = new StringBuilder();
while ((readLine = br.readLine()) != null) {
if (readLine.charAt(0) == '-') {
continue;
} else {
sb.append(readLine);
sb.append('\r');
}
}
loadPublicKey(sb.toString());
} catch (IOException e) {
throw new Exception("公鑰數(shù)據(jù)流讀取錯誤");
} catch (NullPointerException e) {
throw new Exception("公鑰輸入流為空");
}
}
//從字符串/文件輸入流中加載私鑰
/**
* 從字符串中加載私鑰
* @param privateKeyStr
* @throws Exception
*/
public static void loadPrivateKey(String privateKeyStr) throws Exception {
try {
byte[] buffer = EnDecryptionUtil.base64Decode(privateKeyStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
privateKey = (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (NoSuchAlgorithmException e) {
throw new Exception("無此算法");
} catch (InvalidKeySpecException e) {
throw new Exception("私鑰非法");
} catch (NullPointerException e) {
throw new Exception("私鑰數(shù)據(jù)為空");
}
}
/**
* 從文件輸入流中加載私鑰
*
* @param in 私鑰輸入流
* @return 是否成功
* @throws Exception
*/
public static void loadPrivateKey(InputStream in) throws Exception {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String readLine = null;
StringBuilder sb = new StringBuilder();
while ((readLine = br.readLine()) != null) {
if (readLine.charAt(0) == '-') {
continue;
} else {
sb.append(readLine);
sb.append('\r');
}
}
loadPrivateKey(sb.toString());
} catch (IOException e) {
throw new Exception("私鑰數(shù)據(jù)讀取錯誤");
} catch (NullPointerException e) {
throw new Exception("私鑰輸入流為空");
}
}
6.3RSA加密數(shù)據(jù)
/**
* RSA加密過程
*
* @param publicKey 公鑰
* @param plainTextData 明文數(shù)據(jù)
* @return
* @throws Exception 加密過程中的異常信息
*/
public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData) throws Exception {
if (publicKey == null) {
throw new Exception("加密公鑰為空, 請設置");
}
Cipher cipher;
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(plainTextData);
} catch (NoSuchAlgorithmException e) {
throw new Exception("無此加密算法");
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
} catch (InvalidKeyException e) {
throw new Exception("加密公鑰非法,請檢查");
} catch (IllegalBlockSizeException e) {
throw new Exception("明文長度非法");
} catch (BadPaddingException e) {
throw new Exception("明文數(shù)據(jù)已損壞");
}
}
//加密后獲得的byte[]數(shù)組一般會進行Base64編碼
6.4RSA解密
/**
* RSA解密
*
* @param privateKey 私鑰
* @param cipherData 密文數(shù)據(jù)
* @return 明文
* @throws Exception 解密過程中的異常信息
*/
public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception {
if (privateKey == null) {
throw new Exception("解密私鑰為空, 請設置");
}
Cipher cipher = null;
try {
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(cipherData);
} catch (NoSuchAlgorithmException e) {
throw new Exception("無此解密算法");
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
} catch (InvalidKeyException e) {
throw new Exception("解密私鑰非法,請檢查");
} catch (IllegalBlockSizeException e) {
throw new Exception("密文長度非法");
} catch (BadPaddingException e) {
throw new Exception("密文數(shù)據(jù)已損壞");
}
}
//如果輸入的密文進行過Base64編碼降狠,需Base64解碼后再進行RSA解密
6.4RSA 運行結(jié)果
公鑰:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO2TVhB1VIpUhNb5+owamkjmU8dNEMJyTbakBT
b7GysKaA+byMRqJLRAbVPj+eD15erREOkv9A1z4mOMo7i+7hb6J8LuktCDWC5QeusvbwlpOjjIE6
Sq8pETHPnHX5dd+ORFYWPrbd7drSIv0Fbm3R7zi0LhuJn3JWkLf1JEFDywIDAQAB
私鑰:MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAM7ZNWEHVUilSE1vn6jBqaSOZTx0
0QwnJNtqQFNvsbKwpoD5vIxGoktEBtU+P54PXl6tEQ6S/0DXPiY4yjuL7uFvonwu6S0INYLlB66y
9vCWk6OMgTpKrykRMc+cdfl1345EVhY+tt3t2tIi/QVubdHvOLQuG4mfclaQt/UkQUPLAgMBAAEC
gYB+M3Xm4iN9dCI95JnDy4ymMp6/mQImaQeKuzPN9Dq1rCOaU0RfTYUdaL7GgfkshXHtT6g1fSgx
NmHbzhBM7l5qoYJNwz/8KQ9rTphdc0JQFzu3ECkDZvOe+yjSKWpuZFGizLsB2j3Og4MF3fOKNfN7
c1ucNNEYpzbGPyOPC23TWQJBAPOU5pLEwMV4VSC3LgJcjorvf5DQqJVpnPYyHRE7MFhsnVHfmbIq
nTBhOcdomwOde+yQjerGIi7W7RIjobgoZdUCQQDZZOLEo5qdIXn319R3ucPsAHLPcTa8kfxpUHLo
rN8INKUj7dR3FtWc9cye5fzWRg+NkBx6OC408l95qeGvBbMfAkEAqQJ7DgFJBHtfDcksOmVAXnSZ
XcD6CFn0l/rjok4gWGpcqi9stGvPD3+WmJ8jV9nQ367ZWbpKg5eLfReOIXqeVQJBAMuxwuVbIoE+
n8kBm1w/XHuig/EpdI9F/oszTSgE6soGggHjU6PuamMy0PLGLp0bcnFDadt/DpSf0aPu8L8NCSMC
QQDvL5cjxQqIPJSP1T+JKktvd+nWPULt7Adir1fab022e0XfEod73Eoo4rp0GmN0hSZUH0VBBvqf
lNY1P23tZP3C
待加密明文:123456
加密后Base64數(shù)據(jù):KMzWgXeWLpc31/D3LOv65AYquARkNCoPNVy+vqZd4ASC8hev1iZtBOowmWp5mMr0pYHya9AK6Ang
GZmT2KzS472r+UR6LJxY7u3qthGuWiWcWmZbyH/z2LEB6du60b8BOpa670GE/HB074z85kPTWCWE
3kvBNDbYvDdfjMD/8JY=
待解密Base64密文:KMzWgXeWLpc31/D3LOv65AYquARkNCoPNVy+vqZd4ASC8hev1iZtBOowmWp5mMr0pYHya9AK6Ang
GZmT2KzS472r+UR6LJxY7u3qthGuWiWcWmZbyH/z2LEB6du60b8BOpa670GE/HB074z85kPTWCWE
3kvBNDbYvDdfjMD/8JY=
解密后數(shù)據(jù):123456
總結(jié):
公鑰加密对竣、私鑰解密、私鑰簽名榜配、公鑰驗簽否纬。
想要源碼評論區(qū)回復我,給你私發(fā)鏈接
Kotlin基礎篇【1】Android Studio 3.0 Kotlin環(huán)境配置
Kotlin基礎篇【2】初識Kotlin的意義
Kotlin基礎篇【3】Kotlin基礎語法
=======Kotlin基礎篇【4】Kotlin基礎語法即將更新=======