UNPKG

@xbibzlibrary/obfuscator

Version:

Advanced polymorphic obfuscation library for JavaScript, JSON and CSS with multi-layer encryption and browser compatibility

435 lines (355 loc) 14.4 kB
/** * Advanced AES Encryption Engine * Multi-layer encryption with dynamic key derivation * @version 1.0.0 * @author Xbibz Official */ class AdvancedAES { constructor() { this.rounds = 14; this.keySize = 256; this.blockSize = 128; this.ivSize = 16; this.mode = 'CBC'; this.padding = 'PKCS7'; this.sBox = this.generateSBox(); this.invSBox = this.generateInvSBox(); this.rcon = this.generateRcon(); } generateSBox() { const sBox = new Uint8Array(256); let p = 1, q = 1; do { p = p ^ (p << 1) ^ (p & 0x80 ? 0x1B : 0); q ^= q << 1; q ^= q << 2; q ^= q << 4; q ^= (q & 0x80) ? 0x09 : 0; const xformed = q ^ this.rotateLeft(q, 1) ^ this.rotateLeft(q, 2) ^ this.rotateLeft(q, 3) ^ this.rotateLeft(q, 4); sBox[p] = xformed ^ 0x63; } while (p != 1); sBox[0] = 0x63; return sBox; } generateInvSBox() { const invSBox = new Uint8Array(256); for (let i = 0; i < 256; i++) { invSBox[this.sBox[i]] = i; } return invSBox; } generateRcon() { const rcon = new Uint8Array(11); rcon[0] = 0x8d; for (let i = 1; i < 11; i++) { rcon[i] = this.xtime(rcon[i - 1]); } return rcon; } rotateLeft(value, shift) { return ((value << shift) | (value >>> (8 - shift))) & 0xFF; } xtime(x) { return ((x << 1) ^ (((x >>> 7) & 1) * 0x1b)) & 0xFF; } keyExpansion(key) { const keyWords = key.length / 4; const rounds = this.rounds + 1; const w = new Array(4 * rounds); for (let i = 0; i < keyWords; i++) { w[i] = (key[4*i] << 24) | (key[4*i+1] << 16) | (key[4*i+2] << 8) | key[4*i+3]; } for (let i = keyWords; i < 4 * rounds; i++) { let temp = w[i - 1]; if (i % keyWords === 0) { temp = this.subWord(this.rotWord(temp)) ^ (this.rcon[Math.floor(i / keyWords)] << 24); } else if (keyWords > 6 && i % keyWords === 4) { temp = this.subWord(temp); } w[i] = w[i - keyWords] ^ temp; } return w; } subWord(word) { return (this.sBox[(word >>> 24) & 0xFF] << 24) | (this.sBox[(word >>> 16) & 0xFF] << 16) | (this.sBox[(word >>> 8) & 0xFF] << 8) | this.sBox[word & 0xFF]; } rotWord(word) { return (word << 8) | (word >>> 24); } subBytes(state) { for (let i = 0; i < 16; i++) { state[i] = this.sBox[state[i]]; } } invSubBytes(state) { for (let i = 0; i < 16; i++) { state[i] = this.invSBox[state[i]]; } } shiftRows(state) { const temp = new Uint8Array(16); temp[0] = state[0]; temp[1] = state[5]; temp[2] = state[10]; temp[3] = state[15]; temp[4] = state[4]; temp[5] = state[9]; temp[6] = state[14]; temp[7] = state[3]; temp[8] = state[8]; temp[9] = state[13]; temp[10] = state[2]; temp[11] = state[7]; temp[12] = state[12]; temp[13] = state[1]; temp[14] = state[6]; temp[15] = state[11]; state.set(temp); } invShiftRows(state) { const temp = new Uint8Array(16); temp[0] = state[0]; temp[1] = state[13]; temp[2] = state[10]; temp[3] = state[7]; temp[4] = state[4]; temp[5] = state[1]; temp[6] = state[14]; temp[7] = state[11]; temp[8] = state[8]; temp[9] = state[5]; temp[10] = state[2]; temp[11] = state[15]; temp[12] = state[12]; temp[13] = state[9]; temp[14] = state[6]; temp[15] = state[3]; state.set(temp); } mixColumns(state) { for (let i = 0; i < 4; i++) { const a = new Uint8Array(4); const b = new Uint8Array(4); for (let c = 0; c < 4; c++) { a[c] = state[i * 4 + c]; b[c] = (state[i * 4 + c] & 0x80) ? (state[i * 4 + c] << 1) ^ 0x011b : (state[i * 4 + c] << 1); } state[i * 4 + 0] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; state[i * 4 + 1] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; state[i * 4 + 2] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; state[i * 4 + 3] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; } } invMixColumns(state) { for (let i = 0; i < 4; i++) { const a = new Uint8Array(4); for (let c = 0; c < 4; c++) { a[c] = state[i * 4 + c]; } state[i * 4 + 0] = this.xtime(a[0] ^ a[2]) ^ this.xtime(a[1] ^ a[3]) ^ a[1] ^ a[2] ^ a[3]; state[i * 4 + 1] = this.xtime(a[1] ^ a[3]) ^ this.xtime(a[0] ^ a[2]) ^ a[0] ^ a[2] ^ a[3]; state[i * 4 + 2] = this.xtime(a[0] ^ a[2]) ^ this.xtime(a[1] ^ a[3]) ^ a[0] ^ a[1] ^ a[3]; state[i * 4 + 3] = this.xtime(a[1] ^ a[3]) ^ this.xtime(a[0] ^ a[2]) ^ a[0] ^ a[1] ^ a[2]; } } addRoundKey(state, roundKey, round) { for (let i = 0; i < 16; i++) { state[i] ^= roundKey[round * 16 + i]; } } encryptBlock(state, roundKey) { this.addRoundKey(state, roundKey, 0); for (let round = 1; round < this.rounds; round++) { this.subBytes(state); this.shiftRows(state); this.mixColumns(state); this.addRoundKey(state, roundKey, round); } this.subBytes(state); this.shiftRows(state); this.addRoundKey(state, roundKey, this.rounds); } decryptBlock(state, roundKey) { this.addRoundKey(state, roundKey, this.rounds); for (let round = this.rounds - 1; round > 0; round--) { this.invShiftRows(state); this.invSubBytes(state); this.addRoundKey(state, roundKey, round); this.invMixColumns(state); } this.invShiftRows(state); this.invSubBytes(state); this.addRoundKey(state, roundKey, 0); } pkcs7Pad(data) { const padLength = 16 - (data.length % 16); const padded = new Uint8Array(data.length + padLength); padded.set(data); for (let i = data.length; i < padded.length; i++) { padded[i] = padLength; } return padded; } pkcs7Unpad(data) { const padLength = data[data.length - 1]; return data.slice(0, data.length - padLength); } generateIV() { const iv = new Uint8Array(this.ivSize); for (let i = 0; i < this.ivSize; i++) { iv[i] = Math.floor(Math.random() * 256); } return iv; } deriveKey(password, salt) { // PBKDF2-like key derivation let key = new TextEncoder().encode(password); const keyBuffer = new Uint8Array(32); for (let i = 0; i < 1000; i++) { const hmac = this.hmacSha256(key, salt); for (let j = 0; j < hmac.length; j++) { keyBuffer[j] ^= hmac[j]; } key = hmac; } return keyBuffer; } hmacSha256(key, data) { // Simplified HMAC-SHA256 implementation const blockSize = 64; const ipad = new Uint8Array(blockSize); const opad = new Uint8Array(blockSize); if (key.length > blockSize) { key = this.sha256(key); } for (let i = 0; i < blockSize; i++) { ipad[i] = (i < key.length ? key[i] : 0) ^ 0x36; opad[i] = (i < key.length ? key[i] : 0) ^ 0x5C; } const innerHash = this.sha256(new Uint8Array([...ipad, ...data])); return this.sha256(new Uint8Array([...opad, ...innerHash])); } sha256(data) { // Simplified SHA-256 implementation const h = new Uint32Array([ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 ]); // Padding const bitLength = data.length * 8; const padded = new Uint8Array(((data.length + 8 + 64) & ~63) || 64); padded.set(data); padded[data.length] = 0x80; const view = new DataView(padded.buffer); view.setUint32(padded.length - 8, Math.floor(bitLength / 0x100000000), false); view.setUint32(padded.length - 4, bitLength, false); // Process blocks for (let i = 0; i < padded.length; i += 64) { const w = new Uint32Array(64); for (let j = 0; j < 16; j++) { w[j] = view.getUint32(i + j * 4, false); } for (let j = 16; j < 64; j++) { const s0 = this.rotr(w[j-15], 7) ^ this.rotr(w[j-15], 18) ^ (w[j-15] >>> 3); const s1 = this.rotr(w[j-2], 17) ^ this.rotr(w[j-2], 19) ^ (w[j-2] >>> 10); w[j] = (w[j-16] + s0 + w[j-7] + s1) >>> 0; } let [a, b, c, d, e, f, g, hTemp] = h; for (let j = 0; j < 64; j++) { const S1 = this.rotr(e, 6) ^ this.rotr(e, 11) ^ this.rotr(e, 25); const ch = (e & f) ^ (~e & g); const temp1 = (hTemp + S1 + ch + this.k[j] + w[j]) >>> 0; const S0 = this.rotr(a, 2) ^ this.rotr(a, 13) ^ this.rotr(a, 22); const maj = (a & b) ^ (a & c) ^ (b & c); const temp2 = (S0 + maj) >>> 0; hTemp = g; g = f; f = e; e = (d + temp1) >>> 0; d = c; c = b; b = a; a = (temp1 + temp2) >>> 0; } h[0] = (h[0] + a) >>> 0; h[1] = (h[1] + b) >>> 0; h[2] = (h[2] + c) >>> 0; h[3] = (h[3] + d) >>> 0; h[4] = (h[4] + e) >>> 0; h[5] = (h[5] + f) >>> 0; h[6] = (h[6] + g) >>> 0; h[7] = (h[7] + hTemp) >>> 0; } const result = new Uint8Array(32); for (let i = 0; i < 8; i++) { result[i*4] = (h[i] >>> 24) & 0xFF; result[i*4+1] = (h[i] >>> 16) & 0xFF; result[i*4+2] = (h[i] >>> 8) & 0xFF; result[i*4+3] = h[i] & 0xFF; } return result; } get k() { return new Uint32Array([ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 ]); } rotr(value, shift) { return (value >>> shift) | (value << (32 - shift)); } encrypt(data, password) { const salt = this.generateIV(); const key = this.deriveKey(password, salt); const expandedKey = this.keyExpansion(key); const paddedData = this.pkcs7Pad(new Uint8Array(data)); const iv = this.generateIV(); const result = new Uint8Array(salt.length + iv.length + paddedData.length); result.set(salt, 0); result.set(iv, salt.length); let previousBlock = iv; for (let i = 0; i < paddedData.length; i += 16) { const block = paddedData.slice(i, i + 16); // CBC mode XOR for (let j = 0; j < 16; j++) { block[j] ^= previousBlock[j]; } this.encryptBlock(block, expandedKey); result.set(block, salt.length + iv.length + i); previousBlock = block; } return result; } decrypt(encryptedData, password) { const salt = encryptedData.slice(0, 16); const iv = encryptedData.slice(16, 32); const data = encryptedData.slice(32); const key = this.deriveKey(password, salt); const expandedKey = this.keyExpansion(key); const result = new Uint8Array(data.length); let previousBlock = iv; for (let i = 0; i < data.length; i += 16) { const block = data.slice(i, i + 16); const tempBlock = new Uint8Array(block); this.decryptBlock(tempBlock, expandedKey); // CBC mode XOR for (let j = 0; j < 16; j++) { tempBlock[j] ^= previousBlock[j]; } result.set(tempBlock, i); previousBlock = block; } return this.pkcs7Unpad(result); } encryptString(text, password) { const data = new TextEncoder().encode(text); const encrypted = this.encrypt(data, password); return btoa(String.fromCharCode(...encrypted)); } decryptString(encryptedText, password) { const binaryString = atob(encryptedText); const encryptedData = new Uint8Array(binaryString.length); for (let i = 0; i < binaryString.length; i++) { encryptedData[i] = binaryString.charCodeAt(i); } const decrypted = this.decrypt(encryptedData, password); return new TextDecoder().decode(decrypted); } } module.exports = AdvancedAES;