nstdlib-nightly
Version:
Node.js standard library converted to runtime-agnostic ES modules.
136 lines (118 loc) • 3.46 kB
JavaScript
// Source: https://github.com/nodejs/node/blob/65eff1eb/lib/internal/crypto/scrypt.js
import { Buffer } from "nstdlib/lib/buffer";
import {
ScryptJob,
kCryptoJobAsync,
kCryptoJobSync,
} from "nstdlib/stub/binding/crypto";
import {
validateFunction,
validateInteger,
validateInt32,
validateUint32,
} from "nstdlib/lib/internal/validators";
import { codes as __codes__ } from "nstdlib/lib/internal/errors";
import { getArrayBufferOrView } from "nstdlib/lib/internal/crypto/util";
const { ERR_CRYPTO_SCRYPT_INVALID_PARAMETER, ERR_CRYPTO_SCRYPT_NOT_SUPPORTED } =
__codes__;
const defaults = {
N: 16384,
r: 8,
p: 1,
maxmem: 32 << 20, // 32 MiB, matches SCRYPT_MAX_MEM.
};
function scrypt(password, salt, keylen, options, callback = defaults) {
if (callback === defaults) {
callback = options;
options = defaults;
}
options = check(password, salt, keylen, options);
const { N, r, p, maxmem } = options;
({ password, salt, keylen } = options);
validateFunction(callback, "callback");
const job = new ScryptJob(
kCryptoJobAsync,
password,
salt,
N,
r,
p,
maxmem,
keylen,
);
job.ondone = (error, result) => {
if (error !== undefined)
return Function.prototype.call.call(callback, job, error);
const buf = Buffer.from(result);
return Function.prototype.call.call(callback, job, null, buf);
};
job.run();
}
function scryptSync(password, salt, keylen, options = defaults) {
options = check(password, salt, keylen, options);
const { N, r, p, maxmem } = options;
({ password, salt, keylen } = options);
const job = new ScryptJob(
kCryptoJobSync,
password,
salt,
N,
r,
p,
maxmem,
keylen,
);
const { 0: err, 1: result } = job.run();
if (err !== undefined) throw err;
return Buffer.from(result);
}
function check(password, salt, keylen, options) {
if (ScryptJob === undefined) throw new ERR_CRYPTO_SCRYPT_NOT_SUPPORTED();
password = getArrayBufferOrView(password, "password");
salt = getArrayBufferOrView(salt, "salt");
validateInt32(keylen, "keylen", 0);
let { N, r, p, maxmem } = defaults;
if (options && options !== defaults) {
const has_N = options.N !== undefined;
if (has_N) {
N = options.N;
validateUint32(N, "N");
}
if (options.cost !== undefined) {
if (has_N) throw new ERR_CRYPTO_SCRYPT_INVALID_PARAMETER();
N = options.cost;
validateUint32(N, "cost");
}
const has_r = options.r !== undefined;
if (has_r) {
r = options.r;
validateUint32(r, "r");
}
if (options.blockSize !== undefined) {
if (has_r) throw new ERR_CRYPTO_SCRYPT_INVALID_PARAMETER();
r = options.blockSize;
validateUint32(r, "blockSize");
}
const has_p = options.p !== undefined;
if (has_p) {
p = options.p;
validateUint32(p, "p");
}
if (options.parallelization !== undefined) {
if (has_p) throw new ERR_CRYPTO_SCRYPT_INVALID_PARAMETER();
p = options.parallelization;
validateUint32(p, "parallelization");
}
if (options.maxmem !== undefined) {
maxmem = options.maxmem;
validateInteger(maxmem, "maxmem", 0);
}
if (N === 0) N = defaults.N;
if (r === 0) r = defaults.r;
if (p === 0) p = defaults.p;
if (maxmem === 0) maxmem = defaults.maxmem;
}
return { password, salt, keylen, N, r, p, maxmem };
}
export { scrypt };
export { scryptSync };