1.RSA简介
RSA是一个非对称加密系统,目前是很安全的一个加密算法,在公开密钥加密和电子商业中RSA被广泛使用,是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。
2.RSA与前段交互遇到的坑
(1) 你这边生成的公钥给前端传输的过程中或者是前段加密好的密文给后台传输的过程中,由于是http协议不能传输特殊符号,会被http提交换成空格,导致加密的密文不被后台解析,或者解析出来为空字符串。
(2)由于生成的公钥携带换行,在传输的过程中加入了'\n\r'所以导致你的公钥和密文格式不正确。
3.解决方案
(1) 前后端都用base64编码传输
(2)java将 '\n\r' 替换为 ‘’
4.流程
先是后台java提供前端一个公钥 - 》 前端利用公钥加密 -》 后台用密钥解密
5.java RSA代码
package com.uximt.util.encryption;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.*;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;
public class RSAEncryption {
protected static final Logger log = LoggerFactory.getLogger(RSAEncryption.class);
private static String KEY_RSA_TYPE = "RSA";
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<String,String> createRSAKeys(){
Map<String,String> 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<byte[]> 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);
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
byte[] sourceBytes = sourceStr.getBytes("utf-8");
int sourceLen = sourceBytes.length;
for(int i=0;i<sourceLen;i+=maxEncodeSize){
int curPosition = sourceLen - i;
int tempLen = curPosition;
if(curPosition > 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<byte[]> 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);
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;
}
public static void main(String[] args) {
Map<String,String> map = createRSAKeys();
//公钥
String publicKey = map.get(PUBLIC_KEY_NAME);
//私钥
String privateKey = map.get(PRIVATE_KEY_NAME);
String message = "abc";
//加密
String m = encode(message,publicKey);
System.out.println(m);
String m3 = "Kvy/Ms5ZgeI5W6i7bJ9U9PGkcyVw63VTdkfLfYUoqrGuuEMtIIw8yx/sS2jBMPaq ycEOjJCI8/ZTvGeG66Mt/UNh00O/XoAZP/4vgEdRqrMEs6I9QrhujUCOxCgnBe43HT9DUiUq6IGkOjGzQiFV9dwcj7yu6P26nsACjxFqiQ=";
String m5 = "Kvy/Ms5ZgeI5W6i7bJ9U9PGkcyVw63VTdkfLfYUoqrGuuEMtIIw8yx/sS2jBMPaq+ycEOjJCI8/ZTvGeG66Mt/UNh00O/XoAZP/4vgEdRqrMEs6I9QrhujUCOxCgnBe43HT9DUiUq6IGkOjGzQiFV9dwcj7yu6P26nsACjxFqiQ=";
String m4 = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOeWd/2vtaTroeE5tsLfgsksNcf8xgIn52QzefU72X+IyDRVl11oZ4BhJiSgwFri4s+zkY60l58fiHlNlSFIiOpwYuaEyBlHyA7uMfc9w/8wfXhYv7BhIDzH7+qN1WwJnuQo3+QPz4L5ZmA0ysGfBYHXLkHlB0cHmIn0QaFZSGT/AgMBAAECgYA0eMpNJ3+vk1gFUO9Q7hWTATpaSrKOkH4EHQm3/8yC8fnyqaX3Gw3Ab8KVr/qFXTzotJX5UH++JQXl/icY+HdUwLInSA2uFu7vwPvCR2kvlxf6sGPdrX8OgHAn/YKelSmOyjxDE6P4QYOe6Peuek4fFrgmCbNfSynQExzoYUGFKQJBAPdNxfbtB8SmBnryh7e316lpcTMpEryICn2AKrKy4yLSSwLc/Q4jNtQdLIZrp9L4BHXe+hlluP9/+iuEROBEaxUCQQDvuzhF6bhaPRsE76BLE/JsRvEowD/vpVD4Rom10QnlicsP/qN+2nxbsr07DweOofkU2GD8afAehgzYkQczJITDAkAYTCziGOHFgWZrl/6bn1VyEKkNlMCBg4A8WmZXjlngpva1vk6in/UYHBGu107y3Glbx1+dNTBa8hD7S5CU1EQNAkANbpgAks/ZfoL9C9AXZM64cmEgv2TVsJWQ06LzpPrA+a9+/e17NhKxsJoZrQXnX/vsxxLoEad6jlg56iZVHz6xAkBfHl52NHydXDAIt3IopXVenetyjrhcWRWQciw4LBZhgeKKmHsZXxq9JLYTPyStr7Ovic0aLgSkSOznm4PUwU1l";
//解密
String m1 = decode(m5,m4);
System.out.println(m1);
}
}
6.java Base64
package com.uximt.util.encryption;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
public class Base64Until {
public static void main(String[] args) throws Exception {
String str = "青锋剑,偃月刀";
String a = encryptBASE64(str.getBytes());
System.out.println(a);
byte[] b = decryptBASE64(a);
System.out.println(new String(b));
}
/**
* BASE64解密
* @throws Exception
*/
public static byte[] decryptBASE64(String key) throws Exception {
return (new BASE64Decoder()).decodeBuffer(key);
}
/**
* BASE64加密
*/
public static String encryptBASE64(byte[] key) throws Exception {
return (new BASE64Encoder()).encodeBuffer(key);
}
}
7.前端vue加密
1、安装
npm install --save jsencrypt
2、在main.js 引入
import JsEncrypt from 'jsencrypt'
Vue.prototype.jsEncrypt = JsEncrypt; 3、使用minxin封装,其中公钥和私钥,由后台提供 export default { name:'RSA-encrypt', methods:{ //加密方法 encrypt(pas){ //实例化jsEncrypt对象 let jse = new this.jsEncrypt;
//设置公钥
jse.setPublicKey('公钥');
//加密
return jse.encrypt(pas);
},