Projekt

Obecné

Profil

Stáhnout (3.14 KB) Statistiky
| Větev: | Revize:
1
var AuthCipher = require('./authCipher')
2
var Buffer = require('safe-buffer').Buffer
3
var MODES = require('./modes')
4
var StreamCipher = require('./streamCipher')
5
var Transform = require('cipher-base')
6
var aes = require('./aes')
7
var ebtk = require('evp_bytestokey')
8
var inherits = require('inherits')
9

    
10
function Decipher (mode, key, iv) {
11
  Transform.call(this)
12

    
13
  this._cache = new Splitter()
14
  this._last = void 0
15
  this._cipher = new aes.AES(key)
16
  this._prev = Buffer.from(iv)
17
  this._mode = mode
18
  this._autopadding = true
19
}
20

    
21
inherits(Decipher, Transform)
22

    
23
Decipher.prototype._update = function (data) {
24
  this._cache.add(data)
25
  var chunk
26
  var thing
27
  var out = []
28
  while ((chunk = this._cache.get(this._autopadding))) {
29
    thing = this._mode.decrypt(this, chunk)
30
    out.push(thing)
31
  }
32
  return Buffer.concat(out)
33
}
34

    
35
Decipher.prototype._final = function () {
36
  var chunk = this._cache.flush()
37
  if (this._autopadding) {
38
    return unpad(this._mode.decrypt(this, chunk))
39
  } else if (chunk) {
40
    throw new Error('data not multiple of block length')
41
  }
42
}
43

    
44
Decipher.prototype.setAutoPadding = function (setTo) {
45
  this._autopadding = !!setTo
46
  return this
47
}
48

    
49
function Splitter () {
50
  this.cache = Buffer.allocUnsafe(0)
51
}
52

    
53
Splitter.prototype.add = function (data) {
54
  this.cache = Buffer.concat([this.cache, data])
55
}
56

    
57
Splitter.prototype.get = function (autoPadding) {
58
  var out
59
  if (autoPadding) {
60
    if (this.cache.length > 16) {
61
      out = this.cache.slice(0, 16)
62
      this.cache = this.cache.slice(16)
63
      return out
64
    }
65
  } else {
66
    if (this.cache.length >= 16) {
67
      out = this.cache.slice(0, 16)
68
      this.cache = this.cache.slice(16)
69
      return out
70
    }
71
  }
72

    
73
  return null
74
}
75

    
76
Splitter.prototype.flush = function () {
77
  if (this.cache.length) return this.cache
78
}
79

    
80
function unpad (last) {
81
  var padded = last[15]
82
  if (padded < 1 || padded > 16) {
83
    throw new Error('unable to decrypt data')
84
  }
85
  var i = -1
86
  while (++i < padded) {
87
    if (last[(i + (16 - padded))] !== padded) {
88
      throw new Error('unable to decrypt data')
89
    }
90
  }
91
  if (padded === 16) return
92

    
93
  return last.slice(0, 16 - padded)
94
}
95

    
96
function createDecipheriv (suite, password, iv) {
97
  var config = MODES[suite.toLowerCase()]
98
  if (!config) throw new TypeError('invalid suite type')
99

    
100
  if (typeof iv === 'string') iv = Buffer.from(iv)
101
  if (config.mode !== 'GCM' && iv.length !== config.iv) throw new TypeError('invalid iv length ' + iv.length)
102

    
103
  if (typeof password === 'string') password = Buffer.from(password)
104
  if (password.length !== config.key / 8) throw new TypeError('invalid key length ' + password.length)
105

    
106
  if (config.type === 'stream') {
107
    return new StreamCipher(config.module, password, iv, true)
108
  } else if (config.type === 'auth') {
109
    return new AuthCipher(config.module, password, iv, true)
110
  }
111

    
112
  return new Decipher(config.module, password, iv)
113
}
114

    
115
function createDecipher (suite, password) {
116
  var config = MODES[suite.toLowerCase()]
117
  if (!config) throw new TypeError('invalid suite type')
118

    
119
  var keys = ebtk(password, false, config.key, config.iv)
120
  return createDecipheriv(suite, keys.key, keys.iv)
121
}
122

    
123
exports.createDecipher = createDecipher
124
exports.createDecipheriv = createDecipheriv
(7-7/13)