Projekt

Obecné

Profil

Stáhnout (2.61 KB) Statistiky
| Větev: | Revize:
1
var checkParameters = require('./precondition')
2
var defaultEncoding = require('./default-encoding')
3
var sync = require('./sync')
4
var Buffer = require('safe-buffer').Buffer
5

    
6
var ZERO_BUF
7
var subtle = global.crypto && global.crypto.subtle
8
var toBrowser = {
9
  'sha': 'SHA-1',
10
  'sha-1': 'SHA-1',
11
  'sha1': 'SHA-1',
12
  'sha256': 'SHA-256',
13
  'sha-256': 'SHA-256',
14
  'sha384': 'SHA-384',
15
  'sha-384': 'SHA-384',
16
  'sha-512': 'SHA-512',
17
  'sha512': 'SHA-512'
18
}
19
var checks = []
20
function checkNative (algo) {
21
  if (global.process && !global.process.browser) {
22
    return Promise.resolve(false)
23
  }
24
  if (!subtle || !subtle.importKey || !subtle.deriveBits) {
25
    return Promise.resolve(false)
26
  }
27
  if (checks[algo] !== undefined) {
28
    return checks[algo]
29
  }
30
  ZERO_BUF = ZERO_BUF || Buffer.alloc(8)
31
  var prom = browserPbkdf2(ZERO_BUF, ZERO_BUF, 10, 128, algo)
32
    .then(function () {
33
      return true
34
    }).catch(function () {
35
      return false
36
    })
37
  checks[algo] = prom
38
  return prom
39
}
40

    
41
function browserPbkdf2 (password, salt, iterations, length, algo) {
42
  return subtle.importKey(
43
    'raw', password, {name: 'PBKDF2'}, false, ['deriveBits']
44
  ).then(function (key) {
45
    return subtle.deriveBits({
46
      name: 'PBKDF2',
47
      salt: salt,
48
      iterations: iterations,
49
      hash: {
50
        name: algo
51
      }
52
    }, key, length << 3)
53
  }).then(function (res) {
54
    return Buffer.from(res)
55
  })
56
}
57

    
58
function resolvePromise (promise, callback) {
59
  promise.then(function (out) {
60
    process.nextTick(function () {
61
      callback(null, out)
62
    })
63
  }, function (e) {
64
    process.nextTick(function () {
65
      callback(e)
66
    })
67
  })
68
}
69
module.exports = function (password, salt, iterations, keylen, digest, callback) {
70
  if (typeof digest === 'function') {
71
    callback = digest
72
    digest = undefined
73
  }
74

    
75
  digest = digest || 'sha1'
76
  var algo = toBrowser[digest.toLowerCase()]
77

    
78
  if (!algo || typeof global.Promise !== 'function') {
79
    return process.nextTick(function () {
80
      var out
81
      try {
82
        out = sync(password, salt, iterations, keylen, digest)
83
      } catch (e) {
84
        return callback(e)
85
      }
86
      callback(null, out)
87
    })
88
  }
89

    
90
  checkParameters(password, salt, iterations, keylen)
91
  if (typeof callback !== 'function') throw new Error('No callback provided to pbkdf2')
92
  if (!Buffer.isBuffer(password)) password = Buffer.from(password, defaultEncoding)
93
  if (!Buffer.isBuffer(salt)) salt = Buffer.from(salt, defaultEncoding)
94

    
95
  resolvePromise(checkNative(algo).then(function (resp) {
96
    if (resp) return browserPbkdf2(password, salt, iterations, keylen, algo)
97

    
98
    return sync(password, salt, iterations, keylen, digest)
99
  }), callback)
100
}
(1-1/5)