1、创建RASUtils
package com.demo.springboot.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class RSAUtils {
protected static final Log log = LogFactory.getLog(RSAUtils.class);
private static String KEY_RSA_TYPE = "RSA";
private static String KEY_RSA_TYPE_ALL = "RSA/ECB/PKCS1Padding";
private static int KEY_SIZE = 1024;//JDK方式RSA加密最大只有1024位
private static int ENCODE_PART_SIZE = KEY_SIZE/8;
public static final String PUBLIC_KEY_NAME = "public";
public static final String PRIVATE_KEY_NAME = "private";
/**
* 创建公钥秘钥
* @return
*/
public static Map createRSAKeys(){
Map keyPairMap = new HashMap<>();//里面存放公私秘钥的Base64位加密
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_RSA_TYPE);
keyPairGenerator.initialize(KEY_SIZE,new SecureRandom());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
//获取公钥秘钥
String publicKeyValue = Base64.encodeBase64String(keyPair.getPublic().getEncoded());
String privateKeyValue = Base64.encodeBase64String(keyPair.getPrivate().getEncoded());
//存入公钥秘钥,以便以后获取
keyPairMap.put(PUBLIC_KEY_NAME,publicKeyValue);
keyPairMap.put(PRIVATE_KEY_NAME,privateKeyValue);
} catch (NoSuchAlgorithmException e) {
log.error("当前JDK版本没找到RSA加密算法!");
e.printStackTrace();
}
return keyPairMap;
}
/**
* 公钥加密
* 描述:
* 1字节 = 8位;
* 最大加密长度如 1024位私钥时,最大加密长度为 128-11 = 117字节,不管多长数据,加密出来都是 128 字节长度。
* @param sourceStr
* @param publicKeyBase64Str
* @return
*/
public static String encode(String sourceStr,String publicKeyBase64Str){
byte [] publicBytes = Base64.decodeBase64(publicKeyBase64Str);
//公钥加密
X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicBytes);
List alreadyEncodeListData = new LinkedList<>();
int maxEncodeSize = ENCODE_PART_SIZE - 11;
String encodeBase64Result = null;
try {
KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE);
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE_ALL);
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
byte[] sourceBytes = sourceStr.getBytes("utf-8");
int sourceLen = sourceBytes.length;
for(int i=0;i maxEncodeSize){
tempLen = maxEncodeSize;
}
byte[] tempBytes = new byte[tempLen];//待加密分段数据
System.arraycopy(sourceBytes,i,tempBytes,0,tempLen);
byte[] tempAlreadyEncodeData = cipher.doFinal(tempBytes);
alreadyEncodeListData.add(tempAlreadyEncodeData);
}
int partLen = alreadyEncodeListData.size();//加密次数
int allEncodeLen = partLen * ENCODE_PART_SIZE;
byte[] encodeData = new byte[allEncodeLen];//存放所有RSA分段加密数据
for (int i = 0; i < partLen; i++) {
byte[] tempByteList = alreadyEncodeListData.get(i);
System.arraycopy(tempByteList,0,encodeData,i*ENCODE_PART_SIZE,ENCODE_PART_SIZE);
}
encodeBase64Result = Base64.encodeBase64String(encodeData);
} catch (Exception e) {
e.printStackTrace();
}
return encodeBase64Result;
}
/**
* 私钥解密
* @param sourceBase64RSA
* @param privateKeyBase64Str
*/
public static String decode(String sourceBase64RSA,String privateKeyBase64Str){
byte[] privateBytes = Base64.decodeBase64(privateKeyBase64Str);
byte[] encodeSource = Base64.decodeBase64(sourceBase64RSA);
int encodePartLen = encodeSource.length/ENCODE_PART_SIZE;
List decodeListData = new LinkedList<>();//所有解密数据
String decodeStrResult = null;
//私钥解密
PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(privateBytes);
try {
KeyFactory keyFactory = KeyFactory.getInstance(KEY_RSA_TYPE);
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
Cipher cipher = Cipher.getInstance(KEY_RSA_TYPE_ALL);
cipher.init(Cipher.DECRYPT_MODE,privateKey);
int allDecodeByteLen = 0;//初始化所有被解密数据长度
for (int i = 0; i < encodePartLen; i++) {
byte[] tempEncodedData = new byte[ENCODE_PART_SIZE];
System.arraycopy(encodeSource,i*ENCODE_PART_SIZE,tempEncodedData,0,ENCODE_PART_SIZE);
byte[] decodePartData = cipher.doFinal(tempEncodedData);
decodeListData.add(decodePartData);
allDecodeByteLen += decodePartData.length;
}
byte [] decodeResultBytes = new byte[allDecodeByteLen];
for (int i = 0,curPosition = 0; i < encodePartLen; i++) {
byte[] tempSorceBytes = decodeListData.get(i);
int tempSourceBytesLen = tempSorceBytes.length;
System.arraycopy(tempSorceBytes,0,decodeResultBytes,curPosition,tempSourceBytesLen);
curPosition += tempSourceBytesLen;
}
decodeStrResult = new String(decodeResultBytes,"UTF-8");
}catch (Exception e){
e.printStackTrace();
}
return decodeStrResult;
}
}
2、生成公钥和私钥
package com.demo.springboot;
import com.demo.springboot.util.RSAUtils;
import java.util.Map;
/**
* @author zhanghongkai
* @version 1.0
* @Classname Test5
* @Description Test5
* @Date 2020/12/25 10:24
*/
public class Test5 {
public static void main(String[] args) {
Map rsaKeys = RSAUtils.createRSAKeys();
String publicKey = rsaKeys.get(RSAUtils.PUBLIC_KEY_NAME);
System.out.println("publicKey:"+ publicKey);
String privateKey = rsaKeys.get(RSAUtils.PRIVATE_KEY_NAME);
System.out.println("privateKey:"+ privateKey);
}
}
输出结果为:
publicKey:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtY9zORw7e5CH45W5yyxtzzPqsCgHZbNV7usrWaT5enn+XUSyw1i21Gy4Jf26uHT5I2a8mdZ7gNfewFAJNF9wVFmaOUShaxaO6xlTrDN3VRSCjQNLDZhaTBfKnVtbQ3nrR2Tp8CE4fgydZFnLm9O+saDYqspRFfIfIOhxXhQRU3wIDAQAB
privateKey:MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK1j3M5HDt7kIfjlbnLLG3PM+qwKAdls1Xu6ytZpPl6ef5dRLLDWLbUbLgl/bq4dPkjZryZ1nuA197AUAk0X3BUWZo5RKFrFo7rGVOsM3dVFIKNA0sNmFpMF8qdW1tDeetHZOnwITh+DJ1kWcub076xoNiqylEV8h8g6HFeFBFTfAgMBAAECgYEAlg4fkJFkaDdMw0djb4shBfW2Vt8OPKl4k+zTD/3i0SYgS8cfgybIRbzw+Z1EHwEF3yws7X7LcUSjR8n5N9jXSCRKxEvCksczGM80qJMBypgGh4DzKTlm9ScnbnmYlUYf+cSz53EsoktQLtCqP08tGhYZr2Qe2lJlrgKnSuIrNbkCQQDy+B3XMirkAgveGWD26ofMTcv5ZDw/KyiF69QCGQ0y5EP21esUxXwmVgwbtOx7Q2Ox0jPP6HkczWYCzCsNBJ0dAkEAtrBy23PLbUeSqyEc8D8Psvs0OekQOoogZjJtzj5eFCCZjbWd8PJ0KMAoRnZtqCqGWGP3eRwKntHW1VtaAA/lKwJBAJqdjBfKhALOzpCKo+rdOoenpjrRL4mfRE1c0nB3Uq/lFN76KHvyZFvc/B2Rl7+lFccuFeyjapcKmnUDSg4htn0CQHMTnqYBwMhrZ0YIq7Ph5T+24OUBnEljrJjzdxuNSbGf/1m2Z3DZKLZqpHQOMXDWqJ2RCtftA/ua7pqi2oRjftUCQDVN7DP6Nk/wFiyXwGKDez6jWpjpU5DKak+d0zD462EadQCMDEyHBpgtqPBpMMvVMGXsQtyUiHDOJzooiEEPRho=
3、将公钥和私钥配置到springboot的配置文件application.properties中
publicKey=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCtY9zORw7e5CH45W5yyxtzzPqsCgHZbNV7usrWaT5enn+XUSyw1i21Gy4Jf26uHT5I2a8mdZ7gNfewFAJNF9wVFmaOUShaxaO6xlTrDN3VRSCjQNLDZhaTBfKnVtbQ3nrR2Tp8CE4fgydZFnLm9O+saDYqspRFfIfIOhxXhQRU3wIDAQAB privateKey=MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK1j3M5HDt7kIfjlbnLLG3PM+qwKAdls1Xu6ytZpPl6ef5dRLLDWLbUbLgl/bq4dPkjZryZ1nuA197AUAk0X3BUWZo5RKFrFo7rGVOsM3dVFIKNA0sNmFpMF8qdW1tDeetHZOnwITh+DJ1kWcub076xoNiqylEV8h8g6HFeFBFTfAgMBAAECgYEAlg4fkJFkaDdMw0djb4shBfW2Vt8OPKl4k+zTD/3i0SYgS8cfgybIRbzw+Z1EHwEF3yws7X7LcUSjR8n5N9jXSCRKxEvCksczGM80qJMBypgGh4DzKTlm9ScnbnmYlUYf+cSz53EsoktQLtCqP08tGhYZr2Qe2lJlrgKnSuIrNbkCQQDy+B3XMirkAgveGWD26ofMTcv5ZDw/KyiF69QCGQ0y5EP21esUxXwmVgwbtOx7Q2Ox0jPP6HkczWYCzCsNBJ0dAkEAtrBy23PLbUeSqyEc8D8Psvs0OekQOoogZjJtzj5eFCCZjbWd8PJ0KMAoRnZtqCqGWGP3eRwKntHW1VtaAA/lKwJBAJqdjBfKhALOzpCKo+rdOoenpjrRL4mfRE1c0nB3Uq/lFN76KHvyZFvc/B2Rl7+lFccuFeyjapcKmnUDSg4htn0CQHMTnqYBwMhrZ0YIq7Ph5T+24OUBnEljrJjzdxuNSbGf/1m2Z3DZKLZqpHQOMXDWqJ2RCtftA/ua7pqi2oRjftUCQDVN7DP6Nk/wFiyXwGKDez6jWpjpU5DKak+d0zD462EadQCMDEyHBpgtqPBpMMvVMGXsQtyUiHDOJzooiEEPRho=
4、编写登录控制器,主要是登录解密方法和获取公钥方法
package com.demo.springboot.controller;
import com.demo.springboot.util.RSAUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @author zhanghongkai
* @version 1.0
* @Classname LoginController
* @Description LoginController
* @Date 2020/12/25 10:30
*/
@Controller
public class LoginController {
@Value("${publicKey}")
private String publicKey;
@Value("${privateKey}")
private String privateKey;
@RequestMapping("getPublicKey")
@ResponseBody
public String getPublicKey(){
return this.publicKey;
}
@RequestMapping("login")
@ResponseBody
public String login(@RequestBody User user){
String password = user.getPassword();
System.out.println(password);
password = RSAUtils.decode(password,this.privateKey);
System.out.println(password);
return "登录成功";
}
}
5、前端引入jsencrypt,我这里使用在vue中yinru
npm install jsencrypt --save
6、使用jsencrypt加密并发送密文到后台
123
7、后台解密密文,输出为:
ceq7LtFesQYyi/zR5Rr5P3uBHLmFUVgwx8iOgA6paOmREu9xXDwncGQveGLNHmbM5dNBCo4ErDlP5uUNsLvDCq1EwG63PaNzKYPMvs6BByj8isg9YT9l7MqY9UuC9bSOahFYeAtJ5lESX26zWs55WdRYvNcFv3PCExDJys6bFHo=
123456
解密成功