From 365d5da36e6c9152068473a671a9f3b6e0ec2bf6 Mon Sep 17 00:00:00 2001 From: Tom Gallacher Date: Fri, 27 Nov 2015 10:41:38 +0000 Subject: [PATCH] crypto: pbkdf2 deprecate digest overload. As per #3292, this PR introduces a deprecation notice about removing the 'default digest' overload which currently defaults to the soon to be defunct SHA1 digest. Instead it should be left up to the documentation and implementor to suggest a suitable digest function. Ref: https://github.com/nodejs/node/pull/3292 PR-URL: https://github.com/nodejs/node/pull/4047 Reviewed-By: bnoordhuis - Ben Noordhuis Reviewed-By: James M Snell Reviewed-By: Fedor Indutny Reviewed-By: Shigeki Ohtsu --- doc/api/crypto.markdown | 10 +++---- lib/crypto.js | 10 +++++++ test/parallel/test-crypto-binary-default.js | 24 ++++++++-------- test/parallel/test-crypto-pbkdf2.js | 32 ++++++++++----------- 4 files changed, 42 insertions(+), 34 deletions(-) diff --git a/doc/api/crypto.markdown b/doc/api/crypto.markdown index ba1ba408955218..d3660dbd54708c 100644 --- a/doc/api/crypto.markdown +++ b/doc/api/crypto.markdown @@ -1071,13 +1071,12 @@ const hashes = crypto.getHashes(); console.log(hashes); // ['sha', 'sha1', 'sha1WithRSAEncryption', ...] ``` -### crypto.pbkdf2(password, salt, iterations, keylen[, digest], callback) +### crypto.pbkdf2(password, salt, iterations, keylen, digest, callback) Provides an asynchronous Password-Based Key Derivation Function 2 (PBKDF2) implementation. A selected HMAC digest algorithm specified by `digest` is applied to derive a key of the requested byte length (`keylen`) from the -`password`, `salt` and `iterations`. If the `digest` algorithm is not specified, -a default of `'sha1'` is used. +`password`, `salt` and `iterations`. The supplied `callback` function is called with two arguments: `err` and `derivedKey`. If an error occurs, `err` will be set; otherwise `err` will be @@ -1104,13 +1103,12 @@ crypto.pbkdf2('secret', 'salt', 100000, 512, 'sha512', (err, key) => { An array of supported digest functions can be retrieved using [`crypto.getHashes()`][]. -### crypto.pbkdf2Sync(password, salt, iterations, keylen[, digest]) +### crypto.pbkdf2Sync(password, salt, iterations, keylen, digest) Provides a synchronous Password-Based Key Derivation Function 2 (PBKDF2) implementation. A selected HMAC digest algorithm specified by `digest` is applied to derive a key of the requested byte length (`keylen`) from the -`password`, `salt` and `iterations`. If the `digest` algorithm is not specified, -a default of `'sha1'` is used. +`password`, `salt` and `iterations`. If an error occurs an Error will be thrown, otherwise the derived key will be returned as a [`Buffer`][]. diff --git a/lib/crypto.js b/lib/crypto.js index 2797ad99b3030f..29d5df4906dd8c 100644 --- a/lib/crypto.js +++ b/lib/crypto.js @@ -532,6 +532,11 @@ ECDH.prototype.getPublicKey = function getPublicKey(encoding, format) { }; +const pbkdf2DeprecationWarning = + internalUtil.deprecate(() => {}, 'crypto.pbkdf2 without specifying' + + ' a digest is deprecated. Please specify a digest'); + + exports.pbkdf2 = function(password, salt, iterations, @@ -541,6 +546,7 @@ exports.pbkdf2 = function(password, if (typeof digest === 'function') { callback = digest; digest = undefined; + pbkdf2DeprecationWarning(); } if (typeof callback !== 'function') @@ -551,6 +557,10 @@ exports.pbkdf2 = function(password, exports.pbkdf2Sync = function(password, salt, iterations, keylen, digest) { + if (typeof digest === 'undefined') { + digest = undefined; + pbkdf2DeprecationWarning(); + } return pbkdf2(password, salt, iterations, keylen, digest); }; diff --git a/test/parallel/test-crypto-binary-default.js b/test/parallel/test-crypto-binary-default.js index c4b8990beb2ec2..1ce64a40c8ed0d 100644 --- a/test/parallel/test-crypto-binary-default.js +++ b/test/parallel/test-crypto-binary-default.js @@ -633,34 +633,34 @@ assert.strictEqual(rsaVerify.verify(rsaPubPem, rsaSignature, 'hex'), true); // Test PBKDF2 with RFC 6070 test vectors (except #4) // function testPBKDF2(password, salt, iterations, keylen, expected) { - var actual = crypto.pbkdf2Sync(password, salt, iterations, keylen); + var actual = crypto.pbkdf2Sync(password, salt, iterations, keylen, 'sha256'); assert.equal(actual, expected); - crypto.pbkdf2(password, salt, iterations, keylen, function(err, actual) { + crypto.pbkdf2(password, salt, iterations, keylen, 'sha256', (err, actual) => { assert.equal(actual, expected); }); } testPBKDF2('password', 'salt', 1, 20, - '\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24' + - '\xaf\x60\x12\x06\x2f\xe0\x37\xa6'); + '\x12\x0f\xb6\xcf\xfc\xf8\xb3\x2c\x43\xe7\x22\x52' + + '\x56\xc4\xf8\x37\xa8\x65\x48\xc9'); testPBKDF2('password', 'salt', 2, 20, - '\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a' + - '\xce\x1d\x41\xf0\xd8\xde\x89\x57'); + '\xae\x4d\x0c\x95\xaf\x6b\x46\xd3\x2d\x0a\xdf\xf9' + + '\x28\xf0\x6d\xd0\x2a\x30\x3f\x8e'); testPBKDF2('password', 'salt', 4096, 20, - '\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26' + - '\xf7\x21\xd0\x65\xa4\x29\xc1'); + '\xc5\xe4\x78\xd5\x92\x88\xc8\x41\xaa\x53\x0d\xb6' + + '\x84\x5c\x4c\x8d\x96\x28\x93\xa0'); testPBKDF2('passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 4096, 25, - '\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8\xd8\x36\x62' + - '\xc0\xe4\x4a\x8b\x29\x1a\x96\x4c\xf2\xf0\x70\x38'); + '\x34\x8c\x89\xdb\xcb\xd3\x2b\x2f\x32\xd8\x14\xb8' + + '\x11\x6e\x84\xcf\x2b\x17\x34\x7e\xbc\x18\x00\x18\x1c'); testPBKDF2('pass\0word', 'sa\0lt', 4096, 16, - '\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37\xd7\xf0\x34' + - '\x25\xe0\xc3'); + '\x89\xb6\x9d\x05\x16\xf8\x29\x89\x3c\x69\x62\x26' + + '\x65\x0a\x86\x87'); diff --git a/test/parallel/test-crypto-pbkdf2.js b/test/parallel/test-crypto-pbkdf2.js index 39b98b38e2710e..cbea3dae4c0d04 100644 --- a/test/parallel/test-crypto-pbkdf2.js +++ b/test/parallel/test-crypto-pbkdf2.js @@ -12,37 +12,37 @@ var crypto = require('crypto'); // Test PBKDF2 with RFC 6070 test vectors (except #4) // function testPBKDF2(password, salt, iterations, keylen, expected) { - var actual = crypto.pbkdf2Sync(password, salt, iterations, keylen); + var actual = crypto.pbkdf2Sync(password, salt, iterations, keylen, 'sha256'); assert.equal(actual.toString('binary'), expected); - crypto.pbkdf2(password, salt, iterations, keylen, function(err, actual) { + crypto.pbkdf2(password, salt, iterations, keylen, 'sha256', (err, actual) => { assert.equal(actual.toString('binary'), expected); }); } testPBKDF2('password', 'salt', 1, 20, - '\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9\xb5\x24' + - '\xaf\x60\x12\x06\x2f\xe0\x37\xa6'); + '\x12\x0f\xb6\xcf\xfc\xf8\xb3\x2c\x43\xe7\x22\x52' + + '\x56\xc4\xf8\x37\xa8\x65\x48\xc9'); testPBKDF2('password', 'salt', 2, 20, - '\xea\x6c\x01\x4d\xc7\x2d\x6f\x8c\xcd\x1e\xd9\x2a' + - '\xce\x1d\x41\xf0\xd8\xde\x89\x57'); + '\xae\x4d\x0c\x95\xaf\x6b\x46\xd3\x2d\x0a\xdf\xf9' + + '\x28\xf0\x6d\xd0\x2a\x30\x3f\x8e'); testPBKDF2('password', 'salt', 4096, 20, - '\x4b\x00\x79\x01\xb7\x65\x48\x9a\xbe\xad\x49\xd9\x26' + - '\xf7\x21\xd0\x65\xa4\x29\xc1'); + '\xc5\xe4\x78\xd5\x92\x88\xc8\x41\xaa\x53\x0d\xb6' + + '\x84\x5c\x4c\x8d\x96\x28\x93\xa0'); testPBKDF2('passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 4096, 25, - '\x3d\x2e\xec\x4f\xe4\x1c\x84\x9b\x80\xc8\xd8\x36\x62' + - '\xc0\xe4\x4a\x8b\x29\x1a\x96\x4c\xf2\xf0\x70\x38'); + '\x34\x8c\x89\xdb\xcb\xd3\x2b\x2f\x32\xd8\x14\xb8\x11' + + '\x6e\x84\xcf\x2b\x17\x34\x7e\xbc\x18\x00\x18\x1c'); testPBKDF2('pass\0word', 'sa\0lt', 4096, 16, - '\x56\xfa\x6a\xa7\x55\x48\x09\x9d\xcc\x37\xd7\xf0\x34' + - '\x25\xe0\xc3'); + '\x89\xb6\x9d\x05\x16\xf8\x29\x89\x3c\x69\x62\x26\x65' + + '\x0a\x86\x87'); var expected = '64c486c55d30d4c5a079b8823b7d7cb37ff0556f537da8410233bcec330ed956'; @@ -62,28 +62,28 @@ assert.throws(function() { // Should not work with Infinity key length assert.throws(function() { - crypto.pbkdf2('password', 'salt', 1, Infinity, common.fail); + crypto.pbkdf2('password', 'salt', 1, Infinity, 'sha256', common.fail); }, function(err) { return err instanceof Error && err.message === 'Bad key length'; }); // Should not work with negative Infinity key length assert.throws(function() { - crypto.pbkdf2('password', 'salt', 1, -Infinity, common.fail); + crypto.pbkdf2('password', 'salt', 1, -Infinity, 'sha256', common.fail); }, function(err) { return err instanceof Error && err.message === 'Bad key length'; }); // Should not work with NaN key length assert.throws(function() { - crypto.pbkdf2('password', 'salt', 1, NaN, common.fail); + crypto.pbkdf2('password', 'salt', 1, NaN, 'sha256', common.fail); }, function(err) { return err instanceof Error && err.message === 'Bad key length'; }); // Should not work with negative key length assert.throws(function() { - crypto.pbkdf2('password', 'salt', 1, -1, common.fail); + crypto.pbkdf2('password', 'salt', 1, -1, 'sha256', common.fail); }, function(err) { return err instanceof Error && err.message === 'Bad key length'; });