Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 6262fa4

Browse filesBrowse files
bnoordhuistargos
authored andcommitted
crypto: refactor pbkdf2() and pbkdf2Sync() methods
Use the scrypt() infrastructure to reimplement pbkdf2() in a simpler manner. 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>
1 parent c9b4592 commit 6262fa4
Copy full SHA for 6262fa4

File tree

Expand file treeCollapse file tree

6 files changed

+121
-180
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

6 files changed

+121
-180
lines changed
Open diff view settings
Collapse file

‎doc/api/errors.md‎

Copy file name to clipboardExpand all lines: doc/api/errors.md
+6Lines changed: 6 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,12 @@ An invalid [crypto digest algorithm][] was specified.
739739
A crypto method was used on an object that was in an invalid state. For
740740
instance, calling [`cipher.getAuthTag()`][] before calling `cipher.final()`.
741741

742+
<a id="ERR_CRYPTO_PBKDF2_ERROR"></a>
743+
### ERR_CRYPTO_PBKDF2_ERROR
744+
745+
The PBKDF2 algorithm failed for unspecified reasons. OpenSSL does not provide
746+
more details and therefore neither does Node.js.
747+
742748
<a id="ERR_CRYPTO_SCRYPT_INVALID_PARAMETER"></a>
743749
### ERR_CRYPTO_SCRYPT_INVALID_PARAMETER
744750

Collapse file

‎lib/internal/crypto/pbkdf2.js‎

Copy file name to clipboardExpand all lines: lib/internal/crypto/pbkdf2.js
+41-32Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,61 @@
11
'use strict';
22

3+
const { AsyncWrap, Providers } = process.binding('async_wrap');
4+
const { Buffer } = require('buffer');
5+
const { pbkdf2: _pbkdf2 } = process.binding('crypto');
36
const {
7+
ERR_CRYPTO_INVALID_DIGEST,
8+
ERR_CRYPTO_PBKDF2_ERROR,
49
ERR_INVALID_ARG_TYPE,
510
ERR_INVALID_CALLBACK,
6-
ERR_CRYPTO_INVALID_DIGEST,
711
} = require('internal/errors').codes;
812
const {
913
checkIsArrayBufferView,
1014
checkIsUint,
1115
getDefaultEncoding,
1216
} = require('internal/crypto/util');
13-
const {
14-
PBKDF2
15-
} = process.binding('crypto');
1617

1718
function pbkdf2(password, salt, iterations, keylen, digest, callback) {
1819
if (typeof digest === 'function') {
1920
callback = digest;
2021
digest = undefined;
2122
}
2223

24+
({ password, salt, iterations, keylen, digest } =
25+
check(password, salt, iterations, keylen, digest, callback));
26+
2327
if (typeof callback !== 'function')
2428
throw new ERR_INVALID_CALLBACK();
2529

26-
return _pbkdf2(password, salt, iterations, keylen, digest, callback);
30+
const encoding = getDefaultEncoding();
31+
const keybuf = Buffer.alloc(keylen);
32+
33+
const wrap = new AsyncWrap(Providers.PBKDF2REQUEST);
34+
wrap.ondone = (ok) => { // Retains keybuf while request is in flight.
35+
if (!ok) return callback.call(wrap, new ERR_CRYPTO_PBKDF2_ERROR());
36+
if (encoding === 'buffer') return callback.call(wrap, null, keybuf);
37+
callback.call(wrap, null, keybuf.toString(encoding));
38+
};
39+
40+
handleError(keybuf, password, salt, iterations, digest, wrap);
2741
}
2842

2943
function pbkdf2Sync(password, salt, iterations, keylen, digest) {
30-
return _pbkdf2(password, salt, iterations, keylen, digest);
44+
({ password, salt, iterations, keylen, digest } =
45+
check(password, salt, iterations, keylen, digest, pbkdf2Sync));
46+
const keybuf = Buffer.alloc(keylen);
47+
handleError(keybuf, password, salt, iterations, digest);
48+
const encoding = getDefaultEncoding();
49+
if (encoding === 'buffer') return keybuf;
50+
return keybuf.toString(encoding);
3151
}
3252

33-
function _pbkdf2(password, salt, iterations, keylen, digest, callback) {
34-
35-
if (digest !== null && typeof digest !== 'string')
36-
throw new ERR_INVALID_ARG_TYPE('digest', ['string', 'null'], digest);
53+
function check(password, salt, iterations, keylen, digest, callback) {
54+
if (typeof digest !== 'string') {
55+
if (digest !== null)
56+
throw new ERR_INVALID_ARG_TYPE('digest', ['string', 'null'], digest);
57+
digest = 'sha1';
58+
}
3759

3860
password = checkIsArrayBufferView('password', password);
3961
salt = checkIsArrayBufferView('salt', salt);
@@ -42,30 +64,17 @@ function _pbkdf2(password, salt, iterations, keylen, digest, callback) {
4264
iterations = checkIsUint('iterations', iterations, 'a non-negative number');
4365
keylen = checkIsUint('keylen', keylen);
4466

45-
const encoding = getDefaultEncoding();
67+
return { password, salt, iterations, keylen, digest };
68+
}
4669

47-
if (encoding === 'buffer') {
48-
const ret = PBKDF2(password, salt, iterations, keylen, digest, callback);
49-
if (ret === -1)
50-
throw new ERR_CRYPTO_INVALID_DIGEST(digest);
51-
return ret;
52-
}
70+
function handleError(keybuf, password, salt, iterations, digest, wrap) {
71+
const rc = _pbkdf2(keybuf, password, salt, iterations, digest, wrap);
5372

54-
// at this point, we need to handle encodings.
55-
if (callback) {
56-
function next(er, ret) {
57-
if (ret)
58-
ret = ret.toString(encoding);
59-
callback(er, ret);
60-
}
61-
if (PBKDF2(password, salt, iterations, keylen, digest, next) === -1)
62-
throw new ERR_CRYPTO_INVALID_DIGEST(digest);
63-
} else {
64-
const ret = PBKDF2(password, salt, iterations, keylen, digest);
65-
if (ret === -1)
66-
throw new ERR_CRYPTO_INVALID_DIGEST(digest);
67-
return ret.toString(encoding);
68-
}
73+
if (rc === -1)
74+
throw new ERR_CRYPTO_INVALID_DIGEST(digest);
75+
76+
if (rc === false)
77+
throw new ERR_CRYPTO_PBKDF2_ERROR();
6978
}
7079

7180
module.exports = {
Collapse file

‎lib/internal/errors.js‎

Copy file name to clipboardExpand all lines: lib/internal/errors.js
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,8 @@ E('ERR_CRYPTO_HASH_FINALIZED', 'Digest already called', Error);
503503
E('ERR_CRYPTO_HASH_UPDATE_FAILED', 'Hash update failed', Error);
504504
E('ERR_CRYPTO_INVALID_DIGEST', 'Invalid digest: %s', TypeError);
505505
E('ERR_CRYPTO_INVALID_STATE', 'Invalid state for operation %s', Error);
506+
// TODO(bnoordhuis) Decapitalize: s/PBKDF2 Error/PBKDF2 error/
507+
E('ERR_CRYPTO_PBKDF2_ERROR', 'PBKDF2 Error', Error);
506508
E('ERR_CRYPTO_SCRYPT_INVALID_PARAMETER', 'Invalid scrypt parameter', Error);
507509
E('ERR_CRYPTO_SCRYPT_NOT_SUPPORTED', 'Scrypt algorithm not supported', Error);
508510
// Switch to TypeError. The current implementation does not seem right.
Collapse file

‎src/env.h‎

Copy file name to clipboardExpand all lines: src/env.h
-2Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,6 @@ struct PackageConfig {
244244
V(password_string, "password") \
245245
V(path_string, "path") \
246246
V(pending_handle_string, "pendingHandle") \
247-
V(pbkdf2_error_string, "PBKDF2 Error") \
248247
V(pid_string, "pid") \
249248
V(pipe_string, "pipe") \
250249
V(pipe_target_string, "pipeTarget") \
@@ -337,7 +336,6 @@ struct PackageConfig {
337336
V(inspector_console_api_object, v8::Object) \
338337
V(message_port, v8::Object) \
339338
V(message_port_constructor_template, v8::FunctionTemplate) \
340-
V(pbkdf2_constructor_template, v8::ObjectTemplate) \
341339
V(pipe_constructor_template, v8::FunctionTemplate) \
342340
V(performance_entry_callback, v8::Function) \
343341
V(performance_entry_template, v8::Function) \

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.