Vue项目 RSA分段加解密
一、引入JSEncrypt
1.安装依赖
npm install jsencrypt
2.在main.js(需要引入的地方)引入
import { JSEncrypt } from 'jsencrypt'
3.前端公钥加密、后台私钥解密、请求来的数据后台公钥加密、前端私钥解密
二、引入转码方法
// 16进制转byte数组function hexToBytes(hex) {for (var bytes = [], c = 0; c < hex.length; c += 2)bytes.push(parseInt(hex.substr(c, 2), 16));return bytes;
}// byte数组转16进制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("");
};
在原有的JSEncrypt中添加分段加解密的方法
分段加密
JSEncrypt.prototype.encryptLong2 = function (string) {var k = this.getKey(); try {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 += t1;};if (bytes[bytes.length - 1] != string.length - 1) {var lastStr = string.substring(bytes[bytes.length - 1] + 1);ct += k.encrypt(lastStr);}return hexToBytes(ct);}var t = k.encrypt(string);var y = hexToBytes(t);return y;} catch (ex) {return false;}};// utf-8数组转字符串function utf8ByteToUnicodeStr(utf8Bytes) {var unicodeStr = "";for (var pos = 0; pos < utf8Bytes.length;) {var flag = utf8Bytes[pos];var unicode = 0;if ((flag >>> 7) === 0) {unicodeStr += String.fromCharCode(utf8Bytes[pos]);pos += 1;} else if ((flag & 0xFC) === 0xFC) {unicode = (utf8Bytes[pos] & 0x3) << 30;unicode |= (utf8Bytes[pos + 1] & 0x3F) << 24;unicode |= (utf8Bytes[pos + 2] & 0x3F) << 18;unicode |= (utf8Bytes[pos + 3] & 0x3F) << 12;unicode |= (utf8Bytes[pos + 4] & 0x3F) << 6;unicode |= (utf8Bytes[pos + 5] & 0x3F);unicodeStr += String.fromCharCode(unicode);pos += 6;} else if ((flag & 0xF8) === 0xF8) {unicode = (utf8Bytes[pos] & 0x7) << 24;unicode |= (utf8Bytes[pos + 1] & 0x3F) << 18;unicode |= (utf8Bytes[pos + 2] & 0x3F) << 12;unicode |= (utf8Bytes[pos + 3] & 0x3F) << 6;unicode |= (utf8Bytes[pos + 4] & 0x3F);unicodeStr += String.fromCharCode(unicode);pos += 5;} else if ((flag & 0xF0) === 0xF0) {unicode = (utf8Bytes[pos] & 0xF) << 18;unicode |= (utf8Bytes[pos + 1] & 0x3F) << 12;unicode |= (utf8Bytes[pos + 2] & 0x3F) << 6;unicode |= (utf8Bytes[pos + 3] & 0x3F);unicodeStr += String.fromCharCode(unicode);pos += 4;} else if ((flag & 0xE0) === 0xE0) {unicode = (utf8Bytes[pos] & 0x1F) << 12;;unicode |= (utf8Bytes[pos + 1] & 0x3F) << 6;unicode |= (utf8Bytes[pos + 2] & 0x3F);unicodeStr += String.fromCharCode(unicode);pos += 3;} else if ((flag & 0xC0) === 0xC0) { //110unicode = (utf8Bytes[pos] & 0x3F) << 6;unicode |= (utf8Bytes[pos + 1] & 0x3F);unicodeStr += String.fromCharCode(unicode);pos += 2;} else {unicodeStr += String.fromCharCode(utf8Bytes[pos]);pos += 1;}}return unicodeStr;}
分段解密
JSEncrypt.prototype.decryptLong2 = function (string) {var k = this.getKey();var MAX_DECRYPT_BLOCK = 128;//分段解密最大长度限制为128字节try {var ct = "";var t1;var bufTmp;var hexTmp;var str = bytesToHex(string); //这块可能有些没有必要,因为sting参数已经及转为byte数组var buf = hexToBytes(str);var inputLen = buf.length;//开始长度var offSet = 0;//结束长度var endOffSet = MAX_DECRYPT_BLOCK;//分段解密while (inputLen - offSet > 0) {if (inputLen - offSet > MAX_DECRYPT_BLOCK) {bufTmp = buf.slice(offSet, endOffSet);hexTmp = bytesToHex(bufTmp);t1 = k.decrypt(hexTmp);ct += t1;console.log('分段' + offSet)console.log(hexTmp)console.log(t1)} else {bufTmp = buf.slice(offSet, inputLen);hexTmp = bytesToHex(bufTmp);t1 = k.decrypt(hexTmp);ct += t1;console.log('分段' + offSet)console.log(hexTmp)console.log(t1)}offSet += MAX_DECRYPT_BLOCK;endOffSet += MAX_DECRYPT_BLOCK;}return ct;} catch (ex) {return false;}};
三、使用方法
前端给后台传输所以要把byte数组进行base64编码
后台传输来的base64的数据前端解码为byte数组
// btye数组转base64
function arrayBufferToBase64(buffer) {var binary = '';var bytes = new Uint8Array(buffer);var len = bytes.byteLength;for (var i = 0; i < len; i++) {binary += String.fromCharCode(bytes[i]);}return window.btoa(binary);}// base64转btye数组
function base64ToArrayBuffer(base64) {var binary_string = window.atob(base64);var len = binary_string.length;var bytes = new Uint8Array(len);for (var i = 0; i < len; i++) {bytes[i] = binary_string.charCodeAt(i);}return bytes;}
使用加密方法
const $getrsa = function (password) {let encrypt = new JSEncrypt()encrypt.setPublicKey('-----BEGIN PUBLIC KEY-----公钥----END PUBLIC KEY-----') // 公钥let getrsadata = arrayBufferToBase64(encrypt.encryptLong2(password)); //将加密的数据转码为base64return getrsadata //加密后的数据}
使用解密方法
const $decrsa = function (passwords) {let encrypt = new JSEncrypt()encrypt.setPrivateKey('-----BEGIN PRIVATE KEY-----私钥-----') // 私钥let decrsadata = encrypt.decryptLong2(base64ToArrayBuffer(passwords)) // password要解密的数据 先转为byte数组在进行解码return decrsadata //解密后的数据}
四、Tip
后台如果进行分段加密请严格使用117字节划分,前端解析请严格使用128字节划分。
链接:https://www.jianshu.com/p/70dc1b5e2a7c
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
