• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3const { AsyncWrap, Providers } = internalBinding('async_wrap');
4const { Buffer } = require('buffer');
5const { pbkdf2: _pbkdf2 } = internalBinding('crypto');
6const { validateUint32 } = require('internal/validators');
7const {
8  ERR_CRYPTO_INVALID_DIGEST,
9  ERR_CRYPTO_PBKDF2_ERROR,
10  ERR_INVALID_ARG_TYPE,
11  ERR_INVALID_CALLBACK,
12} = require('internal/errors').codes;
13const {
14  getDefaultEncoding,
15  getArrayBufferView,
16} = require('internal/crypto/util');
17
18function pbkdf2(password, salt, iterations, keylen, digest, callback) {
19  if (typeof digest === 'function') {
20    callback = digest;
21    digest = undefined;
22  }
23
24  ({ password, salt, iterations, keylen, digest } =
25    check(password, salt, iterations, keylen, digest));
26
27  if (typeof callback !== 'function')
28    throw new ERR_INVALID_CALLBACK(callback);
29
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(_pbkdf2(keybuf, password, salt, iterations, digest, wrap),
41              digest);
42}
43
44function pbkdf2Sync(password, salt, iterations, keylen, digest) {
45  ({ password, salt, iterations, keylen, digest } =
46    check(password, salt, iterations, keylen, digest));
47  const keybuf = Buffer.alloc(keylen);
48  handleError(_pbkdf2(keybuf, password, salt, iterations, digest), digest);
49  const encoding = getDefaultEncoding();
50  if (encoding === 'buffer') return keybuf;
51  return keybuf.toString(encoding);
52}
53
54function check(password, salt, iterations, keylen, digest) {
55  if (typeof digest !== 'string')
56    throw new ERR_INVALID_ARG_TYPE('digest', 'string', digest);
57
58  password = getArrayBufferView(password, 'password');
59  salt = getArrayBufferView(salt, 'salt');
60  validateUint32(iterations, 'iterations', true);
61  validateUint32(keylen, 'keylen');
62
63  return { password, salt, iterations, keylen, digest };
64}
65
66function handleError(rc, digest) {
67  if (rc === -1)
68    throw new ERR_CRYPTO_INVALID_DIGEST(digest);
69
70  if (rc === false)
71    throw new ERR_CRYPTO_PBKDF2_ERROR();
72}
73
74module.exports = {
75  pbkdf2,
76  pbkdf2Sync
77};
78