@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
JavaScript
/**
* 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;