Rsa非对称性算法-springboot实现
使用这个算法增强表单提交的安全性。
原理相当简单如下:
假设后端a和前端b是两个人,a有两把钥匙(俗称:公钥和秘钥,他们是一对的缺一不可),a把私钥留给自己,公钥给了b,b可以使用公钥对账号密码加密。但是b无法解密因为私钥在a的手上,b把加密后的东西给a。a用私钥解密。这就完成了Rsa的实现原理。
1、引入maven依赖替换Base64
<!-- 替换sun.misc.BASE64Encoder Rsa非对称性算法-->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
2、工具类RsaUtils
package com.su.main.utils;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* RSA加解密工具类,实现公钥加密私钥解密和私钥解密公钥解密
*/
public class RSAUtils {
private static final String src = "123abc";
public static void main(String[] args) throws Exception {
System.out.println("\n");
RSAKeyPair keyPair = generateKeyPair();
System.out.println("公钥:" + keyPair.getPublicKey());
System.out.println("私钥:" + keyPair.getPrivateKey());
System.out.println("\n");
test1(keyPair, src);
System.out.println("\n");
test2(keyPair, src);
System.out.println("\n");
}
/**
* 公钥加密私钥解密
*/
private static void test1(RSAKeyPair keyPair, String source) throws Exception {
System.out.println("***************** 公钥加密私钥解密开始 *****************");
String text1 = encryptByPublicKey(keyPair.getPublicKey(), source);
String text2 = decryptByPrivateKey(keyPair.getPrivateKey(), text1);
System.out.println("加密前:" + source);
System.out.println("加密后:" + text1);
System.out.println("解密后:" + text2);
if (source.equals(text2)) {
System.out.println("解密字符串和原始字符串一致,解密成功");
} else {
System.out.println("解密字符串和原始字符串不一致,解密失败");
}
System.out.println("***************** 公钥加密私钥解密结束 *****************");
}
/**
* 私钥加密公钥解密
*
* @throws Exception
*/
private static void test2(RSAKeyPair keyPair, String source) throws Exception {
System.out.println("***************** 私钥加密公钥解密开始 *****************");
String text1 = encryptByPrivateKey(keyPair.getPrivateKey(), source);
String text2 = decryptByPublicKey(keyPair.getPublicKey(), text1);
System.out.println("加密前:" + source);
System.out.println("加密后:" + text1);
System.out.println("解密后:" + text2);
if (source.equals(text2)) {
System.out.println("解密字符串和原始字符串一致,解密成功");
} else {
System.out.println("解密字符串和原始字符串不一致,解密失败");
}
System.out.println("***************** 私钥加密公钥解密结束 *****************");
}
/**
* 公钥解密
*
* @param publicKeyText
* @param text
* @return
* @throws Exception
*/
public static String decryptByPublicKey(String publicKeyText, String text) throws Exception {
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
return new String(result);
}
/**
* 私钥加密
*
* @param privateKeyText
* @param text
* @return
* @throws Exception
*/
public static String encryptByPrivateKey(String privateKeyText, String text) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(text.getBytes());
return Base64.encodeBase64String(result);
}
/**
* 私钥解密
*
* @param privateKeyText
* @param text
* @return
* @throws Exception
*/
public static String decryptByPrivateKey(String privateKeyText, String text) throws Exception {
PKCS8EncodedKeySpec pkcs8EncodedKeySpec5 = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
return new String(result);
}
/**
* 公钥加密
*
* @param publicKeyText
* @param text
* @return
*/
public static String encryptByPublicKey(String publicKeyText, String text) throws Exception {
X509EncodedKeySpec x509EncodedKeySpec2 = new X509EncodedKeySpec(Base64.decodeBase64(publicKeyText));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] result = cipher.doFinal(text.getBytes());
return Base64.encodeBase64String(result);
}
/**
* 构建RSA密钥对
*
* @return
* @throws NoSuchAlgorithmException
*/
public static RSAKeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey rsaPublicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
String publicKeyString = Base64.encodeBase64String(rsaPublicKey.getEncoded());
String privateKeyString = Base64.encodeBase64String(rsaPrivateKey.getEncoded());
RSAKeyPair rsaKeyPair = new RSAKeyPair(publicKeyString, privateKeyString);
return rsaKeyPair;
}
/**
* RSA密钥对对象
*/
public static class RSAKeyPair {
private String publicKey;
private String privateKey;
public RSAKeyPair(String publicKey, String privateKey) {
this.publicKey = publicKey;
this.privateKey = privateKey;
}
public String getPublicKey() {
return publicKey;
}
public String getPrivateKey() {
return privateKey;
}
}
}
3、controller 的调用
package com.su.main.controller;
import com.su.main.utils.RSAUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
import java.security.NoSuchAlgorithmException;
import static com.su.main.utils.RSAUtils.generateKeyPair;
/**
* TODO
*
* @author Administrator
* @version 1.0
* @date 2020/10/28 17:44
*/
@Controller
public class RsaTest {
@RequestMapping("/rsa")
public String toRsaTest(){
return "rsaTest";
}
@RequestMapping("/getPublicKey")
@ResponseBody
public String buildKeyPair(HttpSession session) throws NoSuchAlgorithmException {
RSAUtils.RSAKeyPair rsaKeyPair = generateKeyPair();
//如果这个session存在,先删除后添加
if(session.getAttribute("privateKeySu")!=null){
session.removeAttribute("privateKeySu");
session.setAttribute("privateKeySu",rsaKeyPair.getPrivateKey());
System.out.println("privateKeySu:"+rsaKeyPair.getPrivateKey());
}else {
session.setAttribute("privateKeySu",rsaKeyPair.getPrivateKey());
System.out.println("privateKeySu:"+rsaKeyPair.getPrivateKey());
}
String publicKey = rsaKeyPair.getPublicKey();
System.out.println("publicKey:"+publicKey);
//返回公钥
return rsaKeyPair.getPublicKey();
}
@RequestMapping("/aaa")
@ResponseBody
public String Login(String name, HttpSession session) throws Exception {
String comeBackMsg;
//获得秘钥对
if(session.getAttribute("privateKeySu")!=null){
String privateKey = (String) session.getAttribute("privateKeySu");
System.out.println("privateKey:"+privateKey);
//获取私钥解密方法
RSAUtils rsaUtils = new RSAUtils();
String changeName = rsaUtils.decryptByPrivateKey(privateKey, name);
comeBackMsg = "私钥解开了!解开为:"+changeName;
}else{
comeBackMsg = "抱歉你没有权限";
}
return comeBackMsg;
}
}
4、前端页面设计和js的导入
前端页面设计:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
账号:<input type="text" id="name1" name="name1" oninput="getPublicKey(this)" >
</div>
<div>
密码:<input type="password" id="pwd1" name="pwd1">
</div>
<div>
<button type="button" name="aaa" onclick="clickA(this)">aaa</button>
</div>
<form action="">
<input type="hidden" id="name2" name="name2">
<input type="hidden" id="pwd2" name="pwd2">
<input type="hidden" id="publicKey" name="publicKey">
<input type="submit" value="提交">
</form>
<script type="text/javascript" src="/Rsa/js/jquery.min-2.1.4.js"></script>
<!--Rsa非对称性算法前端js-->
<script type="text/javascript" src="/Rsa/js/jsencrypt.min.js"></script>
<script>
//oninput 当表单的value值改变是触发,但js改变value的值不会触发
function getPublicKey(e) {
// 3-Url参数加密类
//公钥加密
var encrypt = new JSEncrypt();
//获取公钥
$.post(
"/getPublicKey",
function (r) {
//获取公钥
console.log(r);
let pkey = r;
console.log(pkey);
$("#publicKey").val(pkey);
//公匙加密
encrypt.setPublicKey(pkey);
let name1 = $("#name1").val();
console.log("name1加密前:"+name1);
let name2;
name2 = encrypt.encrypt(JSON.stringify(name1));
console.log("name2加密后:"+name2);
$("#name2").val(name2);
}
);
}
function clickA() {
//获取加密后的密码上交解密
if($("#name2").val()!=null){
let name2 = $("#name2").val();
console.log(name2);
$.post(
"/aaa",
{
name : name2
},
function (r) {
alert(r);
}
);
}else {
alert("请输入你的账号在试试点击我!");
}
}
</script>
</body>
</html>
js的引入(需要jQuery和jsencrypt.min.js(前端Rsa的库))
这两个js自行去网站下载即可啦,jQuery要求不高,其他版本也可以,jsencrypt.min.js,百度一下在别人项目里面拿也可以
粟德桡 QQ:648713624