JavaScript 65.5%
Python 17.8%
CSS 13%
HTML 3.7%
1export class AESECBCipher {2 constructor() {3 this._key = null;4 }56 get algorithm() {7 return { name: "AES-ECB" };8 }910 static async importKey(key, _algorithm, extractable, keyUsages) {11 const cipher = new AESECBCipher;12 await cipher._importKey(key, extractable, keyUsages);13 return cipher;14 }1516 async _importKey(key, extractable, keyUsages) {17 this._key = await window.crypto.subtle.importKey(18 "raw", key, {name: "AES-CBC"}, extractable, keyUsages);19 }2021 async encrypt(_algorithm, plaintext) {22 const x = new Uint8Array(plaintext);23 if (x.length % 16 !== 0 || this._key === null) {24 return null;25 }26 const n = x.length / 16;27 for (let i = 0; i < n; i++) {28 const y = new Uint8Array(await window.crypto.subtle.encrypt({29 name: "AES-CBC",30 iv: new Uint8Array(16),31 }, this._key, x.slice(i * 16, i * 16 + 16))).slice(0, 16);32 x.set(y, i * 16);33 }34 return x;35 }36}3738export class AESEAXCipher {39 constructor() {40 this._rawKey = null;41 this._ctrKey = null;42 this._cbcKey = null;43 this._zeroBlock = new Uint8Array(16);44 this._prefixBlock0 = this._zeroBlock;45 this._prefixBlock1 = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);46 this._prefixBlock2 = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]);47 }4849 get algorithm() {50 return { name: "AES-EAX" };51 }5253 async _encryptBlock(block) {54 const encrypted = await window.crypto.subtle.encrypt({55 name: "AES-CBC",56 iv: this._zeroBlock,57 }, this._cbcKey, block);58 return new Uint8Array(encrypted).slice(0, 16);59 }6061 async _initCMAC() {62 const k1 = await this._encryptBlock(this._zeroBlock);63 const k2 = new Uint8Array(16);64 const v = k1[0] >>> 6;65 for (let i = 0; i < 15; i++) {66 k2[i] = (k1[i + 1] >> 6) | (k1[i] << 2);67 k1[i] = (k1[i + 1] >> 7) | (k1[i] << 1);68 }69 const lut = [0x0, 0x87, 0x0e, 0x89];70 k2[14] ^= v >>> 1;71 k2[15] = (k1[15] << 2) ^ lut[v];72 k1[15] = (k1[15] << 1) ^ lut[v >> 1];73 this._k1 = k1;74 this._k2 = k2;75 }7677 async _encryptCTR(data, counter) {78 const encrypted = await window.crypto.subtle.encrypt({79 name: "AES-CTR",80 counter: counter,81 length: 12882 }, this._ctrKey, data);83 return new Uint8Array(encrypted);84 }8586 async _decryptCTR(data, counter) {87 const decrypted = await window.crypto.subtle.decrypt({88 name: "AES-CTR",89 counter: counter,90 length: 12891 }, this._ctrKey, data);92 return new Uint8Array(decrypted);93 }9495 async _computeCMAC(data, prefixBlock) {96 if (prefixBlock.length !== 16) {97 return null;98 }99 const n = Math.floor(data.length / 16);100 const m = Math.ceil(data.length / 16);101 const r = data.length - n * 16;102 const cbcData = new Uint8Array((m + 1) * 16);103 cbcData.set(prefixBlock);104 cbcData.set(data, 16);105 if (r === 0) {106 for (let i = 0; i < 16; i++) {107 cbcData[n * 16 + i] ^= this._k1[i];108 }109 } else {110 cbcData[(n + 1) * 16 + r] = 0x80;111 for (let i = 0; i < 16; i++) {112 cbcData[(n + 1) * 16 + i] ^= this._k2[i];113 }114 }115 let cbcEncrypted = await window.crypto.subtle.encrypt({116 name: "AES-CBC",117 iv: this._zeroBlock,118 }, this._cbcKey, cbcData);119120 cbcEncrypted = new Uint8Array(cbcEncrypted);121 const mac = cbcEncrypted.slice(cbcEncrypted.length - 32, cbcEncrypted.length - 16);122 return mac;123 }124125 static async importKey(key, _algorithm, _extractable, _keyUsages) {126 const cipher = new AESEAXCipher;127 await cipher._importKey(key);128 return cipher;129 }130131 async _importKey(key) {132 this._rawKey = key;133 this._ctrKey = await window.crypto.subtle.importKey(134 "raw", key, {name: "AES-CTR"}, false, ["encrypt", "decrypt"]);135 this._cbcKey = await window.crypto.subtle.importKey(136 "raw", key, {name: "AES-CBC"}, false, ["encrypt"]);137 await this._initCMAC();138 }139140 async encrypt(algorithm, message) {141 const ad = algorithm.additionalData;142 const nonce = algorithm.iv;143 const nCMAC = await this._computeCMAC(nonce, this._prefixBlock0);144 const encrypted = await this._encryptCTR(message, nCMAC);145 const adCMAC = await this._computeCMAC(ad, this._prefixBlock1);146 const mac = await this._computeCMAC(encrypted, this._prefixBlock2);147 for (let i = 0; i < 16; i++) {148 mac[i] ^= nCMAC[i] ^ adCMAC[i];149 }150 const res = new Uint8Array(16 + encrypted.length);151 res.set(encrypted);152 res.set(mac, encrypted.length);153 return res;154 }155156 async decrypt(algorithm, data) {157 const encrypted = data.slice(0, data.length - 16);158 const ad = algorithm.additionalData;159 const nonce = algorithm.iv;160 const mac = data.slice(data.length - 16);161 const nCMAC = await this._computeCMAC(nonce, this._prefixBlock0);162 const adCMAC = await this._computeCMAC(ad, this._prefixBlock1);163 const computedMac = await this._computeCMAC(encrypted, this._prefixBlock2);164 for (let i = 0; i < 16; i++) {165 computedMac[i] ^= nCMAC[i] ^ adCMAC[i];166 }167 if (computedMac.length !== mac.length) {168 return null;169 }170 for (let i = 0; i < mac.length; i++) {171 if (computedMac[i] !== mac[i]) {172 return null;173 }174 }175 const res = await this._decryptCTR(encrypted, nCMAC);176 return res;177 }178}179