summaryrefslogtreecommitdiff
path: root/ext/node/polyfills/internal/crypto/scrypt.ts
diff options
context:
space:
mode:
Diffstat (limited to 'ext/node/polyfills/internal/crypto/scrypt.ts')
-rw-r--r--ext/node/polyfills/internal/crypto/scrypt.ts210
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);
}