rsa和xxtea加密算法对比,以及优缺点
之前项目中使用的是RSA
加密:👇
但是因为后续使用过程中发现一些RSA
加解密的问题:加解密速度较慢,不适合对大量数据进行加密。
服务端 性能压测过程中发现RSA
太慢了,而使用XXTEA
,速度会快很多。
XXTEA算法的优缺点:
优点:
- 实现简单,使用方便。
- 加解密速度较快,适合对大量数据进行加密。
- 数据长度限制较小。
缺点:
- 安全性较低,易受到破解攻击。
- 密钥管理相对较为困难。
- 不支持数字签名等高级功能。
RSA算法的优缺点:
优点:
- 安全性较高,可提供有效的保护机制。
- 可以实现数字签名、密钥交换等高级功能。
- 公钥加密方便,可以实现非对称加密。
缺点:
- 实现复杂,使用起来相对困难。
- 加解密速度较慢,不适合对大量数据进行加密。
- 数据长度无限制,但加密后的数据长度较长。
综上所述,XXTEA算法适合在前端对少量数据进行加密,但安全性较低;RSA算法适合在服务端对大量数据进行加密,并提供更好的安全保障。在选择哪种算法时,需要根据具体的应用场景和需求来做出决策。
最终根据具体需求和场景 以及安全
部门、压测
部门的建议,我们选择从rsa
算法转到xxtea
算法。
前端使用XXTEA
xxtea.js代码:
if (typeof (global.btoa) == "undefined") { global.btoa = function () { var base64EncodeChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split(''); return function (str) { var buf, i, j, len, r, l, c; i = j = 0; len = str.length; r = len % 3; len = len - r; l = (len / 3) << 2; if (r > 0) { l += 4 } buf = new Array(l); while (i < len) { c = str.charCodeAt(i++) << 16 | str.charCodeAt(i++) << 8 | str.charCodeAt(i++); buf[j++] = base64EncodeChars[c >> 18] + base64EncodeChars[c >> 12 & 0x3f] + base64EncodeChars[c >> 6 & 0x3f] + base64EncodeChars[c & 0x3f] } if (r == 1) { c = str.charCodeAt(i++); buf[j++] = base64EncodeChars[c >> 2] + base64EncodeChars[(c & 0x03) << 4] + "==" } else if (r == 2) { c = str.charCodeAt(i++) << 8 | str.charCodeAt(i++); buf[j++] = base64EncodeChars[c >> 10] + base64EncodeChars[c >> 4 & 0x3f] + base64EncodeChars[(c & 0x0f) << 2] + "=" } return buf.join('') } }() } if (typeof (global.atob) == "undefined") { global.atob = function () { var base64DecodeChars = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1]; return function (str) { var c1, c2, c3, c4; var i, j, len, r, l, out; len = str.length; if (len % 4 !== 0) { return '' } if (/[^ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\+\/\=]/.test(str)) { return '' } if (str.charAt(len - 2) == '=') { r = 1 } else if (str.charAt(len - 1) == '=') { r = 2 } else { r = 0 } l = len; if (r > 0) { l -= 4 } l = (l >> 2) * 3 + r; out = new Array(l); i = j = 0; while (i < len) { c1 = base64DecodeChars[str.charCodeAt(i++)]; if (c1 == -1) break; c2 = base64DecodeChars[str.charCodeAt(i++)]; if (c2 == -1) break; out[j++] = String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4)); c3 = base64DecodeChars[str.charCodeAt(i++)]; if (c3 == -1) break; out[j++] = String.fromCharCode(((c2 & 0x0f) << 4) | ((c3 & 0x3c) >> 2)); c4 = base64DecodeChars[str.charCodeAt(i++)]; if (c4 == -1) break; out[j++] = String.fromCharCode(((c3 & 0x03) << 6) | c4) } return out.join('') } }() } var DELTA = 0x9E3779B9; function toBinaryString(v, includeLength) { var length = v.length; var n = length << 2; if (includeLength) { var m = v[length - 1]; n -= 4; if ((m < n - 3) || (m > n)) { return null } n = m } for (var i = 0; i < length; i++) { v[i] = String.fromCharCode(v[i] & 0xFF, v[i] >>> 8 & 0xFF, v[i] >>> 16 & 0xFF, v[i] >>> 24 & 0xFF) } var result = v.join(''); if (includeLength) { return result.substring(0, n) } return result } function toUint32Array(bs, includeLength) { var length = bs.length; var n = length >> 2; if ((length & 3) !== 0) { ++n } var v; if (includeLength) { v = new Array(n + 1); v[n] = length } else { v = new Array(n) } for (var i = 0; i < length; ++i) { v[i >> 2] |= bs.charCodeAt(i) << ((i & 3) << 3) } return v } function int32(i) { return i & 0xFFFFFFFF } function mx(sum, y, z, p, e, k) { return ((z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4)) ^ ((sum ^ y) + (k[p & 3 ^ e] ^ z)) } function fixk(k) { if (k.length < 4) k.length = 4; return k } function encryptUint32Array(v, k) { var length = v.length; var n = length - 1; var y, z, sum, e, p, q; z = v[n]; sum = 0; for (q = Math.floor(6 + 52 / length) | 0; q > 0; --q) { sum = int32(sum + DELTA); e = sum >>> 2 & 3; for (p = 0; p < n; ++p) { y = v[p + 1]; z = v[p] = int32(v[p] + mx(sum, y, z, p, e, k)) } y = v[0]; z = v[n] = int32(v[n] + mx(sum, y, z, n, e, k)) } return v } function decryptUint32Array(v, k) { var length = v.length; var n = length - 1; var y, z, sum, e, p, q; y = v[0]; q = Math.floor(6 + 52 / length); for (sum = int32(q * DELTA); sum !== 0; sum = int32(sum - DELTA)) { e = sum >>> 2 & 3; for (p = n; p > 0; --p) { z = v[p - 1]; y = v[p] = int32(v[p] - mx(sum, y, z, p, e, k)) } z = v[n]; y = v[0] = int32(v[0] - mx(sum, y, z, 0, e, k)) } return v } function utf8Encode(str) { if (/^[\x00-\x7f]*$/.test(str)) { return str } var buf = []; var n = str.length; for (var i = 0, j = 0; i < n; ++i, ++j) { var codeUnit = str.charCodeAt(i); if (codeUnit < 0x80) { buf[j] = str.charAt(i) } else if (codeUnit < 0x800) { buf[j] = String.fromCharCode(0xC0 | (codeUnit >> 6), 0x80 | (codeUnit & 0x3F)) } else if (codeUnit < 0xD800 || codeUnit > 0xDFFF) { buf[j] = String.fromCharCode(0xE0 | (codeUnit >> 12), 0x80 | ((codeUnit >> 6) & 0x3F), 0x80 | (codeUnit & 0x3F)) } else { if (i + 1 < n) { var nextCodeUnit = str.charCodeAt(i + 1); if (codeUnit < 0xDC00 && 0xDC00 <= nextCodeUnit && nextCodeUnit <= 0xDFFF) { var rune = (((codeUnit & 0x03FF) << 10) | (nextCodeUnit & 0x03FF)) + 0x010000; buf[j] = String.fromCharCode(0xF0 | ((rune >> 18) & 0x3F), 0x80 | ((rune >> 12) & 0x3F), 0x80 | ((rune >> 6) & 0x3F), 0x80 | (rune & 0x3F)); ++i; continue } } throw new Error('Malformed string'); } } return buf.join('') } function utf8DecodeShortString(bs, n) { var charCodes = new Array(n); var i = 0, off = 0; for (var len = bs.length; i < n && off < len; i++) { var unit = bs.charCodeAt(off++); switch (unit >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: charCodes[i] = unit; break; case 12: case 13: if (off < len) { charCodes[i] = ((unit & 0x1F) << 6) | (bs.charCodeAt(off++) & 0x3F) } else { throw new Error('Unfinished UTF-8 octet sequence'); } break; case 14: if (off + 1 < len) { charCodes[i] = ((unit & 0x0F) << 12) | ((bs.charCodeAt(off++) & 0x3F) << 6) | (bs.charCodeAt(off++) & 0x3F) } else { throw new Error('Unfinished UTF-8 octet sequence'); } break; case 15: if (off + 2 < len) { var rune = (((unit & 0x07) << 18) | ((bs.charCodeAt(off++) & 0x3F) << 12) | ((bs.charCodeAt(off++) & 0x3F) << 6) | (bs.charCodeAt(off++) & 0x3F)) - 0x10000; if (0 <= rune && rune <= 0xFFFFF) { charCodes[i++] = (((rune >> 10) & 0x03FF) | 0xD800); charCodes[i] = ((rune & 0x03FF) | 0xDC00) } else { throw new Error('Character outside valid Unicode range: 0x' + rune.toString(16)); } } else { throw new Error('Unfinished UTF-8 octet sequence'); } break; default: throw new Error('Bad UTF-8 encoding 0x' + unit.toString(16)); } } if (i < n) { charCodes.length = i } return String.fromCharCode.apply(String, charCodes) } function utf8DecodeLongString(bs, n) { var buf = []; var charCodes = new Array(0x8000); var i = 0, off = 0; for (var len = bs.length; i < n && off < len; i++) { var unit = bs.charCodeAt(off++); switch (unit >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: charCodes[i] = unit; break; case 12: case 13: if (off < len) { charCodes[i] = ((unit & 0x1F) << 6) | (bs.charCodeAt(off++) & 0x3F) } else { throw new Error('Unfinished UTF-8 octet sequence'); } break; case 14: if (off + 1 < len) { charCodes[i] = ((unit & 0x0F) << 12) | ((bs.charCodeAt(off++) & 0x3F) << 6) | (bs.charCodeAt(off++) & 0x3F) } else { throw new Error('Unfinished UTF-8 octet sequence'); } break; case 15: if (off + 2 < len) { var rune = (((unit & 0x07) << 18) | ((bs.charCodeAt(off++) & 0x3F) << 12) | ((bs.charCodeAt(off++) & 0x3F) << 6) | (bs.charCodeAt(off++) & 0x3F)) - 0x10000; if (0 <= rune && rune <= 0xFFFFF) { charCodes[i++] = (((rune >> 10) & 0x03FF) | 0xD800); charCodes[i] = ((rune & 0x03FF) | 0xDC00) } else { throw new Error('Character outside valid Unicode range: 0x' + rune.toString(16)); } } else { throw new Error('Unfinished UTF-8 octet sequence'); } break; default: throw new Error('Bad UTF-8 encoding 0x' + unit.toString(16)); }if (i >= 0x7FFF - 1) { var size = i + 1; charCodes.length = size; buf[buf.length] = String.fromCharCode.apply(String, charCodes); n -= size; i = -1 } } if (i > 0) { charCodes.length = i; buf[buf.length] = String.fromCharCode.apply(String, charCodes) } return buf.join('') } function utf8Decode(bs, n) { if (n === undefined || n === null || (n < 0)) n = bs.length; if (n === 0) return ''; if (/^[\x00-\x7f]*$/.test(bs) || !(/^[\x00-\xff]*$/.test(bs))) { if (n === bs.length) return bs; return bs.substr(0, n) } return ((n < 0xFFFF) ? utf8DecodeShortString(bs, n) : utf8DecodeLongString(bs, n)) } function encrypt(data, key) { if (data === undefined || data === null || data.length === 0) { return data } data = utf8Encode(data); key = utf8Encode(key); return toBinaryString(encryptUint32Array(toUint32Array(data, true), fixk(toUint32Array(key, false))), false) } function encryptToBase64(data, key) { return global.btoa(encrypt(data, key)) } function decrypt(data, key) { if (data === undefined || data === null || data.length === 0) { return data } key = utf8Encode(key); return utf8Decode(toBinaryString(decryptUint32Array(toUint32Array(data, false), fixk(toUint32Array(key, false))), true)) } function decryptFromBase64(data, key) { if (data === undefined || data === null || data.length === 0) { return data } return decrypt(global.atob(data), key) } module.exports = { utf8Encode: utf8Encode, utf8Decode: utf8Decode, encrypt: encrypt, encryptToBase64: encryptToBase64, decrypt: decrypt, decryptFromBase64: decryptFromBase64 };
在vue中使用:
import XXTEA from '@/assets/js/xxtea'
let str = 'Hello World! 你好,哆啦!'
let secretKey = '123456789'
let encrypt_data = XXTEA.encryptToBase64(str, secretKey)
// console.log('加密--', encrypt_data)
let decrypt_data = XXTEA.decryptFromBase64(encrypt_data, secretKey)
// console.log('解密--', decrypt_data)