8889841cindex.js000066600000002406150544105370006223 0ustar00var native = require('crypto') var checkParameters = require('./lib/precondition') var defaultEncoding = require('./lib/default-encoding') var toBuffer = require('./lib/to-buffer') function nativePBKDF2 (password, salt, iterations, keylen, digest, callback) { checkParameters(iterations, keylen) password = toBuffer(password, defaultEncoding, 'Password') salt = toBuffer(salt, defaultEncoding, 'Salt') if (typeof digest === 'function') { callback = digest digest = 'sha1' } if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2') return native.pbkdf2(password, salt, iterations, keylen, digest, callback) } function nativePBKDF2Sync (password, salt, iterations, keylen, digest) { checkParameters(iterations, keylen) password = toBuffer(password, defaultEncoding, 'Password') salt = toBuffer(salt, defaultEncoding, 'Salt') digest = digest || 'sha1' return native.pbkdf2Sync(password, salt, iterations, keylen, digest) } /* istanbul ignore next */ if (!native.pbkdf2Sync || native.pbkdf2Sync.toString().indexOf('keylen, digest') === -1) { exports.pbkdf2Sync = require('./lib/sync') exports.pbkdf2 = require('./lib/async') // native } else { exports.pbkdf2Sync = nativePBKDF2Sync exports.pbkdf2 = nativePBKDF2 } README.md000066600000003117150544105370006035 0ustar00# pbkdf2 [![NPM Package](https://img.shields.io/npm/v/pbkdf2.svg?style=flat-square)](https://www.npmjs.org/package/pbkdf2) [![Build Status](https://img.shields.io/travis/crypto-browserify/pbkdf2.svg?branch=master&style=flat-square)](https://travis-ci.org/crypto-browserify/pbkdf2) [![Dependency status](https://img.shields.io/david/crypto-browserify/pbkdf2.svg?style=flat-square)](https://david-dm.org/crypto-browserify/pbkdf2#info=dependencies) [![js-standard-style](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) This library provides the functionality of PBKDF2 with the ability to use any supported hashing algorithm returned from `crypto.getHashes()` ## Usage ```js var pbkdf2 = require('pbkdf2') var derivedKey = pbkdf2.pbkdf2Sync('password', 'salt', 1, 32, 'sha512') ... ``` 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). For high performance, use the `async` variant (`pbkdf2.pbkdf2`), not `pbkdf2.pbkdf2Sync`, this variant has the oppurtunity to use `window.crypto.subtle` when browserified. ## Credits 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. 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). browser.js000066600000000123150544105370006571 0ustar00exports.pbkdf2 = require('./lib/async') exports.pbkdf2Sync = require('./lib/sync') lib/to-buffer.js000066600000000636150544105370007556 0ustar00var Buffer = require('safe-buffer').Buffer module.exports = function (thing, encoding, name) { if (Buffer.isBuffer(thing)) { return thing } else if (typeof thing === 'string') { return Buffer.from(thing, encoding) } else if (ArrayBuffer.isView(thing)) { return Buffer.from(thing.buffer) } else { throw new TypeError(name + ' must be a string, a Buffer, a typed array or a DataView') } } lib/sync.js000066600000002261150544105370006635 0ustar00var sizes = { md5: 16, sha1: 20, sha224: 28, sha256: 32, sha384: 48, sha512: 64, rmd160: 20, ripemd160: 20 } var createHmac = require('create-hmac') var Buffer = require('safe-buffer').Buffer var checkParameters = require('./precondition') var defaultEncoding = require('./default-encoding') var toBuffer = require('./to-buffer') function pbkdf2 (password, salt, iterations, keylen, digest) { checkParameters(iterations, keylen) password = toBuffer(password, defaultEncoding, 'Password') salt = toBuffer(salt, defaultEncoding, 'Salt') digest = digest || 'sha1' var DK = Buffer.allocUnsafe(keylen) var block1 = Buffer.allocUnsafe(salt.length + 4) salt.copy(block1, 0, 0, salt.length) var destPos = 0 var hLen = sizes[digest] var l = Math.ceil(keylen / hLen) for (var i = 1; i <= l; i++) { block1.writeUInt32BE(i, salt.length) var T = createHmac(digest, password).update(block1).digest() var U = T for (var j = 1; j < iterations; j++) { U = createHmac(digest, password).update(U).digest() for (var k = 0; k < hLen; k++) T[k] ^= U[k] } T.copy(DK, destPos) destPos += hLen } return DK } module.exports = pbkdf2 lib/async.js000066600000005712150544105370007002 0ustar00var Buffer = require('safe-buffer').Buffer var checkParameters = require('./precondition') var defaultEncoding = require('./default-encoding') var sync = require('./sync') var toBuffer = require('./to-buffer') var ZERO_BUF var subtle = global.crypto && global.crypto.subtle var toBrowser = { sha: 'SHA-1', 'sha-1': 'SHA-1', sha1: 'SHA-1', sha256: 'SHA-256', 'sha-256': 'SHA-256', sha384: 'SHA-384', 'sha-384': 'SHA-384', 'sha-512': 'SHA-512', sha512: 'SHA-512' } var checks = [] function checkNative (algo) { if (global.process && !global.process.browser) { return Promise.resolve(false) } if (!subtle || !subtle.importKey || !subtle.deriveBits) { return Promise.resolve(false) } if (checks[algo] !== undefined) { return checks[algo] } ZERO_BUF = ZERO_BUF || Buffer.alloc(8) var prom = browserPbkdf2(ZERO_BUF, ZERO_BUF, 10, 128, algo) .then(function () { return true }).catch(function () { return false }) checks[algo] = prom return prom } var nextTick function getNextTick () { if (nextTick) { return nextTick } if (global.process && global.process.nextTick) { nextTick = global.process.nextTick } else if (global.queueMicrotask) { nextTick = global.queueMicrotask } else if (global.setImmediate) { nextTick = global.setImmediate } else { nextTick = global.setTimeout } return nextTick } function browserPbkdf2 (password, salt, iterations, length, algo) { return subtle.importKey( 'raw', password, { name: 'PBKDF2' }, false, ['deriveBits'] ).then(function (key) { return subtle.deriveBits({ name: 'PBKDF2', salt: salt, iterations: iterations, hash: { name: algo } }, key, length << 3) }).then(function (res) { return Buffer.from(res) }) } function resolvePromise (promise, callback) { promise.then(function (out) { getNextTick()(function () { callback(null, out) }) }, function (e) { getNextTick()(function () { callback(e) }) }) } module.exports = function (password, salt, iterations, keylen, digest, callback) { if (typeof digest === 'function') { callback = digest digest = undefined } digest = digest || 'sha1' var algo = toBrowser[digest.toLowerCase()] if (!algo || typeof global.Promise !== 'function') { getNextTick()(function () { var out try { out = sync(password, salt, iterations, keylen, digest) } catch (e) { return callback(e) } callback(null, out) }) return } checkParameters(iterations, keylen) password = toBuffer(password, defaultEncoding, 'Password') salt = toBuffer(salt, defaultEncoding, 'Salt') if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2') resolvePromise(checkNative(algo).then(function (resp) { if (resp) return browserPbkdf2(password, salt, iterations, keylen, algo) return sync(password, salt, iterations, keylen, digest) }), callback) } lib/sync-browser.js000066600000004722150544105370010322 0ustar00var md5 = require('create-hash/md5') var RIPEMD160 = require('ripemd160') var sha = require('sha.js') var Buffer = require('safe-buffer').Buffer var checkParameters = require('./precondition') var defaultEncoding = require('./default-encoding') var toBuffer = require('./to-buffer') var ZEROS = Buffer.alloc(128) var sizes = { md5: 16, sha1: 20, sha224: 28, sha256: 32, sha384: 48, sha512: 64, rmd160: 20, ripemd160: 20 } function Hmac (alg, key, saltLen) { var hash = getDigest(alg) var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64 if (key.length > blocksize) { key = hash(key) } else if (key.length < blocksize) { key = Buffer.concat([key, ZEROS], blocksize) } var ipad = Buffer.allocUnsafe(blocksize + sizes[alg]) var opad = Buffer.allocUnsafe(blocksize + sizes[alg]) for (var i = 0; i < blocksize; i++) { ipad[i] = key[i] ^ 0x36 opad[i] = key[i] ^ 0x5C } var ipad1 = Buffer.allocUnsafe(blocksize + saltLen + 4) ipad.copy(ipad1, 0, 0, blocksize) this.ipad1 = ipad1 this.ipad2 = ipad this.opad = opad this.alg = alg this.blocksize = blocksize this.hash = hash this.size = sizes[alg] } Hmac.prototype.run = function (data, ipad) { data.copy(ipad, this.blocksize) var h = this.hash(ipad) h.copy(this.opad, this.blocksize) return this.hash(this.opad) } function getDigest (alg) { function shaFunc (data) { return sha(alg).update(data).digest() } function rmd160Func (data) { return new RIPEMD160().update(data).digest() } if (alg === 'rmd160' || alg === 'ripemd160') return rmd160Func if (alg === 'md5') return md5 return shaFunc } function pbkdf2 (password, salt, iterations, keylen, digest) { checkParameters(iterations, keylen) password = toBuffer(password, defaultEncoding, 'Password') salt = toBuffer(salt, defaultEncoding, 'Salt') digest = digest || 'sha1' var hmac = new Hmac(digest, password, salt.length) var DK = Buffer.allocUnsafe(keylen) var block1 = Buffer.allocUnsafe(salt.length + 4) salt.copy(block1, 0, 0, salt.length) var destPos = 0 var hLen = sizes[digest] var l = Math.ceil(keylen / hLen) for (var i = 1; i <= l; i++) { block1.writeUInt32BE(i, salt.length) var T = hmac.run(block1, hmac.ipad1) var U = T for (var j = 1; j < iterations; j++) { U = hmac.run(U, hmac.ipad2) for (var k = 0; k < hLen; k++) T[k] ^= U[k] } T.copy(DK, destPos) destPos += hLen } return DK } module.exports = pbkdf2 lib/default-encoding.js000066600000000602150544105370011066 0ustar00var defaultEncoding /* istanbul ignore next */ if (global.process && global.process.browser) { defaultEncoding = 'utf-8' } else if (global.process && global.process.version) { var pVersionMajor = parseInt(process.version.split('.')[0].slice(1), 10) defaultEncoding = pVersionMajor >= 6 ? 'utf-8' : 'binary' } else { defaultEncoding = 'utf-8' } module.exports = defaultEncoding lib/precondition.js000066600000000773150544105370010364 0ustar00var MAX_ALLOC = Math.pow(2, 30) - 1 // default in iojs module.exports = function (iterations, keylen) { if (typeof iterations !== 'number') { throw new TypeError('Iterations not a number') } if (iterations < 0) { throw new TypeError('Bad iterations') } if (typeof keylen !== 'number') { throw new TypeError('Key length not a number') } if (keylen < 0 || keylen > MAX_ALLOC || keylen !== keylen) { /* eslint no-self-compare: 0 */ throw new TypeError('Bad key length') } } LICENSE000066600000002071150544105370005561 0ustar00The MIT License (MIT) Copyright (c) 2014 Daniel Cousens Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. package.json000066600000003215150544105370007043 0ustar00{ "name": "pbkdf2", "version": "3.1.2", "description": "This library provides the functionality of PBKDF2 with the ability to use any supported hashing algorithm returned from crypto.getHashes()", "keywords": [ "pbkdf2", "kdf", "salt", "hash" ], "homepage": "https://github.com/crypto-browserify/pbkdf2", "bugs": { "url": "https://github.com/crypto-browserify/pbkdf2/issues" }, "license": "MIT", "author": "Daniel Cousens", "browser": { "./index.js": "./browser.js", "./lib/sync.js": "./lib/sync-browser.js" }, "files": [ "browser.js", "index.js", "lib/" ], "main": "index.js", "repository": { "type": "git", "url": "https://github.com/crypto-browserify/pbkdf2.git" }, "scripts": { "prepublish": "npm run test", "coverage-report": "nyc report --reporter=lcov", "coverage-html": "nyc report --reporter=html", "coverage": "nyc --check-coverage --branches 95 --functions 95 tape test/*.js", "lint": "standard", "test": "npm run lint && npm run unit", "bundle-test": "browserify test/index.js > test/bundle.js", "unit": "tape test/*.js", "bench": "node bench/" }, "devDependencies": { "benchmark": "^2.1.4", "browserify": "*", "nyc": "^6.4.0", "standard": "*", "tape": "^4.5.1" }, "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", "ripemd160": "^2.0.1", "safe-buffer": "^5.0.1", "sha.js": "^2.4.8" }, "standard": { "ignore": [ "test/bundle.js" ] }, "engines": { "node": ">=0.12" }, "nyc": { "exclude": [ "lib/async.js", "test/bundle.js" ] } }