├── .eslintrc
├── .github
├── FUNDING.yml
└── workflows
│ ├── node-aught.yml
│ ├── node-pretest.yml
│ ├── node-tens.yml
│ ├── node-twenties.yml
│ ├── rebase.yml
│ └── require-allow-edits.yml
├── .gitignore
├── .npmrc
├── .nycrc
├── .travis.yml
├── LICENSE
├── README.md
├── bench
├── index.js
└── old.js
├── browser.js
├── index.js
├── lib
├── async.js
├── default-encoding.js
├── precondition.js
├── sync-browser.js
├── sync.js
└── to-buffer.js
├── package.json
└── test
├── bundle.html
├── fixtures.json
└── index.js
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 |
4 | "extends": "@ljharb",
5 |
6 | "globals": {
7 | "Uint8Array": "readonly",
8 | "Uint16Array": "readonly",
9 | "Uint32Array": "readonly",
10 | "Int8Array": "readonly",
11 | "Int16Array": "readonly",
12 | "Int32Array": "readonly",
13 | "Float32Array": "readonly",
14 | "Float64Array": "readonly",
15 | "BigInt64Array": "readonly",
16 | "BigUint64Array": "readonly",
17 | },
18 |
19 | "rules": {
20 | "func-style": "warn",
21 | "max-params": "warn",
22 | "multiline-comment-style": "off",
23 | "no-param-reassign": "warn",
24 | "sort-keys": "warn",
25 | },
26 |
27 | "ignorePatterns": [
28 | "test/bundle.js",
29 | ],
30 |
31 | "overrides": [
32 | {
33 | "files": "bench/*",
34 | "extends": "@ljharb/eslint-config/node/4",
35 | "rules": {
36 | "func-style": "warn",
37 | "max-params": "warn",
38 | "no-param-reassign": "warn",
39 | "no-var": "off",
40 | "prefer-arrow-callback": "off",
41 | "prefer-template": "off",
42 | },
43 | },
44 | ],
45 | }
46 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [ljharb]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: npm/pbkdf2
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
13 |
--------------------------------------------------------------------------------
/.github/workflows/node-aught.yml:
--------------------------------------------------------------------------------
1 | name: 'Tests: node.js < 10'
2 |
3 | on: [pull_request, push]
4 |
5 | jobs:
6 | tests:
7 | uses: ljharb/actions/.github/workflows/node.yml@main
8 | with:
9 | range: '>= 0.12 < 10'
10 | type: minors
11 | command: npm run tests-only
12 |
13 | node:
14 | name: 'node < 10'
15 | needs: [tests]
16 | runs-on: ubuntu-latest
17 | steps:
18 | - run: true
19 |
--------------------------------------------------------------------------------
/.github/workflows/node-pretest.yml:
--------------------------------------------------------------------------------
1 | name: 'Tests: pretest/posttest'
2 |
3 | on: [pull_request, push]
4 |
5 | jobs:
6 | tests:
7 | uses: ljharb/actions/.github/workflows/pretest.yml@main
8 |
--------------------------------------------------------------------------------
/.github/workflows/node-tens.yml:
--------------------------------------------------------------------------------
1 | name: 'Tests: node.js 10 - 20'
2 |
3 | on: [pull_request, push]
4 |
5 | permissions:
6 | contents: read
7 |
8 | jobs:
9 | tests:
10 | uses: ljharb/actions/.github/workflows/node.yml@main
11 | with:
12 | range: '>= 10 < 20'
13 | type: minors
14 | command: npm run tests-only
15 |
16 | node:
17 | name: 'node 10 - 20'
18 | needs: [tests]
19 | runs-on: ubuntu-latest
20 | steps:
21 | - run: true
22 |
--------------------------------------------------------------------------------
/.github/workflows/node-twenties.yml:
--------------------------------------------------------------------------------
1 | name: 'Tests: node.js >= 20'
2 |
3 | on: [pull_request, push]
4 |
5 | permissions:
6 | contents: read
7 |
8 | jobs:
9 | tests:
10 | uses: ljharb/actions/.github/workflows/node.yml@main
11 | with:
12 | range: '>= 20'
13 | type: minors
14 | command: npm run tests-only
15 |
16 | node:
17 | name: 'node >= 20'
18 | needs: [tests]
19 | runs-on: ubuntu-latest
20 | steps:
21 | - run: true
22 |
--------------------------------------------------------------------------------
/.github/workflows/rebase.yml:
--------------------------------------------------------------------------------
1 | name: Automatic Rebase
2 |
3 | on: [pull_request_target]
4 |
5 | jobs:
6 | _:
7 | uses: ljharb/actions/.github/workflows/rebase.yml@main
8 | secrets:
9 | token: ${{ secrets.GITHUB_TOKEN }}
10 |
--------------------------------------------------------------------------------
/.github/workflows/require-allow-edits.yml:
--------------------------------------------------------------------------------
1 | name: Require “Allow Edits”
2 |
3 | on: [pull_request_target]
4 |
5 | jobs:
6 | _:
7 | name: "Require “Allow Edits”"
8 |
9 | runs-on: ubuntu-latest
10 |
11 | steps:
12 | - uses: ljharb/require-allow-edits@main
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # Compiled binary addons (http://nodejs.org/api/addons.html)
20 | build/Release
21 |
22 | # Dependency directory
23 | # Deployed apps should consider commenting this line out:
24 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
25 | node_modules
26 |
27 | # build artifact
28 | test/bundle.js
29 | .nyc_output
30 |
31 | # Only apps should have lockfiles
32 | npm-shrinkwrap.json
33 | package-lock.json
34 | yarn.lock
35 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 |
--------------------------------------------------------------------------------
/.nycrc:
--------------------------------------------------------------------------------
1 | {
2 | "all": true,
3 | "check-coverage": false,
4 | "reporter": ["text-summary", "text", "html", "json"],
5 | "exclude": [
6 | "bench",
7 | "coverage",
8 | "test"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: node_js
3 | before_install:
4 | - npm install npm -g
5 | node_js:
6 | - "12"
7 | - "lts/*"
8 | - "8"
9 | - "9"
10 | - "10"
11 | matrix:
12 | include:
13 | - node_js: "8"
14 | env: TEST_SUITE=coverage
15 | - node_js: "8"
16 | env: TEST_SUITE=lint
17 | env:
18 | - TEST_SUITE=test
19 | script: npm run-script $TEST_SUITE
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Daniel Cousens
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # pbkdf2
2 |
3 | [](https://www.npmjs.org/package/pbkdf2)
4 | [](https://travis-ci.org/crypto-browserify/pbkdf2)
5 | [](https://david-dm.org/crypto-browserify/pbkdf2#info=dependencies)
6 |
7 | [](https://github.com/feross/standard)
8 |
9 | This library provides the functionality of PBKDF2 with the ability to use any supported hashing algorithm returned from `crypto.getHashes()`
10 |
11 |
12 | ## Usage
13 |
14 | ```js
15 | var pbkdf2 = require('pbkdf2')
16 | var derivedKey = pbkdf2.pbkdf2Sync('password', 'salt', 1, 32, 'sha512')
17 |
18 | ...
19 | ```
20 |
21 | For more information on the API, please see the relevant [Node documentation](https://nodejs.org/api/crypto.html#crypto_crypto_pbkdf2_password_salt_iterations_keylen_digest_callback).
22 |
23 | For high performance, use the `async` variant (`pbkdf2.pbkdf2`), not `pbkdf2.pbkdf2Sync`; this variant has the oppurtunity to use `window.crypto.subtle` when browserified.
24 |
25 |
26 | ## Credits
27 |
28 | This module is a derivative of [cryptocoinjs/pbkdf2-sha256](https://github.com/cryptocoinjs/pbkdf2-sha256/), so thanks to [JP Richardson](https://github.com/jprichardson/) for laying the ground work.
29 |
30 | Thank you to [FangDun Cai](https://github.com/fundon) for donating the package name on npm, if you're looking for his previous module it is located at [fundon/pbkdf2](https://github.com/fundon/pbkdf2).
31 |
--------------------------------------------------------------------------------
/bench/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Benchmark = require('benchmark');
4 | var current = require('../lib/sync');
5 | var old = require('./old');
6 |
7 | function run(password, salt, iterations, keylen, digest) {
8 | var suite = new Benchmark.Suite();
9 | console.log(`password: ${password}`);
10 | console.log(`salt: ${salt}`);
11 | console.log(`iterations: ${iterations}`);
12 | console.log(`keylen: ${keylen}`);
13 | console.log(`digest: ${digest}`);
14 |
15 | // add tests
16 | suite
17 | .add('current', function () {
18 | current(password, salt, iterations, keylen, digest);
19 | })
20 | .add('old', function () {
21 | old(password, salt, iterations, keylen, digest);
22 | })
23 |
24 | // add listeners
25 | .on('cycle', function (event) {
26 | console.log(String(event.target));
27 | })
28 | .on('complete', function () {
29 | // eslint-disable-next-line no-invalid-this
30 | console.log('Fastest is ' + this.filter('fastest').map('name'));
31 | console.log('');
32 | })
33 | .run();
34 | }
35 |
36 | run('hello', 'world', 100, 32, 'md5');
37 | run('hello', 'world', 100, 32, 'sha256');
38 | run('hello', 'world', 10000, 70, 'md5');
39 | run('hello', 'world', 10000, 70, 'sha256');
40 |
--------------------------------------------------------------------------------
/bench/old.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var createHmac = require('create-hmac');
4 | var checkParameters = require('../lib/precondition');
5 | var defaultEncoding = require('../lib/default-encoding');
6 | var Buffer = require('safe-buffer').Buffer;
7 |
8 | module.exports = function pbkdf2(password, salt, iterations, keylen, digest) {
9 | if (!Buffer.isBuffer(password)) {
10 | password = Buffer.from(password, defaultEncoding);
11 | }
12 | if (!Buffer.isBuffer(salt)) {
13 | salt = Buffer.from(salt, defaultEncoding);
14 | }
15 |
16 | checkParameters(iterations, keylen);
17 |
18 | digest = digest || 'sha1';
19 |
20 | var hLen;
21 | var l = 1;
22 | var DK = Buffer.allocUnsafe(keylen);
23 | var block1 = Buffer.allocUnsafe(salt.length + 4);
24 | salt.copy(block1, 0, 0, salt.length);
25 |
26 | var r;
27 | var T;
28 |
29 | for (var i = 1; i <= l; i++) {
30 | block1.writeUInt32BE(i, salt.length);
31 | var U = createHmac(digest, password).update(block1).digest();
32 |
33 | if (!hLen) {
34 | hLen = U.length;
35 | T = Buffer.allocUnsafe(hLen);
36 | l = Math.ceil(keylen / hLen);
37 | r = keylen - ((l - 1) * hLen);
38 | }
39 |
40 | U.copy(T, 0, 0, hLen);
41 |
42 | for (var j = 1; j < iterations; j++) {
43 | U = createHmac(digest, password).update(U).digest();
44 | for (var k = 0; k < hLen; k++) {
45 | T[k] ^= U[k];
46 | }
47 | }
48 |
49 | var destPos = (i - 1) * hLen;
50 | var len = i === l ? r : hLen;
51 | T.copy(DK, destPos, 0, len);
52 | }
53 |
54 | return DK;
55 | };
56 |
--------------------------------------------------------------------------------
/browser.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | exports.pbkdf2 = require('./lib/async');
4 | exports.pbkdf2Sync = require('./lib/sync');
5 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var nativeImpl = require('crypto');
4 |
5 | var checkParameters = require('./lib/precondition');
6 | var defaultEncoding = require('./lib/default-encoding');
7 | var toBuffer = require('./lib/to-buffer');
8 |
9 | function nativePBKDF2(password, salt, iterations, keylen, digest, callback) {
10 | checkParameters(iterations, keylen);
11 | password = toBuffer(password, defaultEncoding, 'Password');
12 | salt = toBuffer(salt, defaultEncoding, 'Salt');
13 |
14 | if (typeof digest === 'function') {
15 | callback = digest;
16 | digest = 'sha1';
17 | }
18 | if (typeof callback !== 'function') {
19 | throw new Error('No callback provided to pbkdf2');
20 | }
21 |
22 | return nativeImpl.pbkdf2(password, salt, iterations, keylen, digest, callback);
23 | }
24 |
25 | function nativePBKDF2Sync(password, salt, iterations, keylen, digest) {
26 | checkParameters(iterations, keylen);
27 | password = toBuffer(password, defaultEncoding, 'Password');
28 | salt = toBuffer(salt, defaultEncoding, 'Salt');
29 | digest = digest || 'sha1';
30 | return nativeImpl.pbkdf2Sync(password, salt, iterations, keylen, digest);
31 | }
32 |
33 | /* istanbul ignore next */
34 | if (!nativeImpl.pbkdf2Sync || nativeImpl.pbkdf2Sync.toString().indexOf('keylen, digest') === -1) {
35 | /* eslint global-require: 0 */
36 | exports.pbkdf2Sync = require('./lib/sync');
37 | exports.pbkdf2 = require('./lib/async');
38 |
39 | // native
40 | } else {
41 | exports.pbkdf2Sync = nativePBKDF2Sync;
42 | exports.pbkdf2 = nativePBKDF2;
43 | }
44 |
--------------------------------------------------------------------------------
/lib/async.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Buffer = require('safe-buffer').Buffer;
4 |
5 | var checkParameters = require('./precondition');
6 | var defaultEncoding = require('./default-encoding');
7 | var sync = require('./sync');
8 | var toBuffer = require('./to-buffer');
9 |
10 | var ZERO_BUF;
11 | var subtle = global.crypto && global.crypto.subtle;
12 | var toBrowser = {
13 | sha: 'SHA-1',
14 | 'sha-1': 'SHA-1',
15 | sha1: 'SHA-1',
16 | sha256: 'SHA-256',
17 | 'sha-256': 'SHA-256',
18 | sha384: 'SHA-384',
19 | 'sha-384': 'SHA-384',
20 | 'sha-512': 'SHA-512',
21 | sha512: 'SHA-512'
22 | };
23 | var checks = [];
24 | var nextTick;
25 | function getNextTick() {
26 | if (nextTick) {
27 | return nextTick;
28 | }
29 | if (global.process && global.process.nextTick) {
30 | nextTick = global.process.nextTick;
31 | } else if (global.queueMicrotask) {
32 | nextTick = global.queueMicrotask;
33 | } else if (global.setImmediate) {
34 | nextTick = global.setImmediate;
35 | } else {
36 | nextTick = global.setTimeout;
37 | }
38 | return nextTick;
39 | }
40 | function browserPbkdf2(password, salt, iterations, length, algo) {
41 | return subtle.importKey('raw', password, { name: 'PBKDF2' }, false, ['deriveBits']).then(function (key) {
42 | return subtle.deriveBits({
43 | name: 'PBKDF2',
44 | salt: salt,
45 | iterations: iterations,
46 | hash: {
47 | name: algo
48 | }
49 | }, key, length << 3);
50 | }).then(function (res) {
51 | return Buffer.from(res);
52 | });
53 | }
54 | function checkNative(algo) {
55 | if (global.process && !global.process.browser) {
56 | return Promise.resolve(false);
57 | }
58 | if (!subtle || !subtle.importKey || !subtle.deriveBits) {
59 | return Promise.resolve(false);
60 | }
61 | if (checks[algo] !== undefined) {
62 | return checks[algo];
63 | }
64 | ZERO_BUF = ZERO_BUF || Buffer.alloc(8);
65 | var prom = browserPbkdf2(ZERO_BUF, ZERO_BUF, 10, 128, algo)
66 | .then(
67 | function () { return true; },
68 | function () { return false; }
69 | );
70 | checks[algo] = prom;
71 | return prom;
72 | }
73 |
74 | function resolvePromise(promise, callback) {
75 | promise.then(function (out) {
76 | getNextTick()(function () {
77 | callback(null, out);
78 | });
79 | }, function (e) {
80 | getNextTick()(function () {
81 | callback(e);
82 | });
83 | });
84 | }
85 | module.exports = function (password, salt, iterations, keylen, digest, callback) {
86 | if (typeof digest === 'function') {
87 | callback = digest;
88 | digest = undefined;
89 | }
90 |
91 | digest = digest || 'sha1';
92 | var algo = toBrowser[digest.toLowerCase()];
93 |
94 | if (!algo || typeof global.Promise !== 'function') {
95 | getNextTick()(function () {
96 | var out;
97 | try {
98 | out = sync(password, salt, iterations, keylen, digest);
99 | } catch (e) {
100 | callback(e);
101 | return;
102 | }
103 | callback(null, out);
104 | });
105 | return;
106 | }
107 |
108 | checkParameters(iterations, keylen);
109 | password = toBuffer(password, defaultEncoding, 'Password');
110 | salt = toBuffer(salt, defaultEncoding, 'Salt');
111 | if (typeof callback !== 'function') {
112 | throw new Error('No callback provided to pbkdf2');
113 | }
114 |
115 | resolvePromise(checkNative(algo).then(function (resp) {
116 | if (resp) {
117 | return browserPbkdf2(password, salt, iterations, keylen, algo);
118 | }
119 |
120 | return sync(password, salt, iterations, keylen, digest);
121 | }), callback);
122 | };
123 |
--------------------------------------------------------------------------------
/lib/default-encoding.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var defaultEncoding;
4 | /* istanbul ignore next */
5 | if (global.process && global.process.browser) {
6 | defaultEncoding = 'utf-8';
7 | } else if (global.process && global.process.version) {
8 | var pVersionMajor = parseInt(process.version.split('.')[0].slice(1), 10);
9 |
10 | defaultEncoding = pVersionMajor >= 6 ? 'utf-8' : 'binary';
11 | } else {
12 | defaultEncoding = 'utf-8';
13 | }
14 | module.exports = defaultEncoding;
15 |
--------------------------------------------------------------------------------
/lib/precondition.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var MAX_ALLOC = Math.pow(2, 30) - 1; // default in iojs
4 |
5 | module.exports = function (iterations, keylen) {
6 | if (typeof iterations !== 'number') {
7 | throw new TypeError('Iterations not a number');
8 | }
9 |
10 | if (iterations < 0) {
11 | throw new TypeError('Bad iterations');
12 | }
13 |
14 | if (typeof keylen !== 'number') {
15 | throw new TypeError('Key length not a number');
16 | }
17 |
18 | if (keylen < 0 || keylen > MAX_ALLOC || keylen !== keylen) { /* eslint no-self-compare: 0 */
19 | throw new TypeError('Bad key length');
20 | }
21 | };
22 |
--------------------------------------------------------------------------------
/lib/sync-browser.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var md5 = require('create-hash/md5');
4 | var RIPEMD160 = require('ripemd160');
5 | var sha = require('sha.js');
6 | var Buffer = require('safe-buffer').Buffer;
7 |
8 | var checkParameters = require('./precondition');
9 | var defaultEncoding = require('./default-encoding');
10 | var toBuffer = require('./to-buffer');
11 |
12 | var ZEROS = Buffer.alloc(128);
13 | var sizes = {
14 | md5: 16,
15 | sha1: 20,
16 | sha224: 28,
17 | sha256: 32,
18 | sha384: 48,
19 | sha512: 64,
20 | rmd160: 20,
21 | ripemd160: 20
22 | };
23 |
24 | function getDigest(alg) {
25 | function shaFunc(data) {
26 | return sha(alg).update(data).digest();
27 | }
28 | function rmd160Func(data) {
29 | return new RIPEMD160().update(data).digest();
30 | }
31 |
32 | if (alg === 'rmd160' || alg === 'ripemd160') {
33 | return rmd160Func;
34 | }
35 | if (alg === 'md5') {
36 | return md5;
37 | }
38 | return shaFunc;
39 | }
40 |
41 | function Hmac(alg, key, saltLen) {
42 | var hash = getDigest(alg);
43 | var blocksize = alg === 'sha512' || alg === 'sha384' ? 128 : 64;
44 |
45 | if (key.length > blocksize) {
46 | key = hash(key);
47 | } else if (key.length < blocksize) {
48 | key = Buffer.concat([key, ZEROS], blocksize);
49 | }
50 |
51 | var ipad = Buffer.allocUnsafe(blocksize + sizes[alg]);
52 | var opad = Buffer.allocUnsafe(blocksize + sizes[alg]);
53 | for (var i = 0; i < blocksize; i++) {
54 | ipad[i] = key[i] ^ 0x36;
55 | opad[i] = key[i] ^ 0x5C;
56 | }
57 |
58 | var ipad1 = Buffer.allocUnsafe(blocksize + saltLen + 4);
59 | ipad.copy(ipad1, 0, 0, blocksize);
60 | this.ipad1 = ipad1;
61 | this.ipad2 = ipad;
62 | this.opad = opad;
63 | this.alg = alg;
64 | this.blocksize = blocksize;
65 | this.hash = hash;
66 | this.size = sizes[alg];
67 | }
68 |
69 | Hmac.prototype.run = function (data, ipad) {
70 | data.copy(ipad, this.blocksize);
71 | var h = this.hash(ipad);
72 | h.copy(this.opad, this.blocksize);
73 | return this.hash(this.opad);
74 | };
75 |
76 | function pbkdf2(password, salt, iterations, keylen, digest) {
77 | checkParameters(iterations, keylen);
78 | password = toBuffer(password, defaultEncoding, 'Password');
79 | salt = toBuffer(salt, defaultEncoding, 'Salt');
80 |
81 | digest = digest || 'sha1';
82 |
83 | var hmac = new Hmac(digest, password, salt.length);
84 |
85 | var DK = Buffer.allocUnsafe(keylen);
86 | var block1 = Buffer.allocUnsafe(salt.length + 4);
87 | salt.copy(block1, 0, 0, salt.length);
88 |
89 | var destPos = 0;
90 | var hLen = sizes[digest];
91 | var l = Math.ceil(keylen / hLen);
92 |
93 | for (var i = 1; i <= l; i++) {
94 | block1.writeUInt32BE(i, salt.length);
95 |
96 | var T = hmac.run(block1, hmac.ipad1);
97 | var U = T;
98 |
99 | for (var j = 1; j < iterations; j++) {
100 | U = hmac.run(U, hmac.ipad2);
101 | for (var k = 0; k < hLen; k++) {
102 | T[k] ^= U[k];
103 | }
104 | }
105 |
106 | T.copy(DK, destPos);
107 | destPos += hLen;
108 | }
109 |
110 | return DK;
111 | }
112 |
113 | module.exports = pbkdf2;
114 |
--------------------------------------------------------------------------------
/lib/sync.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var sizes = {
4 | md5: 16,
5 | sha1: 20,
6 | sha224: 28,
7 | sha256: 32,
8 | sha384: 48,
9 | sha512: 64,
10 | rmd160: 20,
11 | ripemd160: 20
12 | };
13 |
14 | var createHmac = require('create-hmac');
15 | var Buffer = require('safe-buffer').Buffer;
16 |
17 | var checkParameters = require('./precondition');
18 | var defaultEncoding = require('./default-encoding');
19 | var toBuffer = require('./to-buffer');
20 |
21 | function pbkdf2(password, salt, iterations, keylen, digest) {
22 | checkParameters(iterations, keylen);
23 | password = toBuffer(password, defaultEncoding, 'Password');
24 | salt = toBuffer(salt, defaultEncoding, 'Salt');
25 |
26 | digest = digest || 'sha1';
27 |
28 | var DK = Buffer.allocUnsafe(keylen);
29 | var block1 = Buffer.allocUnsafe(salt.length + 4);
30 | salt.copy(block1, 0, 0, salt.length);
31 |
32 | var destPos = 0;
33 | var hLen = sizes[digest];
34 | var l = Math.ceil(keylen / hLen);
35 |
36 | for (var i = 1; i <= l; i++) {
37 | block1.writeUInt32BE(i, salt.length);
38 |
39 | var T = createHmac(digest, password).update(block1).digest();
40 | var U = T;
41 |
42 | for (var j = 1; j < iterations; j++) {
43 | U = createHmac(digest, password).update(U).digest();
44 | for (var k = 0; k < hLen; k++) {
45 | T[k] ^= U[k];
46 | }
47 | }
48 |
49 | T.copy(DK, destPos);
50 | destPos += hLen;
51 | }
52 |
53 | return DK;
54 | }
55 |
56 | module.exports = pbkdf2;
57 |
--------------------------------------------------------------------------------
/lib/to-buffer.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Buffer = require('safe-buffer').Buffer;
4 |
5 | module.exports = function (thing, encoding, name) {
6 | if (Buffer.isBuffer(thing)) {
7 | return thing;
8 | } else if (typeof thing === 'string') {
9 | return Buffer.from(thing, encoding);
10 | } else if (ArrayBuffer.isView(thing)) {
11 | return Buffer.from(thing.buffer);
12 | }
13 | throw new TypeError(name + ' must be a string, a Buffer, a typed array or a DataView');
14 |
15 | };
16 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pbkdf2",
3 | "version": "3.1.2",
4 | "description": "This library provides the functionality of PBKDF2 with the ability to use any supported hashing algorithm returned from crypto.getHashes()",
5 | "keywords": [
6 | "pbkdf2",
7 | "kdf",
8 | "salt",
9 | "hash"
10 | ],
11 | "homepage": "https://github.com/crypto-browserify/pbkdf2",
12 | "bugs": {
13 | "url": "https://github.com/crypto-browserify/pbkdf2/issues"
14 | },
15 | "license": "MIT",
16 | "author": "Daniel Cousens",
17 | "browser": {
18 | "./index.js": "./browser.js",
19 | "./lib/sync.js": "./lib/sync-browser.js"
20 | },
21 | "files": [
22 | "browser.js",
23 | "index.js",
24 | "lib/"
25 | ],
26 | "main": "index.js",
27 | "repository": {
28 | "type": "git",
29 | "url": "https://github.com/crypto-browserify/pbkdf2.git"
30 | },
31 | "scripts": {
32 | "lint": "eslint --ext=js,mjs .",
33 | "pretest": "npm run lint",
34 | "tests-only": "nyc --exclude=bench --exclude=coverage --exclude=test tape test/index.js",
35 | "test": "npm run tests-only && npm run bundle-test",
36 | "posttest": "npx npm@\">= 10.2\" audit --production",
37 | "bundle-test": "browserify test/index.js > test/bundle.js",
38 | "bench": "node bench/"
39 | },
40 | "devDependencies": {
41 | "@ljharb/eslint-config": "^21.1.1",
42 | "benchmark": "^2.1.4",
43 | "browserify": "^17.0.1",
44 | "eslint": "=8.8.0",
45 | "nyc": "^10.3.2",
46 | "object.assign": "^4.1.7",
47 | "semver": "^6.3.1",
48 | "tape": "^5.9.0"
49 | },
50 | "dependencies": {
51 | "create-hash": "~1.1.3",
52 | "create-hmac": "^1.1.4",
53 | "ripemd160": "=2.0.1",
54 | "safe-buffer": "^5.0.1",
55 | "sha.js": "^2.4.8"
56 | },
57 | "engines": {
58 | "node": ">=0.12"
59 | },
60 | "nyc": {
61 | "exclude": [
62 | "lib/async.js",
63 | "test/bundle.js"
64 | ]
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/test/bundle.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/test/fixtures.json:
--------------------------------------------------------------------------------
1 | {
2 | "valid": [
3 | {
4 | "key": "password",
5 | "salt": "salt",
6 | "iterations": 1,
7 | "dkLen": 32,
8 | "results": {
9 | "sha1": "0c60c80f961f0e71f3a9b524af6012062fe037a6e0f0eb94fe8fc46bdc637164",
10 | "sha256": "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b",
11 | "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252",
12 | "sha224": "3c198cbdb9464b7857966bd05b7bc92bc1cc4e6e63155d4e490557fd85989497",
13 | "sha384": "c0e14f06e49e32d73f9f52ddf1d0c5c7191609233631dadd76a567db42b78676",
14 | "ripemd160": "b725258b125e0bacb0e2307e34feb16a4d0d6aed6cb4b0eee458fc1829020428"
15 | },
16 | "resultsOld": {
17 | "sha1": "0c60c80f961f0e71f3a9b524af6012062fe037a6e0f0eb94fe8fc46bdc637164",
18 | "sha224": "3c198cbdb9464b7857966bd05b7bc92bc1cc4e6e63155d4e490557fd85989497",
19 | "sha256": "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b",
20 | "sha384": "c0e14f06e49e32d73f9f52ddf1d0c5c7191609233631dadd76a567db42b78676",
21 | "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252",
22 | "ripemd160": "b725258b125e0bacb0e2307e34feb16a4d0d6aed6cb4b0eee458fc1829020428"
23 | }
24 | },
25 | {
26 | "key": "password",
27 | "salt": "salt",
28 | "iterations": 2,
29 | "dkLen": 32,
30 | "results": {
31 | "sha1": "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957cae93136266537a8d7bf4b76",
32 | "sha256": "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43",
33 | "sha512": "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53c",
34 | "sha224": "93200ffa96c5776d38fa10abdf8f5bfc0054b9718513df472d2331d2d1e66a3f",
35 | "sha384": "54f775c6d790f21930459162fc535dbf04a939185127016a04176a0730c6f1f4",
36 | "ripemd160": "768dcc27b7bfdef794a1ff9d935090fcf598555e66913180b9ce363c615e9ed9"
37 | },
38 | "resultsOld": {
39 | "sha1": "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957cae93136266537a8d7bf4b76",
40 | "sha224": "93200ffa96c5776d38fa10abdf8f5bfc0054b9718513df472d2331d2d1e66a3f",
41 | "sha256": "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43",
42 | "sha384": "54f775c6d790f21930459162fc535dbf04a939185127016a04176a0730c6f1f4",
43 | "sha512": "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53c",
44 | "ripemd160": "768dcc27b7bfdef794a1ff9d935090fcf598555e66913180b9ce363c615e9ed9"
45 | }
46 | },
47 | {
48 | "key": "password",
49 | "salt": "salt",
50 | "iterations": 1,
51 | "dkLen": 64,
52 | "results": {
53 | "sha1": "0c60c80f961f0e71f3a9b524af6012062fe037a6e0f0eb94fe8fc46bdc637164ac2e7a8e3f9d2e83ace57e0d50e5e1071367c179bc86c767fc3f78ddb561363f",
54 | "sha256": "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b4dbf3a2f3dad3377264bb7b8e8330d4efc7451418617dabef683735361cdc18c",
55 | "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce",
56 | "sha224": "3c198cbdb9464b7857966bd05b7bc92bc1cc4e6e63155d4e490557fd859894978ab846d52a1083ac610c36c2c5ea8ce4a024dd691064d5453bd17b15ea1ac194",
57 | "sha384": "c0e14f06e49e32d73f9f52ddf1d0c5c7191609233631dadd76a567db42b78676b38fc800cc53ddb642f5c74442e62be44d727702213e3bb9223c53b767fbfb5d",
58 | "ripemd160": "b725258b125e0bacb0e2307e34feb16a4d0d6aed6cb4b0eee458fc18290204289e55d962783bf52237d264cbbab25f18d89d8c798f90f558ea7b45bdf3d08334"
59 | },
60 | "resultsOld": {
61 | "sha1": "0c60c80f961f0e71f3a9b524af6012062fe037a6e0f0eb94fe8fc46bdc637164ac2e7a8e3f9d2e83ace57e0d50e5e1071367c179bc86c767fc3f78ddb561363f",
62 | "sha224": "3c198cbdb9464b7857966bd05b7bc92bc1cc4e6e63155d4e490557fd859894978ab846d52a1083ac610c36c2c5ea8ce4a024dd691064d5453bd17b15ea1ac194",
63 | "sha256": "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b4dbf3a2f3dad3377264bb7b8e8330d4efc7451418617dabef683735361cdc18c",
64 | "sha384": "c0e14f06e49e32d73f9f52ddf1d0c5c7191609233631dadd76a567db42b78676b38fc800cc53ddb642f5c74442e62be44d727702213e3bb9223c53b767fbfb5d",
65 | "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce",
66 | "ripemd160": "b725258b125e0bacb0e2307e34feb16a4d0d6aed6cb4b0eee458fc18290204289e55d962783bf52237d264cbbab25f18d89d8c798f90f558ea7b45bdf3d08334"
67 | }
68 | },
69 | {
70 | "key": "password",
71 | "salt": "salt",
72 | "iterations": 2,
73 | "dkLen": 64,
74 | "results": {
75 | "sha1": "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957cae93136266537a8d7bf4b76c51094cc1ae010b19923ddc4395cd064acb023ffd1edd5ef4be8ffe61426c28e",
76 | "sha256": "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43830651afcb5c862f0b249bd031f7a67520d136470f5ec271ece91c07773253d9",
77 | "sha512": "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e",
78 | "sha224": "93200ffa96c5776d38fa10abdf8f5bfc0054b9718513df472d2331d2d1e66a3f97b510224f700ce72581ffb10a1c99ec99a8cc1b951851a71f30d9265fccf912",
79 | "sha384": "54f775c6d790f21930459162fc535dbf04a939185127016a04176a0730c6f1f4fb48832ad1261baadd2cedd50814b1c806ad1bbf43ebdc9d047904bf7ceafe1e",
80 | "ripemd160": "768dcc27b7bfdef794a1ff9d935090fcf598555e66913180b9ce363c615e9ed953b95fd07169be535e38afbea29c030e06d14f40745b1513b7ccdf0e76229e50"
81 | },
82 | "resultsOld": {
83 | "sha1": "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957cae93136266537a8d7bf4b76c51094cc1ae010b19923ddc4395cd064acb023ffd1edd5ef4be8ffe61426c28e",
84 | "sha224": "93200ffa96c5776d38fa10abdf8f5bfc0054b9718513df472d2331d2d1e66a3f97b510224f700ce72581ffb10a1c99ec99a8cc1b951851a71f30d9265fccf912",
85 | "sha256": "ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43830651afcb5c862f0b249bd031f7a67520d136470f5ec271ece91c07773253d9",
86 | "sha384": "54f775c6d790f21930459162fc535dbf04a939185127016a04176a0730c6f1f4fb48832ad1261baadd2cedd50814b1c806ad1bbf43ebdc9d047904bf7ceafe1e",
87 | "sha512": "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e",
88 | "ripemd160": "768dcc27b7bfdef794a1ff9d935090fcf598555e66913180b9ce363c615e9ed953b95fd07169be535e38afbea29c030e06d14f40745b1513b7ccdf0e76229e50"
89 | }
90 | },
91 | {
92 | "key": "password",
93 | "salt": "salt",
94 | "iterations": 4096,
95 | "dkLen": 32,
96 | "results": {
97 | "sha1": "4b007901b765489abead49d926f721d065a429c12e463f6c4cd79401085b03db",
98 | "sha256": "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a",
99 | "sha512": "d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5",
100 | "sha224": "218c453bf90635bd0a21a75d172703ff6108ef603f65bb821aedade1d6961683",
101 | "sha384": "559726be38db125bc85ed7895f6e3cf574c7a01c080c3447db1e8a76764deb3c",
102 | "ripemd160": "99a40d3fe4ee95869791d9faa24864562782762171480b620ca8bed3dafbbcac"
103 | },
104 | "resultsOld": {
105 | "sha1": "4b007901b765489abead49d926f721d065a429c12e463f6c4cd79401085b03db",
106 | "sha224": "218c453bf90635bd0a21a75d172703ff6108ef603f65bb821aedade1d6961683",
107 | "sha256": "c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a",
108 | "sha384": "559726be38db125bc85ed7895f6e3cf574c7a01c080c3447db1e8a76764deb3c",
109 | "sha512": "d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5",
110 | "ripemd160": "99a40d3fe4ee95869791d9faa24864562782762171480b620ca8bed3dafbbcac"
111 | }
112 | },
113 | {
114 | "key": "passwordPASSWORDpassword",
115 | "salt": "saltSALTsaltSALTsaltSALTsaltSALTsalt",
116 | "iterations": 4096,
117 | "dkLen": 40,
118 | "results": {
119 | "sha1": "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038b6b89a48612c5a25284e6605e12329",
120 | "sha256": "348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9",
121 | "sha512": "8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd953",
122 | "sha224": "056c4ba438ded91fc14e0594e6f52b87e1f3690c0dc0fbc05784ed9a754ca780e6c017e80c8de278",
123 | "sha384": "819143ad66df9a552559b9e131c52ae6c5c1b0eed18f4d283b8c5c9eaeb92b392c147cc2d2869d58",
124 | "ripemd160": "503b9a069633b261b2d3e4f21c5d0cafeb3f5008aec25ed21418d12630b6ce036ec82a0430ef1974"
125 | },
126 | "resultsOld": {
127 | "sha1": "3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038b6b89a48612c5a25284e6605e12329",
128 | "sha224": "056c4ba438ded91fc14e0594e6f52b87e1f3690c0dc0fbc05784ed9a754ca780e6c017e80c8de278",
129 | "sha256": "348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9",
130 | "sha384": "819143ad66df9a552559b9e131c52ae6c5c1b0eed18f4d283b8c5c9eaeb92b392c147cc2d2869d58",
131 | "sha512": "8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd953",
132 | "ripemd160": "503b9a069633b261b2d3e4f21c5d0cafeb3f5008aec25ed21418d12630b6ce036ec82a0430ef1974"
133 | }
134 | },
135 | {
136 | "key": "pass\u00000word",
137 | "salt": "sa\u00000lt",
138 | "iterations": 4096,
139 | "dkLen": 16,
140 | "results": {
141 | "sha1": "345cbad979dfccb90cac5257bea6ea46",
142 | "sha256": "1df6274d3c0bd2fc7f54fb46f149dda4",
143 | "sha512": "336d14366099e8aac2c46c94a8f178d2",
144 | "sha224": "0aca9ca9634db6ef4927931f633c6453",
145 | "sha384": "b6ab6f8f6532fd9c5c30a79e1f93dcc6",
146 | "ripemd160": "914d58209e6483e491571a60e433124a"
147 | },
148 | "resultsOld": {
149 | "sha1": "345cbad979dfccb90cac5257bea6ea46",
150 | "sha224": "0aca9ca9634db6ef4927931f633c6453",
151 | "sha256": "1df6274d3c0bd2fc7f54fb46f149dda4",
152 | "sha384": "b6ab6f8f6532fd9c5c30a79e1f93dcc6",
153 | "sha512": "336d14366099e8aac2c46c94a8f178d2",
154 | "ripemd160": "914d58209e6483e491571a60e433124a"
155 | }
156 | },
157 | {
158 | "keyHex": "63ffeeddccbbaa",
159 | "salt": "salt",
160 | "iterations": 1,
161 | "dkLen": 32,
162 | "results": {
163 | "sha1": "f6635023b135a57fb8caa89ef8ad93a29d9debb1b011e6e88bffbb212de7c01c",
164 | "sha256": "dadd4a2638c1cf90a220777bc85d81859459513eb83063e3fce7d081490f259a",
165 | "sha512": "f69de451247225a7b30cc47632899572bb980f500d7c606ac9b1c04f928a3488",
166 | "sha224": "9cdee023b5d5e06ccd6c5467463e34fe461a7ed43977f8237f97b0bc7ebfd280",
167 | "sha384": "25c72b6f0e052c883a9273a54cfd41fab86759fa3b33eb7920b923abaad62f99",
168 | "ripemd160": "08609cb567308b81164fe1307c38bb9b87b072a756ce8d74760c4d216ee4e9fb"
169 | },
170 | "resultsOld": {
171 | "sha1": "f6635023b135a57fb8caa89ef8ad93a29d9debb1b011e6e88bffbb212de7c01c",
172 | "sha224": "9cdee023b5d5e06ccd6c5467463e34fe461a7ed43977f8237f97b0bc7ebfd280",
173 | "sha256": "dadd4a2638c1cf90a220777bc85d81859459513eb83063e3fce7d081490f259a",
174 | "sha384": "25c72b6f0e052c883a9273a54cfd41fab86759fa3b33eb7920b923abaad62f99",
175 | "sha512": "f69de451247225a7b30cc47632899572bb980f500d7c606ac9b1c04f928a3488",
176 | "ripemd160": "08609cb567308b81164fe1307c38bb9b87b072a756ce8d74760c4d216ee4e9fb"
177 | }
178 | },
179 | {
180 | "description": "Unicode salt, no truncation due to hex",
181 | "key": "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about",
182 | "saltHex": "6d6e656d6f6e6963e383a1e383bce38388e383abe382abe38299e3838fe38299e382a6e38299e382a1e381afe3829ae381afe38299e3818fe38299e3829de38299e381a1e381a1e38299e58d81e4babae58d81e889b2",
183 | "iterations": 2048,
184 | "dkLen": 64,
185 | "results": {
186 | "sha1": "7e042a2f41ba17e2235fbc794e22a150816b0f54a1dfe113919fccb7a056066a109385e538f183c92bad896ae8b7d8e0f4cd66df359c77c8c7785cd1001c9a2c",
187 | "sha256": "0b57118f2b6b079d9371c94da3a8315c3ada87a1e819b40c4c4e90b36ff2d3c8fd7555538b5119ac4d3da7844aa4259d92f9dd2188e78ac33c4b08d8e6b5964b",
188 | "sha512": "ba553eedefe76e67e2602dc20184c564010859faada929a090dd2c57aacb204ceefd15404ab50ef3e8dbeae5195aeae64b0def4d2eead1cdc728a33ced520ffd",
189 | "sha224": "d76474c525616ce2a527d23df8d6f6fcc4251cc3535cae4e955810a51ead1ec6acbe9c9619187ca5a3c4fd636de5b5fe58d031714731290bbc081dbf0fcb8fc1",
190 | "sha384": "15010450f456769467e834db7fa93dd9d353e8bb733b63b0621090f96599ac3316908eb64ac9366094f0787cd4bfb2fea25be41dc271a19309710db6144f9b34",
191 | "ripemd160": "255321c22a32f41ed925032043e01afe9cacf05470c6506621782c9d768df03c74cb3fe14a4296feba4c2825e736486fb3871e948f9c413ca006cc20b7ff6d37"
192 | },
193 | "resultsOld": {
194 | "sha1": "7e042a2f41ba17e2235fbc794e22a150816b0f54a1dfe113919fccb7a056066a109385e538f183c92bad896ae8b7d8e0f4cd66df359c77c8c7785cd1001c9a2c",
195 | "sha224": "d76474c525616ce2a527d23df8d6f6fcc4251cc3535cae4e955810a51ead1ec6acbe9c9619187ca5a3c4fd636de5b5fe58d031714731290bbc081dbf0fcb8fc1",
196 | "sha256": "0b57118f2b6b079d9371c94da3a8315c3ada87a1e819b40c4c4e90b36ff2d3c8fd7555538b5119ac4d3da7844aa4259d92f9dd2188e78ac33c4b08d8e6b5964b",
197 | "sha384": "15010450f456769467e834db7fa93dd9d353e8bb733b63b0621090f96599ac3316908eb64ac9366094f0787cd4bfb2fea25be41dc271a19309710db6144f9b34",
198 | "sha512": "ba553eedefe76e67e2602dc20184c564010859faada929a090dd2c57aacb204ceefd15404ab50ef3e8dbeae5195aeae64b0def4d2eead1cdc728a33ced520ffd",
199 | "ripemd160": "255321c22a32f41ed925032043e01afe9cacf05470c6506621782c9d768df03c74cb3fe14a4296feba4c2825e736486fb3871e948f9c413ca006cc20b7ff6d37"
200 | }
201 | },
202 | {
203 | "key": "password",
204 | "salt": "salt",
205 | "iterations": 1,
206 | "dkLen": 10,
207 | "results": {
208 | "sha1": "0c60c80f961f0e71f3a9",
209 | "sha256": "120fb6cffcf8b32c43e7",
210 | "sha512": "867f70cf1ade02cff375",
211 | "sha224": "3c198cbdb9464b785796",
212 | "sha384": "c0e14f06e49e32d73f9f",
213 | "ripemd160": "b725258b125e0bacb0e2"
214 | },
215 | "resultsOld": {
216 | "sha1": "0c60c80f961f0e71f3a9",
217 | "sha224": "3c198cbdb9464b785796",
218 | "sha256": "120fb6cffcf8b32c43e7",
219 | "sha384": "c0e14f06e49e32d73f9f",
220 | "sha512": "867f70cf1ade02cff375",
221 | "ripemd160": "b725258b125e0bacb0e2"
222 | }
223 | },
224 | {
225 | "key": "password",
226 | "salt": "salt",
227 | "iterations": 1,
228 | "dkLen": 100,
229 | "results": {
230 | "sha1": "0c60c80f961f0e71f3a9b524af6012062fe037a6e0f0eb94fe8fc46bdc637164ac2e7a8e3f9d2e83ace57e0d50e5e1071367c179bc86c767fc3f78ddb561363fc692ba406d1301e42bcccc3c520d06751d78b80c3db926b16ffa3395bd697c647f280b51",
231 | "sha256": "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b4dbf3a2f3dad3377264bb7b8e8330d4efc7451418617dabef683735361cdc18c22cd7fe60fa40e91c65849e1f60c0d8b62a7b2dbd0d3dfd75fb8498a5c2131ab02b66de5",
232 | "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce7b532e206c2967d4c7d2ffa460539fc4d4e5eec70125d74c6c7cf86d25284f297907fcea",
233 | "sha224": "3c198cbdb9464b7857966bd05b7bc92bc1cc4e6e63155d4e490557fd859894978ab846d52a1083ac610c36c2c5ea8ce4a024dd691064d5453bd17b15ea1ac1944bbfd62e61b997e7b22660f588e297186572480015f33bc2bfd2b423827bcdcdb4845914",
234 | "sha384": "c0e14f06e49e32d73f9f52ddf1d0c5c7191609233631dadd76a567db42b78676b38fc800cc53ddb642f5c74442e62be44d727702213e3bb9223c53b767fbfb5db9d270d54c45d9cb6003d2967280b22671e2dbc6375f6ebf219c36f0d127be35e19d65a8",
235 | "ripemd160": "b725258b125e0bacb0e2307e34feb16a4d0d6aed6cb4b0eee458fc18290204289e55d962783bf52237d264cbbab25f18d89d8c798f90f558ea7b45bdf3d083340c18b9d23ba842183c5364d18bc0ffde5a8a408dd7ef02dde561a08d21c6d2325a69869b"
236 | },
237 | "resultsOld": {
238 | "sha1": "0c60c80f961f0e71f3a9b524af6012062fe037a6e0f0eb94fe8fc46bdc637164ac2e7a8e3f9d2e83ace57e0d50e5e1071367c179bc86c767fc3f78ddb561363fc692ba406d1301e42bcccc3c520d06751d78b80c3db926b16ffa3395bd697c647f280b51",
239 | "sha224": "3c198cbdb9464b7857966bd05b7bc92bc1cc4e6e63155d4e490557fd859894978ab846d52a1083ac610c36c2c5ea8ce4a024dd691064d5453bd17b15ea1ac1944bbfd62e61b997e7b22660f588e297186572480015f33bc2bfd2b423827bcdcdb4845914",
240 | "sha256": "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b4dbf3a2f3dad3377264bb7b8e8330d4efc7451418617dabef683735361cdc18c22cd7fe60fa40e91c65849e1f60c0d8b62a7b2dbd0d3dfd75fb8498a5c2131ab02b66de5",
241 | "sha384": "c0e14f06e49e32d73f9f52ddf1d0c5c7191609233631dadd76a567db42b78676b38fc800cc53ddb642f5c74442e62be44d727702213e3bb9223c53b767fbfb5db9d270d54c45d9cb6003d2967280b22671e2dbc6375f6ebf219c36f0d127be35e19d65a8",
242 | "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce7b532e206c2967d4c7d2ffa460539fc4d4e5eec70125d74c6c7cf86d25284f297907fcea",
243 | "ripemd160": "b725258b125e0bacb0e2307e34feb16a4d0d6aed6cb4b0eee458fc18290204289e55d962783bf52237d264cbbab25f18d89d8c798f90f558ea7b45bdf3d083340c18b9d23ba842183c5364d18bc0ffde5a8a408dd7ef02dde561a08d21c6d2325a69869b"
244 | }
245 | },
246 | {
247 | "keyUint8Array": [112, 97, 115, 115, 119, 111, 114, 100],
248 | "salt": "salt",
249 | "iterations": 1,
250 | "dkLen": 32,
251 | "results": {
252 | "sha1": "0c60c80f961f0e71f3a9b524af6012062fe037a6e0f0eb94fe8fc46bdc637164",
253 | "sha256": "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b",
254 | "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252",
255 | "sha224": "3c198cbdb9464b7857966bd05b7bc92bc1cc4e6e63155d4e490557fd85989497",
256 | "sha384": "c0e14f06e49e32d73f9f52ddf1d0c5c7191609233631dadd76a567db42b78676",
257 | "ripemd160": "b725258b125e0bacb0e2307e34feb16a4d0d6aed6cb4b0eee458fc1829020428"
258 | },
259 | "resultsOld": {
260 | "sha1": "a33dddc30478185515311f8752895d36ea4363a2000d3d26b98e7dffaaa13c3c",
261 | "sha224": "35cc2b821df141e4346ae61836ac2c25a653c02a799e3113c4f6769ddc214f90",
262 | "sha256": "f135c27993baf98773c5cdb40a5706ce6a345cde61b000a67858650cd6a324d7",
263 | "sha384": "0f2e98f6834469c6dd38a3484e8eba4ddfa88b6440358024e1bf865ad155401a",
264 | "sha512": "00ef42cdbfc98d29db20976608e455567fdddf141f6eb03b5a85addd25974f5d",
265 | "ripemd160": "5b2706c986457d820a1214710a25fdbd52c43e6176f7b56b40888d39377243af"
266 | }
267 | },
268 | {
269 | "key": "password",
270 | "saltUint8Array": [115, 97, 108, 116],
271 | "iterations": 1,
272 | "dkLen": 32,
273 | "results": {
274 | "sha1": "0c60c80f961f0e71f3a9b524af6012062fe037a6e0f0eb94fe8fc46bdc637164",
275 | "sha256": "120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b",
276 | "sha512": "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252",
277 | "sha224": "3c198cbdb9464b7857966bd05b7bc92bc1cc4e6e63155d4e490557fd85989497",
278 | "sha384": "c0e14f06e49e32d73f9f52ddf1d0c5c7191609233631dadd76a567db42b78676",
279 | "ripemd160": "b725258b125e0bacb0e2307e34feb16a4d0d6aed6cb4b0eee458fc1829020428"
280 | },
281 | "resultsOld": {
282 | "sha1": "8754c32c64b0f524fc50c00f788135de2d2dd767a414b9cd7d5203200b0377cd",
283 | "sha224": "63d0845366ccd72f2f08741aebf0f3078119eec2c7f3ce1f5afea6c46768c6ae",
284 | "sha256": "c1232f10f62715fda06ae7c0a2037ca19b33cf103b727ba56d870c11f290a2ab",
285 | "sha384": "f368e7e5b466110c1e0b320710b0a64f5f5245baf47df8d8d02818aa88ad68a0",
286 | "sha512": "ae16ce6dfd4a6a0c20421ff80eb3ba4acc13bd1dea45f8bb034b753e4cf2032f",
287 | "ripemd160": "e65851784833c8b718d16903c816ac278a1f720ffad96cfdfadbae8a90c4d5da"
288 | }
289 | },
290 | {
291 | "keyInt32Array": [112, 97, 115, 115, 119, 111, 114, 100],
292 | "salt": "salt",
293 | "iterations": 1,
294 | "dkLen": 32,
295 | "results": {
296 | "sha1": "f260ccd0bbc8fe6773119b834feec48636b716caad4180a4d0af4f9aa67c646e",
297 | "sha256": "9b4608f5eeab348f0b9d85a918b140706b24f275acf6829382dfee491015f9eb",
298 | "sha512": "c44b8f26550fe6ca0a55bce54b4a75e9530398f32ec28b59d0fded996e95e3d5",
299 | "sha224": "03d0c2b530ec6339e6418cb0f906e50591619be40aa8817aa9c7305d1773231c",
300 | "sha384": "2e69d62ae8c21ebc2de45a885b488f65fb88dfa58aaa9c57dd1fcb9d1edce96a",
301 | "ripemd160": "fc69276ba3f145492065feb0259b9edf68179f2023c95094e71ac7d01748018a"
302 | },
303 | "resultsOld": {
304 | "sha1": "a33dddc30478185515311f8752895d36ea4363a2000d3d26b98e7dffaaa13c3c",
305 | "sha224": "35cc2b821df141e4346ae61836ac2c25a653c02a799e3113c4f6769ddc214f90",
306 | "sha256": "f135c27993baf98773c5cdb40a5706ce6a345cde61b000a67858650cd6a324d7",
307 | "sha384": "0f2e98f6834469c6dd38a3484e8eba4ddfa88b6440358024e1bf865ad155401a",
308 | "sha512": "00ef42cdbfc98d29db20976608e455567fdddf141f6eb03b5a85addd25974f5d",
309 | "ripemd160": "5b2706c986457d820a1214710a25fdbd52c43e6176f7b56b40888d39377243af"
310 | }
311 | },
312 | {
313 | "key": "password",
314 | "saltInt32Array": [115, 97, 108, 116],
315 | "iterations": 1,
316 | "dkLen": 32,
317 | "results": {
318 | "sha1": "b297f1ea23008f10ba9d645961e4661109e804b10af26bea22c44244492d6252",
319 | "sha256": "f678f0772894c079f21377d9ee1e76dd77b62dfc1f0575e6aa9eb030af7a356a",
320 | "sha512": "7f8133f6937ae1d7e4a43c19aabd2de8308d5b833341281716a501334cdb2470",
321 | "sha224": "ab66d29d3dacc731e44f091a7baa051926219cf493e8b9e3934cedfb215adc8b",
322 | "sha384": "cf139d648cf63e9b85a3b9b8f23f4445b84d22201bc2544bc273a17d5dcb7b28",
323 | "ripemd160": "26142e48fae1ad1c53be54823aadda2aa7d42f5524463fb1eff0efafa08edb9d"
324 | },
325 | "resultsOld": {
326 | "sha1": "8754c32c64b0f524fc50c00f788135de2d2dd767a414b9cd7d5203200b0377cd",
327 | "sha224": "63d0845366ccd72f2f08741aebf0f3078119eec2c7f3ce1f5afea6c46768c6ae",
328 | "sha256": "c1232f10f62715fda06ae7c0a2037ca19b33cf103b727ba56d870c11f290a2ab",
329 | "sha384": "f368e7e5b466110c1e0b320710b0a64f5f5245baf47df8d8d02818aa88ad68a0",
330 | "sha512": "ae16ce6dfd4a6a0c20421ff80eb3ba4acc13bd1dea45f8bb034b753e4cf2032f",
331 | "ripemd160": "e65851784833c8b718d16903c816ac278a1f720ffad96cfdfadbae8a90c4d5da"
332 | }
333 | },
334 | {
335 | "keyFloat64Array": [112, 97, 115, 115, 119, 111, 114, 100],
336 | "salt": "salt",
337 | "iterations": 1,
338 | "dkLen": 32,
339 | "results": {
340 | "sha1": "c2b17a7e98cc48690a92cd9f753a2c700229045905167571aa281aafe8230bba",
341 | "sha256": "55d62579a083a6c14b886710f81b54f567d214d343af776e5e90c467ea81b821",
342 | "sha512": "ded01ce343e2683d962fc74b7b5ceef525228f49393ce9353254f44e3dc7e9aa",
343 | "sha224": "5f10a348d320c7555b972b8d7d45a363a91e1a82dea063c3ac495cfad74a8d89",
344 | "sha384": "4b7f97dbadfd652e0579499d0e23607ec476ed4bea9d6f1740d0b110e2d08792",
345 | "ripemd160": "f92080d972a649d98d91a53922863fc7b8076c54869e9885f9a804868ef752e0"
346 | },
347 | "resultsOld": {
348 | "sha1": "a33dddc30478185515311f8752895d36ea4363a2000d3d26b98e7dffaaa13c3c",
349 | "sha224": "35cc2b821df141e4346ae61836ac2c25a653c02a799e3113c4f6769ddc214f90",
350 | "sha256": "f135c27993baf98773c5cdb40a5706ce6a345cde61b000a67858650cd6a324d7",
351 | "sha384": "0f2e98f6834469c6dd38a3484e8eba4ddfa88b6440358024e1bf865ad155401a",
352 | "sha512": "00ef42cdbfc98d29db20976608e455567fdddf141f6eb03b5a85addd25974f5d",
353 | "ripemd160": "5b2706c986457d820a1214710a25fdbd52c43e6176f7b56b40888d39377243af"
354 | }
355 | },
356 | {
357 | "key": "password",
358 | "saltFloat64Array": [115, 97, 108, 116],
359 | "iterations": 1,
360 | "dkLen": 32,
361 | "results": {
362 | "sha1": "f158b9edd28c16ad3b41e0e8197ec132a98c2ddea73b959f55ec9792e0b29d6f",
363 | "sha256": "a6154d17480547a10212f75883509842f88f2ca5d6c1a2419646e47342051852",
364 | "sha512": "b10c2ea742de7dd0525988761ee1733564c91380eeaa1b199f4fafcbf7144b0c",
365 | "sha224": "29b315ac30c7d5e1640ca0f9e27b68a794fb9f950b8dd117129824f103ffb9db",
366 | "sha384": "624b4ed6ad389b976fb7503e54a35109f249c29ac6eb8b56850152be21b3cb0e",
367 | "ripemd160": "8999b9280207bc9c76cf25327aa352da26a683fac7a2adff17a39dcc4f4c3b5b"
368 | },
369 | "resultsOld": {
370 | "sha1": "8754c32c64b0f524fc50c00f788135de2d2dd767a414b9cd7d5203200b0377cd",
371 | "sha224": "63d0845366ccd72f2f08741aebf0f3078119eec2c7f3ce1f5afea6c46768c6ae",
372 | "sha256": "c1232f10f62715fda06ae7c0a2037ca19b33cf103b727ba56d870c11f290a2ab",
373 | "sha384": "f368e7e5b466110c1e0b320710b0a64f5f5245baf47df8d8d02818aa88ad68a0",
374 | "sha512": "ae16ce6dfd4a6a0c20421ff80eb3ba4acc13bd1dea45f8bb034b753e4cf2032f",
375 | "ripemd160": "e65851784833c8b718d16903c816ac278a1f720ffad96cfdfadbae8a90c4d5da"
376 | }
377 | }
378 | ],
379 | "invalid": [
380 | {
381 | "key": "password",
382 | "salt": "salt",
383 | "iterations": "NaN",
384 | "dkLen": 16,
385 | "exception": "Iterations not a number"
386 | },
387 | {
388 | "key": "password",
389 | "salt": "salt",
390 | "iterations": -1,
391 | "dkLen": 16,
392 | "exception": "Bad iterations"
393 | },
394 | {
395 | "key": "password",
396 | "salt": "salt",
397 | "iterations": 1,
398 | "dkLen": "NaN",
399 | "exception": "Key length not a number"
400 | },
401 | {
402 | "key": "password",
403 | "salt": "salt",
404 | "iterations": 1,
405 | "dkLen": -1,
406 | "exception": "Bad key length"
407 | }
408 | ]
409 | }
410 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // SHA-1 vectors generated by Node.js
4 | // SHA-256/SHA-512 test vectors from:
5 | // https://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors
6 | // https://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors
7 | var fixtures = require('./fixtures');
8 | var tape = require('tape');
9 | var satisfies = require('semver').satisfies;
10 | var Buffer = require('safe-buffer').Buffer;
11 |
12 | var pVersionMajor = parseInt(process.version.split('.')[0].slice(1), 10);
13 | /* istanbul ignore next */
14 | if (pVersionMajor !== 4 || process.browser) {
15 | fixtures.invalid.push({
16 | key: 'password',
17 | salt: 'salt',
18 | iterations: 1,
19 | dkLen: -1,
20 | exception: 'Bad key length'
21 | }, {
22 | key: 'password',
23 | salt: 'salt',
24 | iterations: 1,
25 | dkLen: 4073741824,
26 | exception: 'Bad key length'
27 | });
28 | }
29 | /* istanbul ignore next */
30 | if (pVersionMajor >= 5 || process.browser) {
31 | fixtures.invalid.push({
32 | key: 'password',
33 | salt: 'salt',
34 | iterations: 1,
35 | dkLen: NaN,
36 | exception: 'Bad key length'
37 | }, {
38 | key: 'password',
39 | salt: 'salt',
40 | iterations: 1,
41 | dkLen: Infinity,
42 | exception: 'Bad key length'
43 | });
44 | }
45 | /* istanbul ignore next */
46 | if (pVersionMajor >= 6 || process.browser) {
47 | fixtures.valid.push({
48 | description: 'Unicode salt, no truncation',
49 | key: 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
50 | salt: 'mnemonicメートルガバヴァぱばぐゞちぢ十人十色',
51 | iterations: 2048,
52 | dkLen: 64,
53 | results: {
54 | sha1: '7e042a2f41ba17e2235fbc794e22a150816b0f54a1dfe113919fccb7a056066a109385e538f183c92bad896ae8b7d8e0f4cd66df359c77c8c7785cd1001c9a2c',
55 | sha256: '0b57118f2b6b079d9371c94da3a8315c3ada87a1e819b40c4c4e90b36ff2d3c8fd7555538b5119ac4d3da7844aa4259d92f9dd2188e78ac33c4b08d8e6b5964b',
56 | sha512: 'ba553eedefe76e67e2602dc20184c564010859faada929a090dd2c57aacb204ceefd15404ab50ef3e8dbeae5195aeae64b0def4d2eead1cdc728a33ced520ffd',
57 | sha224: 'd76474c525616ce2a527d23df8d6f6fcc4251cc3535cae4e955810a51ead1ec6acbe9c9619187ca5a3c4fd636de5b5fe58d031714731290bbc081dbf0fcb8fc1',
58 | sha384: '15010450f456769467e834db7fa93dd9d353e8bb733b63b0621090f96599ac3316908eb64ac9366094f0787cd4bfb2fea25be41dc271a19309710db6144f9b34',
59 | ripemd160: '255321c22a32f41ed925032043e01afe9cacf05470c6506621782c9d768df03c74cb3fe14a4296feba4c2825e736486fb3871e948f9c413ca006cc20b7ff6d37'
60 | }
61 | });
62 |
63 | // 'binary' behaviour, Node 6 defaulted to 'utf-8'
64 | } else {
65 | fixtures.valid.push({
66 | description: 'Unicode salt, suffers from truncation',
67 | key: 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about',
68 | salt: 'mnemonicメートルガバヴァぱばぐゞちぢ十人十色',
69 | iterations: 2048,
70 | dkLen: 64,
71 | results: {
72 | sha1: 'd85d14adcb7bdb5d976160e504f520a98cf71aca4cd5fceadf37759743bd6e1d2ff78bdd4403552aef7658094384b341ede80fffd334182be076f9d988a0a40f',
73 | sha256: 'b86b5b900c29ed2724359afd793e10ffc1eb0e7d6f624fc9c85b8ac1785d9a2f0575af52a2338e611f2e6cffdee544adfff6f3d4f43be2ba0e2bd7e917b38a14',
74 | sha512: '3a863fa00f2e97a83fa9b18805e0047a6282cbae0ff48438b33a14475771c52d05137daa12e364cb34d84547ac07568b801c5c7f8dd4baaeee18a67a5c6a3377',
75 | sha224: '95727793842437774ad9ae27b8154a6f37f208b75a03d3a4d4a2443422bb6bc85efcfa92aa4376926ea89a8f5a63118eecdb58c8ca28ab31007da79437e0a1ef',
76 | sha384: '1a7e02e8ba0e357269a55642024b85738b95238d6cdc49bc440204995aefeff499e22cba76d4c7e96b7d4a9596a70e744f53fa94f3547e7dc506fcaf16ceb4a2',
77 | ripemd160: 'bac7849db13e90604620945695288ffee20369107c3a6632d6b1d6b926175ac914319b5a742e6b1a37b82841b6f010ad47ebdb5cd608026eb48513bf68cb54f5'
78 | }
79 | });
80 | }
81 |
82 | function runTests(name, compat) {
83 | tape(name + ' defaults to sha1 and handles buffers', function (t) {
84 | t.plan(3);
85 |
86 | var resultSync = compat.pbkdf2Sync('password', 'salt', 1, 32);
87 | t.equal(resultSync.toString('hex'), '0c60c80f961f0e71f3a9b524af6012062fe037a6e0f0eb94fe8fc46bdc637164');
88 |
89 | compat.pbkdf2(Buffer.from('password'), Buffer.from('salt'), 1, 32, function (err, result) {
90 | t.error(err);
91 | t.equal(result.toString('hex'), '0c60c80f961f0e71f3a9b524af6012062fe037a6e0f0eb94fe8fc46bdc637164');
92 | });
93 | });
94 |
95 | tape(name + ' should throw if no callback is provided', function (t) {
96 | t.plan(1);
97 |
98 | t['throws'](function () {
99 | compat.pbkdf2('password', 'salt', 1, 32, 'sha1');
100 | }, /No callback provided to pbkdf2/);
101 | });
102 |
103 | tape(name + ' should throw if the password is not a string or an ArrayBuffer', function (t) {
104 | t.plan(2);
105 |
106 | t['throws'](function () {
107 | compat.pbkdf2(['a'], 'salt', 1, 32, 'sha1', function () {});
108 | }, /Password must be a string, a Buffer, a typed array or a DataView/);
109 |
110 | t['throws'](function () {
111 | compat.pbkdf2Sync(['a'], 'salt', 1, 32, 'sha1');
112 | }, /Password must be a string, a Buffer, a typed array or a DataView/);
113 | });
114 |
115 | tape(name + ' should throw if the salt is not a string or an ArrayBuffer', function (t) {
116 | t.plan(2);
117 |
118 | t['throws'](function () {
119 | compat.pbkdf2('pass', ['salt'], 1, 32, 'sha1');
120 | }, /Salt must be a string, a Buffer, a typed array or a DataView/);
121 |
122 | t['throws'](function () {
123 | compat.pbkdf2Sync('pass', ['salt'], 1, 32, 'sha1');
124 | }, /Salt must be a string, a Buffer, a typed array or a DataView/);
125 | });
126 |
127 | var algos = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160'];
128 | algos.forEach(function (algorithm) {
129 | var isUnsupported = satisfies(process.version, '^17') && algorithm === 'ripemd160';
130 | tape(
131 | name + ' + ' + algorithm,
132 | { skip: isUnsupported && 'this node version does not support ' + algorithm },
133 | function (t) {
134 | fixtures.valid.forEach(function (f) {
135 | var key, keyType, salt, saltType;
136 | if (f.keyUint8Array) {
137 | key = new Uint8Array(f.keyUint8Array);
138 | keyType = 'Uint8Array';
139 | } else if (f.keyInt32Array) {
140 | key = new Int32Array(f.keyInt32Array);
141 | keyType = 'Int32Array';
142 | } else if (f.keyFloat64Array) {
143 | key = new Float64Array(f.keyFloat64Array);
144 | keyType = 'Float64Array';
145 | } else if (f.keyHex) {
146 | key = Buffer.from(f.keyHex, 'hex');
147 | keyType = 'hex';
148 | } else {
149 | key = f.key;
150 | keyType = 'string';
151 | }
152 | if (f.saltUint8Array) {
153 | salt = new Uint8Array(f.saltUint8Array);
154 | saltType = 'Uint8Array';
155 | } else if (f.saltInt32Array) {
156 | salt = new Int32Array(f.saltInt32Array);
157 | saltType = 'Int32Array';
158 | } else if (f.saltFloat64Array) {
159 | salt = new Float64Array(f.saltFloat64Array);
160 | saltType = 'Float64Array';
161 | } else if (f.saltHex) {
162 | salt = Buffer.from(f.saltHex, 'hex');
163 | saltType = 'hex';
164 | } else {
165 | salt = f.salt;
166 | saltType = 'string';
167 | }
168 | var expected = satisfies(process.version, '>= 3') || !f.resultsOld ? f.results[algorithm] : f.resultsOld[algorithm];
169 | var description = algorithm + ' encodes "' + key + '" (' + keyType + ') with salt "' + salt + '" (' + saltType + ') with ' + algorithm + ' to ' + expected;
170 |
171 | t.test(name + ' async w/ ' + description, function (st) {
172 | st.plan(2);
173 |
174 | compat.pbkdf2(key, salt, f.iterations, f.dkLen, algorithm, function (err, result) {
175 | st.error(err);
176 | st.equal(result.toString('hex'), expected);
177 | });
178 | });
179 |
180 | t.test(name + 'sync w/ ' + description, function (st) {
181 | st.plan(1);
182 |
183 | var result = compat.pbkdf2Sync(key, salt, f.iterations, f.dkLen, algorithm);
184 | st.equal(result.toString('hex'), expected);
185 | });
186 | });
187 |
188 | fixtures.invalid.forEach(function (f) {
189 | var description = algorithm + ' should throw ' + f.exception;
190 |
191 | t.test(name + ' async w/ ' + description, function (st) {
192 | st.plan(1);
193 | /* istanbul ignore next */
194 | function noop() {}
195 | st['throws'](function () {
196 | compat.pbkdf2(f.key, f.salt, f.iterations, f.dkLen, f.algo, noop);
197 | }, new RegExp(f.exception));
198 | });
199 |
200 | t.test(name + ' sync w/' + description, function (st) {
201 | st.plan(1);
202 |
203 | st['throws'](function () {
204 | compat.pbkdf2Sync(f.key, f.salt, f.iterations, f.dkLen, f.algo);
205 | }, new RegExp(f.exception));
206 | });
207 | });
208 |
209 | t.end();
210 | }
211 | );
212 | });
213 | }
214 |
215 | var js = require('../browser');
216 | runTests('JavaScript pbkdf2', js);
217 |
218 | var assign = require('object.assign');
219 |
220 | /* istanbul ignore next */
221 | if (!process.browser) {
222 | /* eslint global-require: 0 */
223 | var browser = assign({}, js);
224 | browser.pbkdf2Sync = require('../lib/sync-browser');
225 | runTests('browser pbkdf2', {
226 | pbkdf2: browser.pbkdf2,
227 | pbkdf2Sync: require('../lib/sync-browser')
228 | });
229 | runTests('node pbkdf2', require('../'));
230 | }
231 |
--------------------------------------------------------------------------------