|
| 1 | +/** |
| 2 | + * XXTEA library |
| 3 | + * |
| 4 | + * Encryption Algorithm Authors: |
| 5 | + * David J. Wheeler |
| 6 | + * Roger M. Needham |
| 7 | + * |
| 8 | + * @author Ma Bingyao [[email protected]] |
| 9 | + * @author n1474335 [[email protected]] |
| 10 | + * @license MIT |
| 11 | + */ |
| 12 | + |
| 13 | +const DELTA = 0x9E3779B9; |
| 14 | + |
| 15 | +/** |
| 16 | + * Convert a buffer to a Uint8Array |
| 17 | + * @param {Uint32Array} v |
| 18 | + * @param {boolean} includeLength |
| 19 | + * @returns {Uint8Array} |
| 20 | + */ |
| 21 | +function toUint8Array(v, includeLength) { |
| 22 | + const length = v.length; |
| 23 | + let n = length << 2; |
| 24 | + if (includeLength) { |
| 25 | + const m = v[length - 1]; |
| 26 | + n -= 4; |
| 27 | + if ((m < n - 3) || (m > n)) { |
| 28 | + return null; |
| 29 | + } |
| 30 | + n = m; |
| 31 | + } |
| 32 | + const bytes = new Uint8Array(n); |
| 33 | + for (let i = 0; i < n; i++) { |
| 34 | + bytes[i] = v[i >> 2] >> ((i & 3) << 3); |
| 35 | + } |
| 36 | + return bytes; |
| 37 | +} |
| 38 | + |
| 39 | +/** |
| 40 | + * Convert a buffer to a Uint32Array |
| 41 | + * @param {TypedArray} bs |
| 42 | + * @param {boolean} includeLength |
| 43 | + * @returns {Uint32Array} |
| 44 | + */ |
| 45 | +function toUint32Array(bs, includeLength) { |
| 46 | + const length = bs.length; |
| 47 | + let n = length >> 2; |
| 48 | + if ((length & 3) !== 0) { |
| 49 | + ++n; |
| 50 | + } |
| 51 | + let v; |
| 52 | + if (includeLength) { |
| 53 | + v = new Uint32Array(n + 1); |
| 54 | + v[n] = length; |
| 55 | + } else { |
| 56 | + v = new Uint32Array(n); |
| 57 | + } |
| 58 | + for (let i = 0; i < length; ++i) { |
| 59 | + v[i >> 2] |= bs[i] << ((i & 3) << 3); |
| 60 | + } |
| 61 | + return v; |
| 62 | +} |
| 63 | + |
| 64 | +/** |
| 65 | + * Mask an int to 32 bits |
| 66 | + * @param {number} i |
| 67 | + * @returns {number} |
| 68 | + */ |
| 69 | +function int32(i) { |
| 70 | + return i & 0xFFFFFFFF; |
| 71 | +} |
| 72 | + |
| 73 | +/** |
| 74 | + * MX function for data randomisation |
| 75 | + * @param {number} sum |
| 76 | + * @param {number} y |
| 77 | + * @param {number} z |
| 78 | + * @param {number} p |
| 79 | + * @param {number} e |
| 80 | + * @param {number} k |
| 81 | + * @returns {number} |
| 82 | + */ |
| 83 | +function mx(sum, y, z, p, e, k) { |
| 84 | + return ((z >>> 5 ^ y << 2) + (y >>> 3 ^ z << 4)) ^ ((sum ^ y) + (k[p & 3 ^ e] ^ z)); |
| 85 | +} |
| 86 | + |
| 87 | +/** |
| 88 | + * Ensure an array is a multiple of 16 bits |
| 89 | + * @param {TypedArray} k |
| 90 | + * @returns {TypedArray} |
| 91 | + */ |
| 92 | +function fixk(k) { |
| 93 | + if (k.length < 16) { |
| 94 | + const key = new Uint8Array(16); |
| 95 | + key.set(k); |
| 96 | + return key; |
| 97 | + } |
| 98 | + return k; |
| 99 | +} |
| 100 | + |
| 101 | +/** |
| 102 | + * Performs XXTEA encryption on a Uint32Array |
| 103 | + * @param {Uint32Array} v |
| 104 | + * @param {Uint32Array} k |
| 105 | + * @returns {Uint32Array} |
| 106 | + */ |
| 107 | +function encryptUint32Array(v, k) { |
| 108 | + const length = v.length; |
| 109 | + const n = length - 1; |
| 110 | + let y, z, sum, e, p, q; |
| 111 | + z = v[n]; |
| 112 | + sum = 0; |
| 113 | + for (q = Math.floor(6 + 52 / length) | 0; q > 0; --q) { |
| 114 | + sum = int32(sum + DELTA); |
| 115 | + e = sum >>> 2 & 3; |
| 116 | + for (p = 0; p < n; ++p) { |
| 117 | + y = v[p + 1]; |
| 118 | + z = v[p] = int32(v[p] + mx(sum, y, z, p, e, k)); |
| 119 | + } |
| 120 | + y = v[0]; |
| 121 | + z = v[n] = int32(v[n] + mx(sum, y, z, n, e, k)); |
| 122 | + } |
| 123 | + return v; |
| 124 | +} |
| 125 | + |
| 126 | +/** |
| 127 | + * Performs XXTEA decryption on a Uint32Array |
| 128 | + * @param {Uint32Array} v |
| 129 | + * @param {Uint32Array} k |
| 130 | + * @returns {Uint32Array} |
| 131 | + */ |
| 132 | +function decryptUint32Array(v, k) { |
| 133 | + const length = v.length; |
| 134 | + const n = length - 1; |
| 135 | + let y, z, sum, e, p; |
| 136 | + y = v[0]; |
| 137 | + const q = Math.floor(6 + 52 / length); |
| 138 | + for (sum = int32(q * DELTA); sum !== 0; sum = int32(sum - DELTA)) { |
| 139 | + e = sum >>> 2 & 3; |
| 140 | + for (p = n; p > 0; --p) { |
| 141 | + z = v[p - 1]; |
| 142 | + y = v[p] = int32(v[p] - mx(sum, y, z, p, e, k)); |
| 143 | + } |
| 144 | + z = v[n]; |
| 145 | + y = v[0] = int32(v[0] - mx(sum, y, z, 0, e, k)); |
| 146 | + } |
| 147 | + return v; |
| 148 | +} |
| 149 | + |
| 150 | +/** |
| 151 | + * Encrypt function |
| 152 | + * @param {TypedArray} data |
| 153 | + * @param {TypedArray} key |
| 154 | + * @returns {Uint8Array} |
| 155 | + */ |
| 156 | +export function encrypt(data, key) { |
| 157 | + if (data === undefined || data === null || data.length === 0) { |
| 158 | + return data; |
| 159 | + } |
| 160 | + return toUint8Array(encryptUint32Array(toUint32Array(data, true), toUint32Array(fixk(key), false)), false); |
| 161 | +} |
| 162 | + |
| 163 | +/** |
| 164 | + * Decrypt function |
| 165 | + * @param {TypedArray} data |
| 166 | + * @param {TypedArray} key |
| 167 | + * @returns {Uint8Array} |
| 168 | + */ |
| 169 | +export function decrypt(data, key) { |
| 170 | + if (data === undefined || data === null || data.length === 0) { |
| 171 | + return data; |
| 172 | + } |
| 173 | + return toUint8Array(decryptUint32Array(toUint32Array(data, false), toUint32Array(fixk(key), false)), true); |
| 174 | +} |
0 commit comments