最近公司要對前端請求數據進行RSA加密,所以在網上找了一些博客,並下載了一些demo測試了下,但不太樂觀。目前網上的絕大部分博客對超長字符串(117位以上)加密不太支持或者支持的不太好。即使是付費的。。。
所以我在網上的demo基礎上,請教了下算法同學,經過測試,發現轉化位二進制后,若第一位為0則會出現位數不夠,同時導致解密失敗。所以在原來的基礎上進行了改進。
一、引入js文件(下載地址:這里)
js/jsencrypt.min.js
二、生產公私鑰
這一步的話,可以直接在網上找在線生成。
三、定義方法
這里需要重新定義兩個方法:超長加密(encryptLong2)、超長解密(decryptLong2)
let encrypt = new JSEncrypt(); // 聲明變量
let b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
let b64pad = "=";
JSEncrypt.prototype.encryptLong2 = function (string) {
var k = this.getKey();
try {
var lt = "";
var ct = "";
//RSA每次加密117bytes,需要輔助方法判斷字符串截取位置
//1.獲取字符串截取點
var bytes = new Array();
bytes.push(0);
var byteNo = 0;
var len, c;
len = string.length;
var temp = 0;
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) {
for (var i = 0; i < bytes.length - 1; i++) {
var str;
if (i == 0) {
str = string.substring(0, bytes[i + 1] + 1);
} else {
str = string.substring(bytes[i] + 1, bytes[i + 1] + 1);
}
var t1 = k.encrypt(str);
ct += addPreZero(t1,256);
}
;
if (bytes[bytes.length - 1] != string.length - 1) {
var lastStr = string.substring(bytes[bytes.length - 1] + 1);
let rsaStr = k.encrypt(lastStr)
ct += addPreZero(rsaStr,256);
}
//console.log("加密完的數據:"+ct);
return hex2b64(ct);
}
var t = k.encrypt(string);
var y = hex2b64(t);
return y;
} catch (ex) {
return false;
}
}
JSEncrypt.prototype.decryptLong2 = function (string) {
var k = this.getKey();
// var maxLength = ((k.n.bitLength()+7)>>3);
var MAX_DECRYPT_BLOCK = 128;
try {
var ct = "";
var t1;
var bufTmp;
var hexTmp;
var str = b64tohex(string);
var buf = hexToBytes(str);
var inputLen = buf.length;
//開始長度
var offSet = 0;
//結束長度
var 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;
}
}
四、加密
// 配置公鑰
encrypt.setPublicKey('MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCSLZqlbJchBRpyoBe1pWuoxV3At36hG85G3LikI7fiMRynou9nYz4a4T6uCtJNecFGdMPWPKtZ29/amgeFcHw/5vVEHuo8/JLFDM7u4P+cwTtBMwtsQCgynejfB0aOEp4NYjZTMmaeyRWCo5HOQahuV9LORyH/dWdD948qFsIFcQIDAQAB'); // 這里是配置公鑰
// 聲明超長字符串
let str = '{"latitude":"30.685632","longitude":"104.074092","appKey":"123412341234","channelId":"12341234","custId":"LASDFASWERSDFASDFASD","telephone":"2341234211234","token":"68d6a4c21170469289c42386b519612c","name":"王十二"}'
// 加密
var encryptData = encrypt.encryptLong2(str) // encryptData 為加密后的數據
五、解密
// 配置私鑰
encrypt.setPrivateKey('MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJItmqVslyEFGnKgF7Wla6jFXcC3fqEbzkbcuKQjt+IxHKei72djPhrhPq4K0k15wUZ0w9Y8q1nb39qaB4VwfD/m9UQe6jz8ksUMzu7g/5zBO0EzC2xAKDKd6N8HRo4Sng1iNlMyZp7JFYKjkc5BqG5X0s5HIf91Z0P3jyoWwgVxAgMBAAECgYAxsLrvHNjK6rcw2+bzYoYUWvMhvb6X+aHHSOSjN1kc1OEOwz5qgLvt2z+5XghbOdZPowWnX/xHkYyo/M8tty0k8EIAYK+tp8yfTMGIXBnSFhswtB6VDo5TQHU8o1DoD6xIime7PNL8avcjwT0XSH4tGoqWb+N2HzMegoAV0GgdgQJBAMezPNwhOwssEHvb116T+VjWYccuBF/F2nVnFS8XA/RTw3oA9a8luoNIc0Mt+TuBvPg4LzqWuFfdm/cinw7Ob1kCQQC7Y5NC4GBt5KilQaHvp0CVrXELk8HFLiF5bA69Na7WX+O+Jc9z4DDZrJ+tmc/ED2qaSAjapo7EQpko0e/8mVvZAkA4oYqbvky5IVjXVwOfTYVDfSAjVNhmtHv8GSx3uyYi7nIbshP6BE/9FNmi7nGkP2lwVraF/eHvAOhO0CGdGEuZAkBv2vB8axMkhellO9g+Bcg3kGB6WKjB2teAc1AZAYJr1LFNP6Sltp1yUei+56FtlwY7MeSXH/T4kgh6pVZrod+BAkEAs7ZBRtpURnz2yEJGpiMyWJDwyWgkiWufG3ShGcTIHkj4MEO3KX9uaJKw4VqQFs32U4mbucRQv9yvukhgUE+Www==');
// 解密
var str2 = encrypt.decryptLong2(encryptData); //strs 為解密后數據,看看是否一致
注:在定義方法時,需引入以下方法
function hex2b64(h) { var i; var c; var 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) { for (var bytes = [], c = 0; c < hex.length; c += 2) bytes.push(parseInt(hex.substr(c, 2), 16)); return bytes; } function bytesToHex(bytes) { 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) { 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; }
在這里一次性補全了,當時找了好多地方才把引入的方法補全。。。
