Projekt

Obecné

Profil

Stáhnout (2.26 KB) Statistiky
| Větev: | Revize:
1
'use strict'
2
var Buffer = require('safe-buffer').Buffer
3
var Transform = require('stream').Transform
4
var inherits = require('inherits')
5

    
6
function throwIfNotStringOrBuffer (val, prefix) {
7
  if (!Buffer.isBuffer(val) && typeof val !== 'string') {
8
    throw new TypeError(prefix + ' must be a string or a buffer')
9
  }
10
}
11

    
12
function HashBase (blockSize) {
13
  Transform.call(this)
14

    
15
  this._block = Buffer.allocUnsafe(blockSize)
16
  this._blockSize = blockSize
17
  this._blockOffset = 0
18
  this._length = [0, 0, 0, 0]
19

    
20
  this._finalized = false
21
}
22

    
23
inherits(HashBase, Transform)
24

    
25
HashBase.prototype._transform = function (chunk, encoding, callback) {
26
  var error = null
27
  try {
28
    this.update(chunk, encoding)
29
  } catch (err) {
30
    error = err
31
  }
32

    
33
  callback(error)
34
}
35

    
36
HashBase.prototype._flush = function (callback) {
37
  var error = null
38
  try {
39
    this.push(this.digest())
40
  } catch (err) {
41
    error = err
42
  }
43

    
44
  callback(error)
45
}
46

    
47
HashBase.prototype.update = function (data, encoding) {
48
  throwIfNotStringOrBuffer(data, 'Data')
49
  if (this._finalized) throw new Error('Digest already called')
50
  if (!Buffer.isBuffer(data)) data = Buffer.from(data, encoding)
51

    
52
  // consume data
53
  var block = this._block
54
  var offset = 0
55
  while (this._blockOffset + data.length - offset >= this._blockSize) {
56
    for (var i = this._blockOffset; i < this._blockSize;) block[i++] = data[offset++]
57
    this._update()
58
    this._blockOffset = 0
59
  }
60
  while (offset < data.length) block[this._blockOffset++] = data[offset++]
61

    
62
  // update length
63
  for (var j = 0, carry = data.length * 8; carry > 0; ++j) {
64
    this._length[j] += carry
65
    carry = (this._length[j] / 0x0100000000) | 0
66
    if (carry > 0) this._length[j] -= 0x0100000000 * carry
67
  }
68

    
69
  return this
70
}
71

    
72
HashBase.prototype._update = function () {
73
  throw new Error('_update is not implemented')
74
}
75

    
76
HashBase.prototype.digest = function (encoding) {
77
  if (this._finalized) throw new Error('Digest already called')
78
  this._finalized = true
79

    
80
  var digest = this._digest()
81
  if (encoding !== undefined) digest = digest.toString(encoding)
82

    
83
  // reset state
84
  this._block.fill(0)
85
  this._blockOffset = 0
86
  for (var i = 0; i < 4; ++i) this._length[i] = 0
87

    
88
  return digest
89
}
90

    
91
HashBase.prototype._digest = function () {
92
  throw new Error('_digest is not implemented')
93
}
94

    
95
module.exports = HashBase
(3-3/4)