├── .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 | [![NPM Package](https://img.shields.io/npm/v/pbkdf2.svg?style=flat-square)](https://www.npmjs.org/package/pbkdf2) 4 | [![Build Status](https://img.shields.io/travis/crypto-browserify/pbkdf2.svg?branch=master&style=flat-square)](https://travis-ci.org/crypto-browserify/pbkdf2) 5 | [![Dependency status](https://img.shields.io/david/crypto-browserify/pbkdf2.svg?style=flat-square)](https://david-dm.org/crypto-browserify/pbkdf2#info=dependencies) 6 | 7 | [![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](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 | --------------------------------------------------------------------------------