Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto: add scrypt() and scryptSync() methods #20816

Merged
merged 8 commits into from
Jun 13, 2018
Next Next commit
crypto: DRY type checking
Factor out some common code.  The `checkUint()` function will also be
used in a follow-up commit that adds scrypt support to core.

PR-URL: #20816
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
  • Loading branch information
bnoordhuis committed Jun 13, 2018
commit 58176e352c7b4fe6042fc31283a79d8de4cdb569
28 changes: 7 additions & 21 deletions lib/internal/crypto/pbkdf2.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,15 @@ const {
ERR_INVALID_ARG_TYPE,
ERR_INVALID_CALLBACK,
ERR_CRYPTO_INVALID_DIGEST,
ERR_OUT_OF_RANGE
} = require('internal/errors').codes;
const {
checkIsArrayBufferView,
checkIsUint,
getDefaultEncoding,
toBuf
} = require('internal/crypto/util');
const {
PBKDF2
} = process.binding('crypto');
const {
INT_MAX
} = process.binding('constants').crypto;

function pbkdf2(password, salt, iterations, keylen, digest, callback) {
if (typeof digest === 'function') {
Expand All @@ -39,22 +35,12 @@ function _pbkdf2(password, salt, iterations, keylen, digest, callback) {
if (digest !== null && typeof digest !== 'string')
throw new ERR_INVALID_ARG_TYPE('digest', ['string', 'null'], digest);

password = checkIsArrayBufferView('password', toBuf(password));
salt = checkIsArrayBufferView('salt', toBuf(salt));

if (typeof iterations !== 'number')
throw new ERR_INVALID_ARG_TYPE('iterations', 'number', iterations);

if (iterations < 0)
throw new ERR_OUT_OF_RANGE('iterations',
'a non-negative number',
iterations);

if (typeof keylen !== 'number')
throw new ERR_INVALID_ARG_TYPE('keylen', 'number', keylen);

if (keylen < 0 || !Number.isInteger(keylen) || keylen > INT_MAX)
throw new ERR_OUT_OF_RANGE('keylen', `>= 0 && <= ${INT_MAX}`, keylen);
password = checkIsArrayBufferView('password', password);
salt = checkIsArrayBufferView('salt', salt);
// FIXME(bnoordhuis) The error message is in fact wrong since |iterations|
// cannot be > INT_MAX. Adjust in the next major release.
iterations = checkIsUint('iterations', iterations, 'a non-negative number');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m not sure we’d actually have to consider this semver-major anymore.

keylen = checkIsUint('keylen', keylen);

const encoding = getDefaultEncoding();

Expand Down
4 changes: 2 additions & 2 deletions lib/internal/crypto/sig.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Sign.prototype.sign = function sign(options, encoding) {

var pssSaltLength = getSaltLength(options);

key = checkIsArrayBufferView('key', toBuf(key));
key = checkIsArrayBufferView('key', key);

var ret = this._handle.sign(key, passphrase, rsaPadding, pssSaltLength);

Expand Down Expand Up @@ -114,7 +114,7 @@ Verify.prototype.verify = function verify(options, signature, sigEncoding) {

var pssSaltLength = getSaltLength(options);

key = checkIsArrayBufferView('key', toBuf(key));
key = checkIsArrayBufferView('key', key);

signature = checkIsArrayBufferView('signature',
toBuf(signature, sigEncoding));
Expand Down
18 changes: 17 additions & 1 deletion lib/internal/crypto/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const {
const {
ERR_CRYPTO_ENGINE_UNKNOWN,
ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH,
ERR_INVALID_ARG_TYPE
ERR_INVALID_ARG_TYPE,
ERR_OUT_OF_RANGE,
} = require('internal/errors').codes;
const { Buffer } = require('buffer');
const {
Expand All @@ -25,6 +26,9 @@ const {
const {
isArrayBufferView
} = require('internal/util/types');
const {
INT_MAX
} = process.binding('constants').crypto;

var defaultEncoding = 'buffer';

Expand Down Expand Up @@ -84,6 +88,7 @@ function timingSafeEqual(buf1, buf2) {
}

function checkIsArrayBufferView(name, buffer) {
buffer = toBuf(buffer);
if (!isArrayBufferView(buffer)) {
throw new ERR_INVALID_ARG_TYPE(
name,
Expand All @@ -94,8 +99,19 @@ function checkIsArrayBufferView(name, buffer) {
return buffer;
}

function checkIsUint(name, value, errmsg = `>= 0 && <= ${INT_MAX}`) {
if (typeof value !== 'number')
throw new ERR_INVALID_ARG_TYPE(name, 'number', value);

if (value < 0 || !Number.isInteger(value) || value > INT_MAX)
throw new ERR_OUT_OF_RANGE(name, errmsg, value);

return value;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a validators file that already contains a check like this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateInt32 doesn't do quite the same thing but take a look at the second-to-last commit. This is with #20816 (comment) in mind.


module.exports = {
checkIsArrayBufferView,
checkIsUint,
getCiphers,
getCurves,
getDefaultEncoding,
Expand Down