node/lib/internal/crypto/pbkdf2.js
Gus Caplan e7f710c1d4 bootstrapper: move internalBinding to NativeModule
internalBinding is used so often that it should just automatically be
available for usage in internals.

PR-URL: https://github.com/nodejs/node/pull/23025
Refs: https://github.com/nodejs/node/commit/2a9eb31
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
2018-10-04 11:55:34 +02:00

88 lines
2.8 KiB
JavaScript

'use strict';
const { AsyncWrap, Providers } = internalBinding('async_wrap');
const { Buffer } = require('buffer');
const { pbkdf2: _pbkdf2 } = internalBinding('crypto');
const { validateUint32 } = require('internal/validators');
const { deprecate } = require('internal/util');
const {
ERR_CRYPTO_INVALID_DIGEST,
ERR_CRYPTO_PBKDF2_ERROR,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_CALLBACK,
} = require('internal/errors').codes;
const {
getDefaultEncoding,
validateArrayBufferView,
} = require('internal/crypto/util');
function pbkdf2(password, salt, iterations, keylen, digest, callback) {
if (typeof digest === 'function') {
callback = digest;
digest = undefined;
}
({ password, salt, iterations, keylen, digest } =
check(password, salt, iterations, keylen, digest));
if (typeof callback !== 'function')
throw new ERR_INVALID_CALLBACK();
const encoding = getDefaultEncoding();
const keybuf = Buffer.alloc(keylen);
const wrap = new AsyncWrap(Providers.PBKDF2REQUEST);
wrap.ondone = (ok) => { // Retains keybuf while request is in flight.
if (!ok) return callback.call(wrap, new ERR_CRYPTO_PBKDF2_ERROR());
if (encoding === 'buffer') return callback.call(wrap, null, keybuf);
callback.call(wrap, null, keybuf.toString(encoding));
};
handleError(keybuf, password, salt, iterations, digest, wrap);
}
function pbkdf2Sync(password, salt, iterations, keylen, digest) {
({ password, salt, iterations, keylen, digest } =
check(password, salt, iterations, keylen, digest));
const keybuf = Buffer.alloc(keylen);
handleError(keybuf, password, salt, iterations, digest);
const encoding = getDefaultEncoding();
if (encoding === 'buffer') return keybuf;
return keybuf.toString(encoding);
}
const defaultDigest = deprecate(() => 'sha1',
'Calling pbkdf2 or pbkdf2Sync with "digest" ' +
'set to null is deprecated.',
'DEP0009');
function check(password, salt, iterations, keylen, digest) {
if (typeof digest !== 'string') {
if (digest !== null)
throw new ERR_INVALID_ARG_TYPE('digest', ['string', 'null'], digest);
digest = defaultDigest();
}
password = validateArrayBufferView(password, 'password');
salt = validateArrayBufferView(salt, 'salt');
iterations = validateUint32(iterations, 'iterations', 0);
keylen = validateUint32(keylen, 'keylen', 0);
return { password, salt, iterations, keylen, digest };
}
function handleError(keybuf, password, salt, iterations, digest, wrap) {
const rc = _pbkdf2(keybuf, password, salt, iterations, digest, wrap);
if (rc === -1)
throw new ERR_CRYPTO_INVALID_DIGEST(digest);
if (rc === false)
throw new ERR_CRYPTO_PBKDF2_ERROR();
}
module.exports = {
pbkdf2,
pbkdf2Sync
};