fei.wang
9 天以前 ae7b22322555448d95fd56f505bafa325c167a26
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
'use strict'
var Buffer = require('safe-buffer').Buffer
var Transform = require('stream').Transform
var inherits = require('inherits')
 
function HashBase (blockSize) {
  Transform.call(this)
 
  this._block = Buffer.allocUnsafe(blockSize)
  this._blockSize = blockSize
  this._blockOffset = 0
  this._length = [0, 0, 0, 0]
 
  this._finalized = false
}
 
inherits(HashBase, Transform)
 
HashBase.prototype._transform = function (chunk, encoding, callback) {
  var error = null
  try {
    this.update(chunk, encoding)
  } catch (err) {
    error = err
  }
 
  callback(error)
}
 
HashBase.prototype._flush = function (callback) {
  var error = null
  try {
    this.push(this.digest())
  } catch (err) {
    error = err
  }
 
  callback(error)
}
 
var useUint8Array = typeof Uint8Array !== 'undefined'
var useArrayBuffer = typeof ArrayBuffer !== 'undefined' &&
  typeof Uint8Array !== 'undefined' &&
  ArrayBuffer.isView &&
  (Buffer.prototype instanceof Uint8Array || Buffer.TYPED_ARRAY_SUPPORT)
 
function toBuffer (data, encoding) {
  // No need to do anything for exact instance
  // This is only valid when safe-buffer.Buffer === buffer.Buffer, i.e. when Buffer.from/Buffer.alloc existed
  if (data instanceof Buffer) return data
 
  // Convert strings to Buffer
  if (typeof data === 'string') return Buffer.from(data, encoding)
 
  /*
   * Wrap any TypedArray instances and DataViews
   * Makes sense only on engines with full TypedArray support -- let Buffer detect that
   */
  if (useArrayBuffer && ArrayBuffer.isView(data)) {
    if (data.byteLength === 0) return Buffer.alloc(0) // Bug in Node.js <6.3.1, which treats this as out-of-bounds
    var res = Buffer.from(data.buffer, data.byteOffset, data.byteLength)
    // Recheck result size, as offset/length doesn't work on Node.js <5.10
    // We just go to Uint8Array case if this fails
    if (res.byteLength === data.byteLength) return res
  }
 
  /*
   * Uint8Array in engines where Buffer.from might not work with ArrayBuffer, just copy over
   * Doesn't make sense with other TypedArray instances
   */
  if (useUint8Array && data instanceof Uint8Array) return Buffer.from(data)
 
  /*
   * Old Buffer polyfill on an engine that doesn't have TypedArray support
   * Also, this is from a different Buffer polyfill implementation then we have, as instanceof check failed
   * Convert to our current Buffer implementation
   */
  if (
    Buffer.isBuffer(data) &&
    data.constructor &&
    typeof data.constructor.isBuffer === 'function' &&
    data.constructor.isBuffer(data)
  ) {
    return Buffer.from(data)
  }
 
  throw new TypeError('The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView.')
}
 
HashBase.prototype.update = function (data, encoding) {
  if (this._finalized) throw new Error('Digest already called')
 
  data = toBuffer(data, encoding) // asserts correct input type
 
  // consume data
  var block = this._block
  var offset = 0
  while (this._blockOffset + data.length - offset >= this._blockSize) {
    for (var i = this._blockOffset; i < this._blockSize;) block[i++] = data[offset++]
    this._update()
    this._blockOffset = 0
  }
  while (offset < data.length) block[this._blockOffset++] = data[offset++]
 
  // update length
  for (var j = 0, carry = data.length * 8; carry > 0; ++j) {
    this._length[j] += carry
    carry = (this._length[j] / 0x0100000000) | 0
    if (carry > 0) this._length[j] -= 0x0100000000 * carry
  }
 
  return this
}
 
HashBase.prototype._update = function () {
  throw new Error('_update is not implemented')
}
 
HashBase.prototype.digest = function (encoding) {
  if (this._finalized) throw new Error('Digest already called')
  this._finalized = true
 
  var digest = this._digest()
  if (encoding !== undefined) digest = digest.toString(encoding)
 
  // reset state
  this._block.fill(0)
  this._blockOffset = 0
  for (var i = 0; i < 4; ++i) this._length[i] = 0
 
  return digest
}
 
HashBase.prototype._digest = function () {
  throw new Error('_digest is not implemented')
}
 
module.exports = HashBase