Skip to content

Commit

Permalink
crypto: deprecate digest == null in PBKDF2
Browse files Browse the repository at this point in the history
I assume that permitting digest === null was unintentional when
digest === undefined was deprecated since their behavior was
equivalent. The sha1 default for digest === null has somehow made it
through refactoring of the PBKDF2 module multiple times, even though
digest === undefined has been EOL for some time now.

This change deprecates setting digest to null so we can fix the
behavior in Node.js 12 or so.

PR-URL: #22861
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
tniessen committed Sep 19, 2018
1 parent 92fd4fc commit 19ad6b8
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 11 deletions.
8 changes: 4 additions & 4 deletions doc/api/crypto.md
Original file line number Diff line number Diff line change
Expand Up @@ -1786,8 +1786,8 @@ otherwise `err` will be `null`. By default, the successfully generated
`derivedKey` will be passed to the callback as a [`Buffer`][]. An error will be
thrown if any of the input arguments specify invalid values or types.

If `digest` is `null`, `'sha1'` will be used. This behavior will be deprecated
in a future version of Node.js.
If `digest` is `null`, `'sha1'` will be used. This behavior is deprecated,
please specify a `digest` explicitely.

The `iterations` argument must be a number set as high as possible. The
higher the number of iterations, the more secure the derived key will be,
Expand Down Expand Up @@ -1852,8 +1852,8 @@ applied to derive a key of the requested byte length (`keylen`) from the
If an error occurs an `Error` will be thrown, otherwise the derived key will be
returned as a [`Buffer`][].

If `digest` is `null`, `'sha1'` will be used. This behavior will be deprecated
in a future version of Node.js.
If `digest` is `null`, `'sha1'` will be used. This behavior is deprecated,
please specify a `digest` explicitely.

The `iterations` argument must be a number set as high as possible. The
higher the number of iterations, the more secure the derived key will be,
Expand Down
17 changes: 12 additions & 5 deletions doc/api/deprecations.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,24 +227,31 @@ to the `constants` property exposed by the relevant module. For instance,
### DEP0009: crypto.pbkdf2 without digest
<!-- YAML
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/22861
description: Runtime deprecation (for `digest === null`).
- version: v8.0.0
pr-url: https://github.com/nodejs/node/pull/11305
description: End-of-Life.
description: End-of-Life (for `digest === undefined`).
- version: v6.12.0
pr-url: https://github.com/nodejs/node/pull/10116
description: A deprecation code has been assigned.
- version: v6.0.0
pr-url: https://github.com/nodejs/node/pull/4047
description: Runtime deprecation.
description: Runtime deprecation (for `digest === undefined`).
-->

Type: End-of-Life
Type: Runtime

Use of the [`crypto.pbkdf2()`][] API without specifying a digest was deprecated
in Node.js 6.0 because the method defaulted to using the non-recommended
`'SHA1'` digest. Previously, a deprecation warning was printed. Starting in
Node.js 8.0.0, calling `crypto.pbkdf2()` or `crypto.pbkdf2Sync()` with an
undefined `digest` will throw a `TypeError`.
Node.js 8.0.0, calling `crypto.pbkdf2()` or `crypto.pbkdf2Sync()` with
`digest` set to `undefined` will throw a `TypeError`.

Beginning in Node.js REPLACEME, calling these functions with `digest` set to
`null` will print a deprecation warning to align with the behavior when `digest`
is `undefined`.

<a id="DEP0010"></a>
### DEP0010: crypto.createCredentials
Expand Down
8 changes: 7 additions & 1 deletion lib/internal/crypto/pbkdf2.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ 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,
Expand Down Expand Up @@ -51,11 +52,16 @@ function pbkdf2Sync(password, salt, iterations, keylen, digest) {
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 = 'sha1';
digest = defaultDigest();
}

password = validateArrayBufferView(password, 'password');
Expand Down
7 changes: 6 additions & 1 deletion test/parallel/test-crypto-pbkdf2.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ if (!common.hasCrypto)
const assert = require('assert');
const crypto = require('crypto');

common.expectWarning(
'DeprecationWarning',
'Calling pbkdf2 or pbkdf2Sync with "digest" set to null is deprecated.',
'DEP0009');

//
// Test PBKDF2 with RFC 6070 test vectors (except #4)
//
Expand Down Expand Up @@ -64,7 +69,7 @@ assert.throws(
);

assert.throws(
() => crypto.pbkdf2Sync('password', 'salt', -1, 20, null),
() => crypto.pbkdf2Sync('password', 'salt', -1, 20, 'sha1'),
{
code: 'ERR_OUT_OF_RANGE',
name: 'RangeError [ERR_OUT_OF_RANGE]',
Expand Down

0 comments on commit 19ad6b8

Please sign in to comment.