一省撑、引入JSEncrypt
1.安裝依賴? ?npm install?jsencrypt
2.在main.js(需要引入的地方)引入import { JSEncrypt } from 'jsencrypt'
3.前端公鑰加密、后臺私鑰解密俯在、請求來的數(shù)據(jù)后臺公鑰加密竟秫、前端私鑰解密
二、引入轉(zhuǎn)碼方法
// Convert a hex string to a byte array? 16進(jìn)制轉(zhuǎn)byte數(shù)組
function hexToBytes(hex) {
? for (var bytes = [], c = 0; c < hex.length; c += 2)
? ? bytes.push(parseInt(hex.substr(c, 2), 16));
? return bytes;
}
// Convert a byte array to a hex string byte數(shù)組轉(zhuǎn)16進(jìn)制
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("");
};
分段加解密是自己寫的方法需要進(jìn)行十六進(jìn)制和byte數(shù)組進(jìn)行相互轉(zhuǎn)換(具體為什么我也不清楚朝巫,希望有知道的大神鸿摇,可以為我指點(diǎn)一下)
在原有的JSEncrypt中添加分段加解密的方法
分段加密
JSEncrypt.prototype.encryptLong2 = function (string) {
? var k = this.getKey();?
? try {
? ? var ct = "";? ?? //RSA每次加密最大117bytes石景,需要輔助方法判斷字符串截取位置
? ? //1.獲取字符串截取點(diǎn)
? ? 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數(shù)組轉(zhuǎn)字符串
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) { //110
? ? ? unicode = (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字節(jié)
? try {
? ? var ct = "";
? ? var t1;
? ? var bufTmp;
? ? var hexTmp;
? ? var str = bytesToHex(string); //這塊可能有些沒有必要劈猿,因?yàn)閟ting參數(shù)已經(jīng)及轉(zhuǎn)為byte數(shù)組
? ? var buf = hexToBytes(str);
? ? var inputLen = buf.length;
? ? //開始長度
? ? var offSet = 0;
? ? //結(jié)束長度
? ? 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數(shù)組進(jìn)行base64編碼
后臺傳輸來的base64的數(shù)據(jù)前端解碼為byte數(shù)組
btye數(shù)組轉(zhuǎn)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轉(zhuǎn)btye數(shù)組
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)); //將加密的數(shù)據(jù)轉(zhuǎn)碼為base64
? return getrsadata //加密后的數(shù)據(jù)
}
使用解密方法
const $decrsa = function (passwords) {
? let encrypt = new JSEncrypt()
? encrypt.setPrivateKey('-----BEGIN PRIVATE KEY-----私鑰-----') // 私鑰
? let decrsadata = encrypt.decryptLong2(base64ToArrayBuffer(passwords)) // password要解密的數(shù)據(jù) 先轉(zhuǎn)為byte數(shù)組在進(jìn)行解碼
? return decrsadata //解密后的數(shù)據(jù)
}
四潮孽、Tip
后臺如果進(jìn)行分段加密請嚴(yán)格使用117字節(jié)劃分揪荣,前端解析請嚴(yán)格使用128字節(jié)劃分。