UNPKG

@qcwx_mediatom/quick-app-ad-sdk

Version:

mediatom快应用广告SDK

123 lines (108 loc) 4.03 kB
// lib/asmcrypto-lite.js // 仅包含 AES-CBC + PKCS7 实现(快应用兼容) // 来源:https://github.com/asmcrypto/asmcrypto.js(提取精简) function xor_block(dst, a, b) { for (let i = 0; i < 16; i++) dst[i] = a[i] ^ b[i]; } function pad_pkcs7(data) { const padLen = 16 - (data.length % 16); const padded = new Uint8Array(data.length + padLen); padded.set(data); padded.fill(padLen, data.length); return padded; } function unpad_pkcs7(buf) { const padLen = buf[buf.length - 1]; return buf.slice(0, buf.length - padLen); } function sub_word(w) { const sbox = AES_CBC._sbox; return (sbox[(w >>> 24) ] << 24) | (sbox[(w >>> 16) & 255] << 16) | (sbox[(w >>> 8) & 255] << 8) | (sbox[(w ) & 255]); } function rot_word(w) { return ((w << 8) | (w >>> 24)) >>> 0; } function key_expansion(keyBytes) { const sbox = AES_CBC._sbox; const Rcon = AES_CBC._Rcon; const keyWords = []; for (let i = 0; i < keyBytes.length; i += 4) { keyWords.push((keyBytes[i] << 24) | (keyBytes[i+1] << 16) | (keyBytes[i+2] << 8) | keyBytes[i+3]); } const Nk = keyWords.length; const Nr = Nk + 6; const w = new Array((Nr + 1) * 4); for (let i = 0; i < Nk; ++i) w[i] = keyWords[i]; for (let i = Nk; i < (Nr + 1) * 4; ++i) { let temp = w[i - 1]; if (i % Nk === 0) temp = sub_word(rot_word(temp)) ^ Rcon[i / Nk | 0]; else if (Nk > 6 && i % Nk === 4) temp = sub_word(temp); w[i] = w[i - Nk] ^ temp; } return w; } function aes_sub_bytes(state) { const sbox = AES_CBC._sbox; for (let i = 0; i < 16; i++) state[i] = sbox[state[i]]; } function aes_shift_rows(state) { const t = new Uint8Array(state); for (let i = 0; i < 16; i++) state[i] = t[(i % 4) + ((i / 4 | 0) * 4 + i / 4 | 0) % 4 * 4]; } function aes_mix_columns(state) { const mul2 = AES_CBC._mul2; const mul3 = AES_CBC._mul3; const t = new Uint8Array(16); for (let c = 0; c < 4; ++c) { const i = c * 4; const s0 = state[i], s1 = state[i+1], s2 = state[i+2], s3 = state[i+3]; t[i ] = mul2[s0] ^ mul3[s1] ^ s2 ^ s3; t[i+1] = s0 ^ mul2[s1] ^ mul3[s2] ^ s3; t[i+2] = s0 ^ s1 ^ mul2[s2] ^ mul3[s3]; t[i+3] = mul3[s0] ^ s1 ^ s2 ^ mul2[s3]; } state.set(t); } function aes_add_round_key(state, roundKey, round) { for (let i = 0; i < 16; ++i) state[i] ^= (roundKey[round * 4 + (i >>> 2)] >>> ((3 - (i % 4)) * 8)) & 255; } function aes_encrypt_block(state, w) { const Nr = w.length / 4 - 1; aes_add_round_key(state, w, 0); for (let round = 1; round < Nr; ++round) { aes_sub_bytes(state); aes_shift_rows(state); aes_mix_columns(state); aes_add_round_key(state, w, round); } aes_sub_bytes(state); aes_shift_rows(state); aes_add_round_key(state, w, Nr); } export const AES_CBC = { _sbox: [...Array(256)].map((_, i) => i), // 替换为完整 SBOX _Rcon: [0x00000000,0x01000000,0x02000000,0x04000000,0x08000000,0x10000000,0x20000000,0x40000000,0x80000000,0x1b000000,0x36000000], _mul2: new Uint8Array(256), // 需初始化 _mul3: new Uint8Array(256), // 需初始化 encrypt(data, key, padding = true, iv) { const input = padding ? pad_pkcs7(data) : data; const output = new Uint8Array(input.length); const w = key_expansion(key); const block = new Uint8Array(16); let prev = new Uint8Array(iv); for (let i = 0; i < input.length; i += 16) { xor_block(block, input.subarray(i, i + 16), prev); aes_encrypt_block(block, w); output.set(block, i); prev = block.slice(); } return output; }, decrypt(data, key, padding = true, iv) { // 留空,示意结构 return new Uint8Array(); } };