1 | var createHmac = require('create-hmac')
|
2 | var checkParameters = require('./precondition')
|
3 | var pVersionMajor = parseInt(process.version.split('.')[0].slice(1), 10)
|
4 |
|
5 | exports.pbkdf2 = function (password, salt, iterations, keylen, digest, callback) {
|
6 | if (typeof digest === 'function') {
|
7 | callback = digest
|
8 | digest = undefined
|
9 | }
|
10 |
|
11 | checkParameters(iterations, keylen)
|
12 | if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2')
|
13 |
|
14 | setTimeout(function () {
|
15 | callback(null, exports.pbkdf2Sync(password, salt, iterations, keylen, digest))
|
16 | })
|
17 | }
|
18 |
|
19 | var defaultEncoding = (process.browser || pVersionMajor >= 6) ? 'utf-8' : 'binary'
|
20 |
|
21 | exports.pbkdf2Sync = function (password, salt, iterations, keylen, digest) {
|
22 | if (!Buffer.isBuffer(password)) password = new Buffer(password, defaultEncoding)
|
23 | if (!Buffer.isBuffer(salt)) salt = new Buffer(salt, defaultEncoding)
|
24 |
|
25 | checkParameters(iterations, keylen)
|
26 |
|
27 | digest = digest || 'sha1'
|
28 |
|
29 | var hLen
|
30 | var l = 1
|
31 | var DK = new Buffer(keylen)
|
32 | var block1 = new Buffer(salt.length + 4)
|
33 | salt.copy(block1, 0, 0, salt.length)
|
34 |
|
35 | var r
|
36 | var T
|
37 |
|
38 | for (var i = 1; i <= l; i++) {
|
39 | block1.writeUInt32BE(i, salt.length)
|
40 | var U = createHmac(digest, password).update(block1).digest()
|
41 |
|
42 | if (!hLen) {
|
43 | hLen = U.length
|
44 | T = new Buffer(hLen)
|
45 | l = Math.ceil(keylen / hLen)
|
46 | r = keylen - (l - 1) * hLen
|
47 | }
|
48 |
|
49 | U.copy(T, 0, 0, hLen)
|
50 |
|
51 | for (var j = 1; j < iterations; j++) {
|
52 | U = createHmac(digest, password).update(U).digest()
|
53 | for (var k = 0; k < hLen; k++) T[k] ^= U[k]
|
54 | }
|
55 |
|
56 | var destPos = (i - 1) * hLen
|
57 | var len = (i === l ? r : hLen)
|
58 | T.copy(DK, destPos, 0, len)
|
59 | }
|
60 |
|
61 | return DK
|
62 | }
|