mirror of
https://github.com/Instadapp/Swap-Aggregator-Subgraph.git
synced 2024-07-29 21:57:12 +00:00
184 lines
6.1 KiB
JavaScript
Executable File
184 lines
6.1 KiB
JavaScript
Executable File
import { AES_asm } from './aes.asm';
|
|
import { _heap_init, _heap_write, is_bytes } from '../other/utils';
|
|
import { IllegalArgumentError, SecurityError } from '../other/errors';
|
|
export class AES {
|
|
constructor(key, iv, padding = true, mode) {
|
|
this.pos = 0;
|
|
this.len = 0;
|
|
this.mode = mode;
|
|
// The AES "worker"
|
|
this.heap = _heap_init().subarray(AES_asm.HEAP_DATA);
|
|
this.asm = new AES_asm(null, this.heap.buffer);
|
|
// The AES object state
|
|
this.pos = 0;
|
|
this.len = 0;
|
|
// Key
|
|
const keylen = key.length;
|
|
if (keylen !== 16 && keylen !== 24 && keylen !== 32)
|
|
throw new IllegalArgumentError('illegal key size');
|
|
const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength);
|
|
this.asm.set_key(keylen >> 2, keyview.getUint32(0), keyview.getUint32(4), keyview.getUint32(8), keyview.getUint32(12), keylen > 16 ? keyview.getUint32(16) : 0, keylen > 16 ? keyview.getUint32(20) : 0, keylen > 24 ? keyview.getUint32(24) : 0, keylen > 24 ? keyview.getUint32(28) : 0);
|
|
// IV
|
|
if (iv !== undefined) {
|
|
if (iv.length !== 16)
|
|
throw new IllegalArgumentError('illegal iv size');
|
|
let ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength);
|
|
this.asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12));
|
|
}
|
|
else {
|
|
this.asm.set_iv(0, 0, 0, 0);
|
|
}
|
|
this.padding = padding;
|
|
}
|
|
AES_Encrypt_process(data) {
|
|
if (!is_bytes(data))
|
|
throw new TypeError("data isn't of expected type");
|
|
let asm = this.asm;
|
|
let heap = this.heap;
|
|
let amode = AES_asm.ENC[this.mode];
|
|
let hpos = AES_asm.HEAP_DATA;
|
|
let pos = this.pos;
|
|
let len = this.len;
|
|
let dpos = 0;
|
|
let dlen = data.length || 0;
|
|
let rpos = 0;
|
|
let rlen = (len + dlen) & -16;
|
|
let wlen = 0;
|
|
let result = new Uint8Array(rlen);
|
|
while (dlen > 0) {
|
|
wlen = _heap_write(heap, pos + len, data, dpos, dlen);
|
|
len += wlen;
|
|
dpos += wlen;
|
|
dlen -= wlen;
|
|
wlen = asm.cipher(amode, hpos + pos, len);
|
|
if (wlen)
|
|
result.set(heap.subarray(pos, pos + wlen), rpos);
|
|
rpos += wlen;
|
|
if (wlen < len) {
|
|
pos += wlen;
|
|
len -= wlen;
|
|
}
|
|
else {
|
|
pos = 0;
|
|
len = 0;
|
|
}
|
|
}
|
|
this.pos = pos;
|
|
this.len = len;
|
|
return result;
|
|
}
|
|
AES_Encrypt_finish() {
|
|
let asm = this.asm;
|
|
let heap = this.heap;
|
|
let amode = AES_asm.ENC[this.mode];
|
|
let hpos = AES_asm.HEAP_DATA;
|
|
let pos = this.pos;
|
|
let len = this.len;
|
|
let plen = 16 - (len % 16);
|
|
let rlen = len;
|
|
if (this.hasOwnProperty('padding')) {
|
|
if (this.padding) {
|
|
for (let p = 0; p < plen; ++p) {
|
|
heap[pos + len + p] = plen;
|
|
}
|
|
len += plen;
|
|
rlen = len;
|
|
}
|
|
else if (len % 16) {
|
|
throw new IllegalArgumentError('data length must be a multiple of the block size');
|
|
}
|
|
}
|
|
else {
|
|
len += plen;
|
|
}
|
|
const result = new Uint8Array(rlen);
|
|
if (len)
|
|
asm.cipher(amode, hpos + pos, len);
|
|
if (rlen)
|
|
result.set(heap.subarray(pos, pos + rlen));
|
|
this.pos = 0;
|
|
this.len = 0;
|
|
return result;
|
|
}
|
|
AES_Decrypt_process(data) {
|
|
if (!is_bytes(data))
|
|
throw new TypeError("data isn't of expected type");
|
|
let asm = this.asm;
|
|
let heap = this.heap;
|
|
let amode = AES_asm.DEC[this.mode];
|
|
let hpos = AES_asm.HEAP_DATA;
|
|
let pos = this.pos;
|
|
let len = this.len;
|
|
let dpos = 0;
|
|
let dlen = data.length || 0;
|
|
let rpos = 0;
|
|
let rlen = (len + dlen) & -16;
|
|
let plen = 0;
|
|
let wlen = 0;
|
|
if (this.padding) {
|
|
plen = len + dlen - rlen || 16;
|
|
rlen -= plen;
|
|
}
|
|
const result = new Uint8Array(rlen);
|
|
while (dlen > 0) {
|
|
wlen = _heap_write(heap, pos + len, data, dpos, dlen);
|
|
len += wlen;
|
|
dpos += wlen;
|
|
dlen -= wlen;
|
|
wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0));
|
|
if (wlen)
|
|
result.set(heap.subarray(pos, pos + wlen), rpos);
|
|
rpos += wlen;
|
|
if (wlen < len) {
|
|
pos += wlen;
|
|
len -= wlen;
|
|
}
|
|
else {
|
|
pos = 0;
|
|
len = 0;
|
|
}
|
|
}
|
|
this.pos = pos;
|
|
this.len = len;
|
|
return result;
|
|
}
|
|
AES_Decrypt_finish() {
|
|
let asm = this.asm;
|
|
let heap = this.heap;
|
|
let amode = AES_asm.DEC[this.mode];
|
|
let hpos = AES_asm.HEAP_DATA;
|
|
let pos = this.pos;
|
|
let len = this.len;
|
|
let rlen = len;
|
|
if (len > 0) {
|
|
if (len % 16) {
|
|
if (this.hasOwnProperty('padding')) {
|
|
throw new IllegalArgumentError('data length must be a multiple of the block size');
|
|
}
|
|
else {
|
|
len += 16 - (len % 16);
|
|
}
|
|
}
|
|
asm.cipher(amode, hpos + pos, len);
|
|
if (this.hasOwnProperty('padding') && this.padding) {
|
|
let pad = heap[pos + rlen - 1];
|
|
if (pad < 1 || pad > 16 || pad > rlen)
|
|
throw new SecurityError('bad padding');
|
|
let pcheck = 0;
|
|
for (let i = pad; i > 1; i--)
|
|
pcheck |= pad ^ heap[pos + rlen - i];
|
|
if (pcheck)
|
|
throw new SecurityError('bad padding');
|
|
rlen -= pad;
|
|
}
|
|
}
|
|
const result = new Uint8Array(rlen);
|
|
if (rlen > 0) {
|
|
result.set(heap.subarray(pos, pos + rlen));
|
|
}
|
|
this.pos = 0;
|
|
this.len = 0;
|
|
return result;
|
|
}
|
|
}
|