module.exports = function(crypto) { function pbkdf2(password, salt, iterations, keylen, digest, callback) { if ('function' === typeof digest) { callback = digest digest = undefined } if ('function' !== typeof callback) throw new Error('No callback provided to pbkdf2') setTimeout(function() { var result try { result = pbkdf2Sync(password, salt, iterations, keylen, digest) } catch (e) { return callback(e) } callback(undefined, result) }) } function pbkdf2Sync(password, salt, iterations, keylen, digest) { if ('number' !== typeof iterations) throw new TypeError('Iterations not a number') if (iterations < 0) throw new TypeError('Bad iterations') if ('number' !== typeof keylen) throw new TypeError('Key length not a number') if (keylen < 0) throw new TypeError('Bad key length') digest = digest || 'sha1' if (!Buffer.isBuffer(password)) password = new Buffer(password) if (!Buffer.isBuffer(salt)) salt = new Buffer(salt) var hLen, l = 1, r, T var DK = new Buffer(keylen) var block1 = new Buffer(salt.length + 4) salt.copy(block1, 0, 0, salt.length) for (var i = 1; i <= l; i++) { block1.writeUInt32BE(i, salt.length) var U = crypto.createHmac(digest, password).update(block1).digest() if (!hLen) { hLen = U.length T = new Buffer(hLen) l = Math.ceil(keylen / hLen) r = keylen - (l - 1) * hLen if (keylen > (Math.pow(2, 32) - 1) * hLen) throw new TypeError('keylen exceeds maximum length') } U.copy(T, 0, 0, hLen) for (var j = 1; j < iterations; j++) { U = crypto.createHmac(digest, password).update(U).digest() for (var k = 0; k < hLen; k++) { T[k] ^= U[k] } } var destPos = (i - 1) * hLen var len = (i == l ? r : hLen) T.copy(DK, destPos, 0, len) } return DK } return { pbkdf2: pbkdf2, pbkdf2Sync: pbkdf2Sync } }