@qcwx_mediatom/quick-app-ad-sdk
Version:
mediatom快应用广告SDK
123 lines (108 loc) • 4.03 kB
JavaScript
// 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();
}
};