RSA加密:web前端用户名密码加密以及java后端解密
编写加解密公共方法类RSAUtils
package com.zhizhenkeji.administrative.common.utils;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPublicKey;
public class RSAUtil {
private static final KeyPair keyPair = initKey();
private static KeyPair initKey() {
try {
Provider provider =new BouncyCastleProvider();
Security.addProvider(provider);
SecureRandom random = new SecureRandom();
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider);
generator.initialize(1024,random);
return generator.generateKeyPair();
} catch(Exception e) {
throw new RuntimeException(e);
}
}
public static String generateBase64PublicKey() {
PublicKey publicKey = (RSAPublicKey)keyPair.getPublic();
return new String(Base64.encodeBase64(publicKey.getEncoded()));
}
public static String decryptBase64(String string) {
return new String(decrypt(Base64.decodeBase64(string.getBytes())));
}
private static byte[] decrypt(byte[] byteArray) {
try {
Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
Security.addProvider(provider);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
PrivateKey privateKey = keyPair.getPrivate();
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] plainText = cipher.doFinal(byteArray);
return plainText;
} catch(Exception e) {
throw new RuntimeException(e);
}
}
}
后端生成公钥方法
@RequestMapping(value = "/xxx", method = RequestMethod.GET)
public JsonResult RSAKey(){
String publicKey = RSAUtil.generateBase64PublicKey();
return JsonResult.getSuccessJsonResult("publicKey",publicKey);
}
前端在向后台发起登录请求之前,先请求后台获取公钥的方法,然后经过加密之后再发起登录请求。
form.on('submit(signin)', function (data) {
// 先获取公钥,然后提交用户名和密码给后台
$.ajax({
url: "获取公钥的请求路径",
type: "GET",
dataType: "json",
async: false,
success: function (res) {
var encrypt = new JSEncrypt();//创建加密实例
if (res) {
// console.log(res.data);
var publicKey = null;
publicKey = res.data;//后端传回来的公钥
var username;
var password;
encrypt.setPublicKey(publicKey);// 初始化公钥
username = encrypt.encrypt(data.field.username.trim());// 加密用户名数据
password = encrypt.encrypt(data.field.password.trim());// 加密密码数据
// console.log(username);
// console.log(password);
// 提交加密后的用户名和密码给后台
$.ajax({
url: "登录请求路径",
data: {
"username": username,
"password": password
},
type: "GET",
dataType: "json",
success: function (result) {
if (result.rtnCode == "000000") {
layer.alert("登录成功!")
// window.top.location.href = './index.html';
} else {
layer.alert(result.data.rtnMsg);
}
},
error: function (e) {
layer.alert("登录失败!");
}
});
};
}
});
});
前端代码需引入jsencrypt.min.js文件,这个js文件网上一大堆,随便搜搜就有。
<script src="http://passport.cnblogs.com/scripts/jsencrypt.min.js"></script>
后端接收前端传输过来的密文进行解密
username = RSAUtil.decryptBase64(username.trim());
password = RSAUtil.decryptBase64(password.trim());
后端代码需要导入的依赖jar
需要导入的依赖jar
<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk16 -->
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
注意:
Http请求特殊符号变空格的问题:参数经过Base64编码会有’+'加号,后端request.request.getParameter(name)获取的值中+号变成了空格。
解决办法:request.getParameter(nms).replaceAll(" ", “+”)