diff --git a/src/aes/aes.ts b/src/aes/aes.ts index 54635d3..98fe657 100644 --- a/src/aes/aes.ts +++ b/src/aes/aes.ts @@ -2,6 +2,9 @@ import { AES_asm, AES_mode } from './aes.asm'; import { _heap_init, _heap_write, is_bytes } from '../other/utils'; import { IllegalArgumentError, SecurityError } from '../other/errors'; +const heap_pool = []; +const asm_pool = []; + export abstract class AES { protected readonly heap: Uint8Array; protected readonly asm: AES_asm; @@ -13,14 +16,34 @@ export abstract class AES { protected constructor(key: Uint8Array, iv: Uint8Array | undefined, padding = true, mode: AES_mode) { 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; + this.key = key; + this.iv = iv; + this.padding = padding; + + // The AES "worker" + this.acquire_asm(); + } + + protected acquire_asm() { + if (this.heap === undefined && this.asm === undefined) { + this.heap = heap_pool.pop() || _heap_init().subarray(AES_asm.HEAP_DATA); + this.asm = asm_pool.pop() || AES_asm(null, this.heap.buffer); + this.reset(this.key, this.iv); + } + } + + protected release_asm() { + heap_pool.push(this.heap)); + asm_pool.push(this.asm); + this.heap = undefined; + this.asm = undefined; + } + + protected reset(key, iv) { // Key const keylen = key.length; if (keylen !== 16 && keylen !== 24 && keylen !== 32) throw new IllegalArgumentError('illegal key size'); @@ -48,13 +71,13 @@ export abstract class AES { } else { this.asm.set_iv(0, 0, 0, 0); } - - this.padding = padding; } AES_Encrypt_process(data: Uint8Array): Uint8Array { if (!is_bytes(data)) throw new TypeError("data isn't of expected type"); + this.acquire_asm(); + let asm = this.asm; let heap = this.heap; let amode = AES_asm.ENC[this.mode]; @@ -96,6 +119,8 @@ export abstract class AES { } AES_Encrypt_finish(): Uint8Array { + this.acquire_asm(); + let asm = this.asm; let heap = this.heap; let amode = AES_asm.ENC[this.mode]; @@ -128,12 +153,16 @@ export abstract class AES { this.pos = 0; this.len = 0; + this.release_asm(); + return result; } AES_Decrypt_process(data: Uint8Array): Uint8Array { if (!is_bytes(data)) throw new TypeError("data isn't of expected type"); + this.acquire_asm(); + let asm = this.asm; let heap = this.heap; let amode = AES_asm.DEC[this.mode]; @@ -181,6 +210,8 @@ export abstract class AES { } AES_Decrypt_finish(): Uint8Array { + this.acquire_asm(); + let asm = this.asm; let heap = this.heap; let amode = AES_asm.DEC[this.mode]; @@ -221,6 +252,8 @@ export abstract class AES { this.pos = 0; this.len = 0; + this.release_asm(); + return result; } } diff --git a/src/hash/hash.ts b/src/hash/hash.ts index 52f112e..735a3a2 100644 --- a/src/hash/hash.ts +++ b/src/hash/hash.ts @@ -1,4 +1,4 @@ -import { _heap_write } from '../other/utils'; +import { _heap_init, _heap_write } from '../other/utils'; import { IllegalStateError } from '../other/errors'; import { sha1result } from './sha1/sha1.asm'; import { sha256result } from './sha256/sha256.asm'; @@ -13,7 +13,32 @@ export abstract class Hash { public BLOCK_SIZE!: number; public HASH_SIZE!: number; + protected static heap_pool !: Array; + protected static asm_pool !: Array; + protected static asm_function!: Function; + + constructor() { + this.acquire_asm(); + } + + protected acquire_asm() { + if (this.heap === undefined && this.asm === undefined) { + this.heap = this.constructor.heap_pool.pop() || _heap_init(); + this.asm = this.constructor.asm_pool.pop() || this.constructor.asm_function({ Uint8Array: Uint8Array }, null, this.heap.buffer); + this.reset(); + } + } + + protected release_asm() { + this.constructor.heap_pool.push(this.heap)); + this.constructor.asm_pool.push(this.asm); + this.heap = undefined; + this.asm = undefined; + } + reset() { + this.acquire_asm(); + this.result = null; this.pos = 0; this.len = 0; @@ -26,6 +51,8 @@ export abstract class Hash { process(data: Uint8Array) { if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data'); + this.acquire_asm(); + let asm = this.asm; let heap = this.heap; let hpos = this.pos; @@ -57,6 +84,8 @@ export abstract class Hash { finish() { if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data'); + this.acquire_asm(); + this.asm.finish(this.pos, this.len, 0); this.result = new Uint8Array(this.HASH_SIZE); @@ -65,6 +94,8 @@ export abstract class Hash { this.pos = 0; this.len = 0; + this.release_asm(); + return this; } } diff --git a/src/hash/sha1/sha1.ts b/src/hash/sha1/sha1.ts index 55d1292..33c2f95 100644 --- a/src/hash/sha1/sha1.ts +++ b/src/hash/sha1/sha1.ts @@ -1,6 +1,5 @@ import { sha1_asm, sha1result } from './sha1.asm'; import { Hash } from '../hash'; -import { _heap_init } from '../../other/utils'; export const _sha1_block_size = 64; export const _sha1_hash_size = 20; @@ -11,12 +10,7 @@ export class Sha1 extends Hash { public BLOCK_SIZE = _sha1_block_size; public HASH_SIZE = _sha1_hash_size; - constructor() { - super(); - - this.heap = _heap_init(); - this.asm = sha1_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); - - this.reset(); - } + protected static heap_pool = []; + protected static asm_pool = []; + protected static asm_function = sha1_asm; } diff --git a/src/hash/sha256/sha256.ts b/src/hash/sha256/sha256.ts index 885d773..32b9adb 100644 --- a/src/hash/sha256/sha256.ts +++ b/src/hash/sha256/sha256.ts @@ -1,6 +1,5 @@ import { sha256_asm, sha256result } from './sha256.asm'; import { Hash } from '../hash'; -import { _heap_init } from '../../other/utils'; export const _sha256_block_size = 64; export const _sha256_hash_size = 32; @@ -11,12 +10,7 @@ export class Sha256 extends Hash { public BLOCK_SIZE = _sha256_block_size; public HASH_SIZE = _sha256_hash_size; - constructor() { - super(); - - this.heap = _heap_init(); - this.asm = sha256_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); - - this.reset(); - } + protected static heap_pool = []; + protected static asm_pool = []; + protected static asm_function = sha256_asm; } diff --git a/src/hash/sha512/sha512.ts b/src/hash/sha512/sha512.ts index ddaaa42..0c2191e 100644 --- a/src/hash/sha512/sha512.ts +++ b/src/hash/sha512/sha512.ts @@ -1,6 +1,5 @@ import { sha512_asm, sha512result } from './sha512.asm'; import { Hash } from '../hash'; -import { _heap_init } from '../../other/utils'; export const _sha512_block_size = 128; export const _sha512_hash_size = 64; @@ -11,12 +10,7 @@ export class Sha512 extends Hash { public BLOCK_SIZE = _sha512_block_size; public HASH_SIZE = _sha512_hash_size; - constructor() { - super(); - - this.heap = _heap_init(); - this.asm = sha512_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer); - - this.reset(); - } + protected static heap_pool = []; + protected static asm_pool = []; + protected static asm_function = sha512_asm; }