RSA加密演算法的簡單案例
RSA加密演算法是目前最有影響力的公鑰加密演算法,它能夠抵抗到目前為止已知的絕大多數密碼攻擊。
那關於RSA加密演算法有哪些應用呢?以下舉一個資料庫身份驗證的案例。
在使用資料集進行身份認證時,密碼存在資料庫中,認證時使用者輸入的密碼與資料庫中密碼相同則認證透過,若資料庫被破解了則對系統造成威脅,怎樣保證系統安全呢?這裡就可以應用RSA加密演算法,對許可權加密。
思路:
就是在url中傳使用者名稱密碼時,先把使用者名稱進行翻轉,然後再進行加密,如輸入的密碼為12,實際後臺進行加密的值為21,再與資料庫進行驗證,這樣就可以避免資料庫被破解檢視到的是21的加密碼,登陸系統時以21是無法登陸成功的。
以報表軟體FineReport為例,這是一個能讀取各類資料庫的報表軟體,分客戶端和前端展示。
實現方案:
1、把RSA加密使用的第三方包,放到工程web-inf/lib資料夾下即可。
2、呼叫js檔案
RSA資料夾為前端js加密時需要呼叫js檔案,因此需要將Barrett.js、BigInt.js、RSA.js放到工程目錄下如:WebReport/js,新建js資料夾放入js檔案。
3、定義RSA加密類
定義RSAUtil.java類檔案,先執行類中generateKeyPair()方法,會在伺服器D盤中生成一個隨機的RSAKey.txt檔案,儲存公鑰和金鑰,每訪問一次這個方法會重新整理一次txt檔案。
點選(此處)摺疊或開啟
-
package com.fr.privilege;
-
-
import java.io.ByteArrayOutputStream;
-
import java.io.FileInputStream;
-
import java.io.FileOutputStream;
-
import java.io.ObjectInputStream;
-
import java.io.ObjectOutputStream;
-
import java.math.BigInteger;
-
import java.security.KeyFactory;
-
import java.security.KeyPair;
-
import java.security.KeyPairGenerator;
-
import java.security.NoSuchAlgorithmException;
-
import java.security.PrivateKey;
-
import java.security.PublicKey;
-
import java.security.SecureRandom;
-
import java.security.interfaces.RSAPrivateKey;
-
import java.security.interfaces.RSAPublicKey;
-
import java.security.spec.InvalidKeySpecException;
-
import java.security.spec.RSAPrivateKeySpec;
-
import java.security.spec.RSAPublicKeySpec;
-
-
import javax.crypto.Cipher;
-
-
/**
-
* RSA 工具類。提供加密,解密,生成金鑰對等方法。
-
* 需要到下載bcprov-jdk14-123.jar。
-
*
-
*/
-
public class RSAUtil {
-
/**
-
* * 生成金鑰對 *
-
*
-
* @return KeyPair *
-
* @throws EncryptException
-
*/
-
public static KeyPair generateKeyPair() throws Exception {
-
try {
-
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",
-
new org.bouncycastle.jce.provider.BouncyCastleProvider());
-
final int KEY_SIZE = 1024;// 沒什麼好說的了,這個值關係到塊加密的大小,可以更改,但是不要太大,否則效率會低
-
keyPairGen.initialize(KEY_SIZE, new SecureRandom());
-
KeyPair keyPair = keyPairGen.generateKeyPair();
-
saveKeyPair(keyPair);
-
return keyPair;
-
} catch (Exception e) {
-
throw new Exception(e.getMessage());
-
}
-
}
-
-
public static KeyPair getKeyPair() throws Exception {
-
FileInputStream fis = new FileInputStream("C:/RSAKey.txt");
-
ObjectInputStream oos = new ObjectInputStream(fis);
-
KeyPair kp = (KeyPair) oos.readObject();
-
oos.close();
-
fis.close();
-
return kp;
-
}
-
-
public static void saveKeyPair(KeyPair kp) throws Exception {
-
-
FileOutputStream fos = new FileOutputStream("C:/RSAKey.txt");
-
ObjectOutputStream oos = new ObjectOutputStream(fos);
-
// 生成金鑰
-
oos.writeObject(kp);
-
oos.close();
-
fos.close();
-
}
-
-
/**
-
* * 生成公鑰 *
-
*
-
* @param modulus *
-
* @param publicExponent *
-
* @return RSAPublicKey *
-
* @throws Exception
-
*/
-
public static RSAPublicKey generateRSAPublicKey(byte[] modulus,
-
byte[] publicExponent) throws Exception {
-
KeyFactory keyFac = null;
-
try {
-
keyFac = KeyFactory.getInstance("RSA",
-
new org.bouncycastle.jce.provider.BouncyCastleProvider());
-
} catch (NoSuchAlgorithmException ex) {
-
throw new Exception(ex.getMessage());
-
}
-
-
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(
-
modulus), new BigInteger(publicExponent));
-
try {
-
return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);
-
} catch (InvalidKeySpecException ex) {
-
throw new Exception(ex.getMessage());
-
}
-
}
-
-
/**
-
* * 生成私鑰 *
-
*
-
* @param modulus *
-
* @param privateExponent *
-
* @return RSAPrivateKey *
-
* @throws Exception
-
*/
-
public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus,
-
byte[] privateExponent) throws Exception {
-
KeyFactory keyFac = null;
-
try {
-
keyFac = KeyFactory.getInstance("RSA",
-
new org.bouncycastle.jce.provider.BouncyCastleProvider());
-
} catch (NoSuchAlgorithmException ex) {
-
throw new Exception(ex.getMessage());
-
}
-
-
RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(
-
modulus), new BigInteger(privateExponent));
-
try {
-
return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);
-
} catch (InvalidKeySpecException ex) {
-
throw new Exception(ex.getMessage());
-
}
-
}
-
-
/**
-
* * 加密 *
-
*
-
* @param key
-
* 加密的金鑰 *
-
* @param data
-
* 待加密的明文資料 *
-
* @return 加密後的資料 *
-
* @throws Exception
-
*/
-
public static byte[] encrypt(PublicKey pk, byte[] data) throws Exception {
-
try {
-
Cipher cipher = Cipher.getInstance("RSA",
-
new org.bouncycastle.jce.provider.BouncyCastleProvider());
-
cipher.init(Cipher.ENCRYPT_MODE, pk);
-
int blockSize = cipher.getBlockSize();// 獲得加密塊大小,如:加密前資料為128個byte,而key_size=1024
-
// 加密塊大小為127
-
// byte,加密後為128個byte;因此共有2個加密塊,第一個127
-
// byte第二個為1個byte
-
int outputSize = cipher.getOutputSize(data.length);// 獲得加密塊加密後塊大小
-
int leavedSize = data.length % blockSize;
-
int blocksSize = leavedSize != 0 ? data.length / blockSize + 1
-
: data.length / blockSize;
-
byte[] raw = new byte[outputSize * blocksSize];
-
int i = 0;
-
while (data.length - i * blockSize > 0) {
-
if (data.length - i * blockSize > blockSize)
-
cipher.doFinal(data, i * blockSize, blockSize, raw, i
-
* outputSize);
-
else
-
cipher.doFinal(data, i * blockSize, data.length - i
-
* blockSize, raw, i * outputSize);
-
// 這裡面doUpdate方法不可用,檢視原始碼後發現每次doUpdate後並沒有什麼實際動作除了把byte[]放到
-
// ByteArrayOutputStream中,而最後doFinal的時候才將所有的byte[]進行加密,可是到了此時加密塊大小很可能已經超出了
-
// OutputSize所以只好用dofinal方法。
-
-
i++;
-
}
-
return raw;
-
} catch (Exception e) {
-
throw new Exception(e.getMessage());
-
}
-
}
-
-
/**
-
* * 解密 *
-
*
-
* @param key
-
* 解密的金鑰 *
-
* @param raw
-
* 已經加密的資料 *
-
* @return 解密後的明文 *
-
* @throws Exception
-
*/
-
public static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception {
-
try {
-
Cipher cipher = Cipher.getInstance("RSA",
-
new org.bouncycastle.jce.provider.BouncyCastleProvider());
-
cipher.init(cipher.DECRYPT_MODE, pk);
-
int blockSize = cipher.getBlockSize();
-
ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
-
int j = 0;
-
-
while (raw.length - j * blockSize > 0) {
-
bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
-
j++;
-
}
-
return bout.toByteArray();
-
} catch (Exception e) {
-
throw new Exception(e.getMessage());
-
}
-
}
-
-
/**
-
* * *
-
*
-
* @param args *
-
* @throws Exception
-
*/
-
public static void main(String[] args) throws Exception {
-
RSAPublicKey rsap = (RSAPublicKey) RSAUtil.generateKeyPair()
-
.getPublic();
-
String test = "hello world";
-
byte[] en_test = encrypt(getKeyPair().getPublic(), test.getBytes());
-
System.out.println("123:" + new String(en_test));
-
byte[] de_test = decrypt(getKeyPair().getPrivate(), en_test);
-
System.out.println(new String(de_test));
-
}
- }
4、定義密碼驗證類
定義TestPasswordValidatorRSA.java密碼驗證類
定義一個類,命名為TestPasswordValidatorRSA.java,擴充套件於AbstractPasswordValidator,重寫其中密碼驗證方法encodePassword,先把輸入的密碼進行翻轉,然後再進行加密,返回密碼進行驗證,具體程式碼如下:
點選(此處)摺疊或開啟
-
package com.fr.privilege;
-
-
import com.fr.privilege.providers.dao.AbstractPasswordValidator;
-
public class TestPasswordValidatorRSA extends AbstractPasswordValidator{
-
//@Override
-
public String encodePassword( String clinetPassword) {
-
try {
-
//對密碼進行翻轉如輸入ab翻轉後為ba
-
StringBuffer sb = new StringBuffer();
-
sb.append(new String(clinetPassword));
-
String bb = sb.reverse().toString();
-
//進行加密
-
byte[] en_test = RSAUtil.encrypt(RSAUtil.getKeyPair().getPublic(),bb.getBytes());
-
//進行解密,如果資料庫裡面儲存的是加密碼,則此處不需要進行解密
-
byte[] de_test = RSAUtil.decrypt(RSAUtil.getKeyPair().getPrivate(),en_test);
-
//返回加密密碼
-
clinetPassword=new String(de_test);
-
} catch (Exception e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
return clinetPassword; //即獲取加密密碼再與資料庫密碼匹配。
-
}
-
-
@Override
-
public boolean validatePassword(String arg0, String arg1) {
-
// TODO Auto-generated method stub
-
return false;
-
}
-
-
- }
5、編譯類檔案
首先編譯RSAUtil.java類檔案在伺服器的D盤生成RSAKey.txt檔案,再編譯TestPasswordValidatorRSA.java類,把編譯後的class檔案放到專案工程web-inf/classes/com/fr/privilege資料夾中。
6、登陸Login.jsp頁面設定
客戶端請求到登入頁面,隨機生成一字串,此隨機字串作為金鑰加密密碼,如下程式碼:
點選(此處)摺疊或開啟
-
<%@page contentType="text/html" pageEncoding="UTF-8"%>
-
<%@page import="com.fr.privilege.providers.dao.RSAUtil"%>
-
<%!public String Testmo() {
-
String module = "";
-
try {
-
java.security.interfaces.RSAPublicKey rsap = (java.security.interfaces.RSAPublicKey) RSAUtil
-
.getKeyPair().getPublic();
-
module = rsap.getModulus().toString(16);
-
} catch (Exception e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
return module;
-
}%>
-
<%!public String Testem() {
-
String empoent = "";
-
try {
-
java.security.interfaces.RSAPublicKey rsap = (java.security.interfaces.RSAPublicKey) RSAUtil
-
.getKeyPair().getPublic();
-
empoent = rsap.getPublicExponent().toString(16);
-
} catch (Exception e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
return empoent;
-
}%>
-
<html>
-
<head>
-
<script type="text/javascript"
-
src="ReportServer?op=emb&resource=finereport.js"></script>
-
<script type="text/javascript" src="js/RSA.js"></script>
-
<script type="text/javascript" src="js/BigInt.js"></script>
-
<script type="text/javascript" src="js/Barrett.js"></script>
-
<script type="text/javascript">
-
function bodyRSA()
-
{
-
setMaxDigits(130);
-
var a = "<%=Testmo()%>";
-
var b = "<%=Testem()%>";
-
key = new RSAKeyPair(b,"",a);
-
}
-
function doSubmit() {
-
bodyRSA();
-
var username = FR.cjkEncode(document.getElementById("username").value); //獲取輸入的使用者名稱
-
var password = FR.cjkEncode(document.getElementById("password").value); //獲取輸入的引數
-
$.ajax({
-
url : "ReportServer?op=auth_login&fr_username=" + username + "&fr_password=" + password, //將使用者名稱和密碼傳送到報表認證地址op=auth_login
-
data : {__redirect__ : 'false'},
-
complete : function(res) {
-
var jo = FR.jsonDecode(res.responseText);
-
if(jo.url) {
-
window.location=jo.url+ "&_=" + new Date().getTime(); //認證成功跳轉頁面,因為ajax不支援重定向所有需要跳轉的設定
-
}
-
else{
-
alert("使用者名稱密碼錯誤!") //認證失敗
-
}
-
}
-
})
-
}
-
</script>
-
</head>
-
<body>
-
<p>
-
請登入
-
</p>
-
<form name="login" method="POST">
-
<p>
-
使用者名稱:
-
<input id="username" type="text" />
-
</p>
-
<p>
-
密 碼:
-
<input id="password" type="password" />
-
</p>
-
<input type="button" value="登入" onclick="doSubmit()" />
-
</form>
-
</body>
- </html>
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/21472864/viewspace-2123552/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- RSA加密演算法簡單介紹以及python實現加密演算法Python
- springmvc使用RSA演算法加密表單SpringMVC演算法加密
- RSA加密演算法加密演算法
- # RSA 公鑰加密演算法加密演算法
- PHP中RSA加密演算法的使用PHP加密演算法
- RSA演算法揭秘:加密世界的守護者演算法加密
- 最簡單的RSA加密demo,初學者的保姆級即抄即用!加密
- 26.RSA加密解密在Java專案中的簡單應用加密解密Java
- 非對稱加密演算法-RSA演算法加密演算法
- RSA演算法簡介演算法
- RSA加密加密
- 經典加密演算法入門-RSA加密演算法
- RSA非對稱加密演算法淺析加密演算法
- RSA加密遇到的坑加密
- javascript RSA 加密JavaScript加密
- 一個非常簡單的私有加密演算法加密演算法
- 第四篇:非對稱加密及RSA加密演算法加密演算法
- 簡單加密加密
- 秀爾演算法:破解RSA加密的“不滅神話”演算法加密
- 在SQL SERVER中實現RSA加密演算法SQLServer加密演算法
- Blowfish 加密演算法 Java 版簡單實現加密演算法Java
- RSA加密與解密加密解密
- C# RSA 加密C#加密
- RSA加密檔案加密
- "簡單"的加密簽名加密
- 一個簡單實用的 vb 加密/解密演算法 (轉)加密解密演算法
- php中aes加密和rsa加密的區別PHP加密
- Https中公私鑰加密演算法和其使用的RSA演算法分析HTTP加密演算法
- 非對稱加密演算法RSA中的公鑰和私鑰加密演算法
- php rsa長文加密解密PHP加密解密
- Android資料加密之Rsa加密Android加密
- 硬碟簡單加密. (轉)硬碟加密
- java中的使用RSA演算法進行公鑰加密私鑰解密 .Java演算法加密解密
- 非對稱加密技術- RSA演算法數學原理分析加密演算法
- drools的簡單入門案例
- Velocity案例(簡單的Hello)
- RSA 非對稱加密&解密加密解密
- 網易雲簡單案例