8889841cindex.js000066600000002406150432031340006212 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.md000066600000003117150432031340006024 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.js000066600000000123150432031340006560 0ustar00exports.pbkdf2 = require('./lib/async') exports.pbkdf2Sync = require('./lib/sync') lib/to-buffer.js000066600000000636150432031340007545 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.js000066600000002261150432031340006624 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.js000066600000005712150432031340006771 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.js000066600000004722150432031340010311 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.js000066600000000602150432031340011055 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.js000066600000000773150432031340010353 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') } } LICENSE000066600000002071150432031340005550 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.json000066600000003215150432031340007032 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" ] } }