diff options
Diffstat (limited to 'ext/node/polyfills/internal/crypto/scrypt.ts')
-rw-r--r-- | ext/node/polyfills/internal/crypto/scrypt.ts | 210 |
1 files changed, 32 insertions, 178 deletions
diff --git a/ext/node/polyfills/internal/crypto/scrypt.ts b/ext/node/polyfills/internal/crypto/scrypt.ts index 5e6586906..438335531 100644 --- a/ext/node/polyfills/internal/crypto/scrypt.ts +++ b/ext/node/polyfills/internal/crypto/scrypt.ts @@ -24,9 +24,11 @@ SOFTWARE. */ import { Buffer } from "ext:deno_node/buffer.ts"; -import { pbkdf2Sync as pbkdf2 } from "ext:deno_node/internal/crypto/pbkdf2.ts"; import { HASH_DATA } from "ext:deno_node/internal/crypto/types.ts"; +const { core } = globalThis.__bootstrap; +const { ops } = core; + type Opts = Partial<{ N: number; cost: number; @@ -55,166 +57,6 @@ const fixOpts = (opts?: Opts) => { return out; }; -function blockxor(S: Buffer, Si: number, D: Buffer, Di: number, len: number) { - let i = -1; - while (++i < len) D[Di + i] ^= S[Si + i]; -} -function arraycopy( - src: Buffer, - srcPos: number, - dest: Buffer, - destPos: number, - length: number, -) { - src.copy(dest, destPos, srcPos, srcPos + length); -} - -const R = (a: number, b: number) => (a << b) | (a >>> (32 - b)); - -class ScryptRom { - B: Buffer; - r: number; - N: number; - p: number; - XY: Buffer; - V: Buffer; - B32: Int32Array; - x: Int32Array; - _X: Buffer; - constructor(b: Buffer, r: number, N: number, p: number) { - this.B = b; - this.r = r; - this.N = N; - this.p = p; - this.XY = Buffer.allocUnsafe(256 * r); - this.V = Buffer.allocUnsafe(128 * r * N); - this.B32 = new Int32Array(16); // salsa20_8 - this.x = new Int32Array(16); // salsa20_8 - this._X = Buffer.allocUnsafe(64); // blockmix_salsa8 - } - - run() { - const p = this.p | 0; - const r = this.r | 0; - for (let i = 0; i < p; i++) this.scryptROMix(i, r); - - return this.B; - } - - scryptROMix(i: number, r: number) { - const blockStart = i * 128 * r; - const offset = (2 * r - 1) * 64; - const blockLen = 128 * r; - const B = this.B; - const N = this.N | 0; - const V = this.V; - const XY = this.XY; - B.copy(XY, 0, blockStart, blockStart + blockLen); - for (let i1 = 0; i1 < N; i1++) { - XY.copy(V, i1 * blockLen, 0, blockLen); - this.blockmix_salsa8(blockLen); - } - - let j: number; - for (let i2 = 0; i2 < N; i2++) { - j = XY.readUInt32LE(offset) & (N - 1); - blockxor(V, j * blockLen, XY, 0, blockLen); - this.blockmix_salsa8(blockLen); - } - XY.copy(B, blockStart, 0, blockLen); - } - - blockmix_salsa8(blockLen: number) { - const BY = this.XY; - const r = this.r; - const _X = this._X; - arraycopy(BY, (2 * r - 1) * 64, _X, 0, 64); - let i; - for (i = 0; i < 2 * r; i++) { - blockxor(BY, i * 64, _X, 0, 64); - this.salsa20_8(); - arraycopy(_X, 0, BY, blockLen + i * 64, 64); - } - for (i = 0; i < r; i++) { - arraycopy(BY, blockLen + i * 2 * 64, BY, i * 64, 64); - arraycopy(BY, blockLen + (i * 2 + 1) * 64, BY, (i + r) * 64, 64); - } - } - - salsa20_8() { - const B32 = this.B32; - const B = this._X; - const x = this.x; - - let i; - for (i = 0; i < 16; i++) { - B32[i] = (B[i * 4 + 0] & 0xff) << 0; - B32[i] |= (B[i * 4 + 1] & 0xff) << 8; - B32[i] |= (B[i * 4 + 2] & 0xff) << 16; - B32[i] |= (B[i * 4 + 3] & 0xff) << 24; - } - - for (i = 0; i < 16; i++) x[i] = B32[i]; - - for (i = 0; i < 4; i++) { - x[4] ^= R(x[0] + x[12], 7); - x[8] ^= R(x[4] + x[0], 9); - x[12] ^= R(x[8] + x[4], 13); - x[0] ^= R(x[12] + x[8], 18); - x[9] ^= R(x[5] + x[1], 7); - x[13] ^= R(x[9] + x[5], 9); - x[1] ^= R(x[13] + x[9], 13); - x[5] ^= R(x[1] + x[13], 18); - x[14] ^= R(x[10] + x[6], 7); - x[2] ^= R(x[14] + x[10], 9); - x[6] ^= R(x[2] + x[14], 13); - x[10] ^= R(x[6] + x[2], 18); - x[3] ^= R(x[15] + x[11], 7); - x[7] ^= R(x[3] + x[15], 9); - x[11] ^= R(x[7] + x[3], 13); - x[15] ^= R(x[11] + x[7], 18); - x[1] ^= R(x[0] + x[3], 7); - x[2] ^= R(x[1] + x[0], 9); - x[3] ^= R(x[2] + x[1], 13); - x[0] ^= R(x[3] + x[2], 18); - x[6] ^= R(x[5] + x[4], 7); - x[7] ^= R(x[6] + x[5], 9); - x[4] ^= R(x[7] + x[6], 13); - x[5] ^= R(x[4] + x[7], 18); - x[11] ^= R(x[10] + x[9], 7); - x[8] ^= R(x[11] + x[10], 9); - x[9] ^= R(x[8] + x[11], 13); - x[10] ^= R(x[9] + x[8], 18); - x[12] ^= R(x[15] + x[14], 7); - x[13] ^= R(x[12] + x[15], 9); - x[14] ^= R(x[13] + x[12], 13); - x[15] ^= R(x[14] + x[13], 18); - } - for (i = 0; i < 16; i++) B32[i] += x[i]; - - let bi; - - for (i = 0; i < 16; i++) { - bi = i * 4; - B[bi + 0] = (B32[i] >> 0) & 0xff; - B[bi + 1] = (B32[i] >> 8) & 0xff; - B[bi + 2] = (B32[i] >> 16) & 0xff; - B[bi + 3] = (B32[i] >> 24) & 0xff; - } - } - - clean() { - this.XY.fill(0); - this.V.fill(0); - this._X.fill(0); - this.B.fill(0); - for (let i = 0; i < 16; i++) { - this.B32[i] = 0; - this.x[i] = 0; - } - } -} - export function scryptSync( password: HASH_DATA, salt: HASH_DATA, @@ -226,17 +68,22 @@ export function scryptSync( const blen = p * 128 * r; if (32 * r * (N + 2) * 4 + blen > maxmem) { - throw new Error("excedes max memory"); + throw new Error("exceeds max memory"); } - const b = pbkdf2(password, salt, 1, blen, "sha256"); - - const scryptRom = new ScryptRom(b, r, N, p); - const out = scryptRom.run(); - - const fin = pbkdf2(password, out, 1, keylen, "sha256"); - scryptRom.clean(); - return fin; + const buf = Buffer.alloc(keylen); + ops.op_node_scrypt_sync( + password, + salt, + keylen, + Math.log2(N), + r, + p, + maxmem, + buf.buffer, + ); + + return buf; } type Callback = (err: unknown, result?: Buffer) => void; @@ -256,17 +103,24 @@ export function scrypt( const blen = p * 128 * r; if (32 * r * (N + 2) * 4 + blen > maxmem) { - throw new Error("excedes max memory"); + throw new Error("exceeds max memory"); } try { - const b = pbkdf2(password, salt, 1, blen, "sha256"); - - const scryptRom = new ScryptRom(b, r, N, p); - const out = scryptRom.run(); - const result = pbkdf2(password, out, 1, keylen, "sha256"); - scryptRom.clean(); - cb(null, result); + core.opAsync( + "op_node_scrypt_async", + password, + salt, + keylen, + Math.log2(N), + r, + p, + maxmem, + ).then( + (buf: Uint8Array) => { + cb(null, Buffer.from(buf.buffer)); + }, + ); } catch (err: unknown) { return cb(err); } |