解决Message too long for RSA报错
在这里我们有两种选择方案,jsencrypt和 encryptlong
使用后者的原因是因为jsencrypt的加密长度有限制,不过encryptlong本身也是有bug,有事又会问题,加密后解析不出来,可能是我的个人原因
这次我主要就说明jsencrypt如果能加密比较长的数据
1、先下载 encrypt
npm i encrypt / yarn add encrypt
2、复制代码
用来给他重新定义一方法使用
加密
const b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const b64pad = "=";
JSEncrypt.prototype.encryptLong2 = function (string) {
const k = this.getKey();
try {
const lt = "";
let ct = "";
//RSA每次加密117bytes,需要辅助方法判断字符串截取位置
//1.获取字符串截取点
const bytes = new Array();
bytes.push(0);
let byteNo = 0;
let len, c;
// eslint-disable-next-line prefer-const
len = string.length;
let temp = 0;
// eslint-disable-next-line no-var
for (var i = 0; i < len; i++) {
c = string.charCodeAt(i);
if (c >= 0x010000 && c <= 0x10FFFF) {
byteNo += 4;
} else if (c >= 0x000800 && c <= 0x00FFFF) {
byteNo += 3;
} else if (c >= 0x000080 && c <= 0x0007FF) {
byteNo += 2;
} else {
byteNo += 1;
}
if ((byteNo % 117) >= 114 || (byteNo % 117) == 0) {
if (byteNo - temp >= 114) {
bytes.push(i);
temp = byteNo;
}
}
}
//2.截取字符串并分段加密
if (bytes.length > 1) {
// eslint-disable-next-line no-var
for (var i = 0; i < bytes.length - 1; i++) {
// eslint-disable-next-line no-var
var str;
if (i == 0) {
str = string.substring(0, bytes[i + 1] + 1);
} else {
str = string.substring(bytes[i] + 1, bytes[i + 1] + 1);
}
const t1 = k.encrypt(str);
ct += addPreZero(t1, 256);
}
;
if (bytes[bytes.length - 1] != string.length - 1) {
const lastStr = string.substring(bytes[bytes.length - 1] + 1);
const rsaStr = k.encrypt(lastStr)
ct += addPreZero(rsaStr, 256);
}
//console.log("加密完的数据:"+ct);
return hex2b64(ct);
}
const t = k.encrypt(string);
const y = hex2b64(t);
return y;
} catch (ex) {
return false;
}
}
解密,(注:前端基本用不着就不用引了)
JSEncrypt.prototype.decryptLong2 = function (string) {
const k = this.getKey();
// var maxLength = ((k.n.bitLength()+7)>>3);
const MAX_DECRYPT_BLOCK = 128;
try {
let ct = "";
let t1;
let bufTmp;
let hexTmp;
const str = b64tohex(string);
const buf = hexToBytes(str);
const inputLen = buf.length;
//开始长度
let offSet = 0;
//结束长度
let endOffSet = MAX_DECRYPT_BLOCK;
//分段解密
console.log(inputLen + "----" + offSet)
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
bufTmp = buf.slice(offSet, endOffSet);
hexTmp = bytesToHex(bufTmp);
t1 = k.decrypt(hexTmp);
ct += t1;
} else {
bufTmp = buf.slice(offSet, inputLen);
hexTmp = bytesToHex(bufTmp);
t1 = k.decrypt(hexTmp);
ct += t1;
}
offSet += MAX_DECRYPT_BLOCK;
endOffSet += MAX_DECRYPT_BLOCK;
}
return ct;
} catch (ex) {
return false;
}
}
3、需要引入的方法
这些都是编码过程中需要使用的一些方法
// 在JsEncrypt原型上写了分段加密方法 encryptLong 使用时替换encrypt方法即可
function hex2b64(h) {
let i;
let c;
let ret = "";
for (i = 0; i + 3 <= h.length; i += 3) {
c = parseInt(h.substring(i, i + 3), 16);
ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
}
if (i + 1 == h.length) {
c = parseInt(h.substring(i, i + 1), 16);
ret += b64map.charAt(c << 2);
}
else if (i + 2 == h.length) {
c = parseInt(h.substring(i, i + 2), 16);
ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
}
while ((ret.length & 3) > 0) ret += b64pad;
return ret;
}
function hexToBytes(hex: string) {
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
}
function bytesToHex(bytes: string | any[]) {
for (var hex = [], i = 0; i < bytes.length; i++) {
hex.push((bytes[i] >>> 4).toString(16));
hex.push((bytes[i] & 0xF).toString(16));
}
return hex.join("");
}
function b64tohex(str: string) {
for (var i = 0, bin = atob(str.replace(/[ \r\n]+$/, "")), hex = []; i < bin.length; ++i) {
var tmp = bin.charCodeAt(i).toString(16);
if (tmp.length === 1) tmp = "0" + tmp;
hex[hex.length] = tmp;
}
return hex.join("");
}
function addPreZero(num, length) {
var t = (num + '').length,
s = '';
for (var i = 0; i < length - t; i++) {
s += '0';
}
return s + num;
}
三、代码中使用
尽可能两个都设置,这个是我封装的方法
const encryptLong = (Encstr: string) => {
const encrypt = new JSEncrypt();
encrypt.setPublicKey(PUBLIC_KEY); // 你的公钥
encrypt.setPrivateKey(PRIVATE_KEY) // 你的私钥
const data = encrypt.encryptLong2(Encstr);
return data;
}
使用过程
const data = {
"id": "7ca6a4981a28cf3734343434242710c2c",
"name": "admin",
"userName": "admin",
"phone": "13211222222222",
"sex": 0,
"roleId": "32423asdsad4234234",
"isDriver": 0,
"department": "体育部",
"status": 0,
"reset": 1,
"remark": "你好呀你是哪里人呢",
"companyId": "060b8b4fd3ef48f589727db415571427"
}
const strJSON= JSON.stringify(data); // 将jso转为字符串
const result = encryptLong(strJSON); // 调用封装的方法
//加密结果 后端也要使用分段解密
ZHOd7cj0zc0Iaw1hqOH4TFGLxhWGpaqPqWQ+jTVUnosAPr85LAuFXRxZpD6czT0eh96XhRxWgZIQxsqkXEaOPKk1LKWHahrkf1IvtyBO1Uf8GEVkGMPcqj27Qx/HfrsZaUoV0awXVP7dcu/4HDLyF50Is1H7VmUULWmCHd1xxJpvTS5B8yptitanEqDL8pf0qx1dF7AHLNojYw9xusBfWCp21BOyrzjprKtW2ZRQeRmmxURRpPtqoJdOU0PwI/ZbPTtwK26nlLwlzIOkqz5wx9qyjm7ub38sulZP2BGZfv+3EjatVS7XqzxmvcQLPwIU/adoUVFg74XZbg6UGpYi0EXZkqVz03JaG190PxwdjN6ds0gU9WTvSPZAxd7ce7M+LjE/SwP6czAePgG9kHmD3KXJTJ8Ja8PtZUPDnw2Ar8LJL7oyDrTAVLO+IbozO6YMXkVgeZytJ4TwZBfHcSDECfpp+ge1atHtukgKz3Q2O3IO2AN6Cm6zQHTRv...
基本上就是如此使用
完美使用,完结撒花