| 'use strict'; |
| |
| var utils = require('./utils'); |
| var assert = require('minimalistic-assert'); |
| |
| function BlockHash() { |
| this.pending = null; |
| this.pendingTotal = 0; |
| this.blockSize = this.constructor.blockSize; |
| this.outSize = this.constructor.outSize; |
| this.hmacStrength = this.constructor.hmacStrength; |
| this.padLength = this.constructor.padLength / 8; |
| this.endian = 'big'; |
| |
| this._delta8 = this.blockSize / 8; |
| this._delta32 = this.blockSize / 32; |
| } |
| exports.BlockHash = BlockHash; |
| |
| BlockHash.prototype.update = function update(msg, enc) { |
| // Convert message to array, pad it, and join into 32bit blocks |
| msg = utils.toArray(msg, enc); |
| if (!this.pending) |
| this.pending = msg; |
| else |
| this.pending = this.pending.concat(msg); |
| this.pendingTotal += msg.length; |
| |
| // Enough data, try updating |
| if (this.pending.length >= this._delta8) { |
| msg = this.pending; |
| |
| // Process pending data in blocks |
| var r = msg.length % this._delta8; |
| this.pending = msg.slice(msg.length - r, msg.length); |
| if (this.pending.length === 0) |
| this.pending = null; |
| |
| msg = utils.join32(msg, 0, msg.length - r, this.endian); |
| for (var i = 0; i < msg.length; i += this._delta32) |
| this._update(msg, i, i + this._delta32); |
| } |
| |
| return this; |
| }; |
| |
| BlockHash.prototype.digest = function digest(enc) { |
| this.update(this._pad()); |
| assert(this.pending === null); |
| |
| return this._digest(enc); |
| }; |
| |
| BlockHash.prototype._pad = function pad() { |
| var len = this.pendingTotal; |
| var bytes = this._delta8; |
| var k = bytes - ((len + this.padLength) % bytes); |
| var res = new Array(k + this.padLength); |
| res[0] = 0x80; |
| for (var i = 1; i < k; i++) |
| res[i] = 0; |
| |
| // Append length |
| len <<= 3; |
| if (this.endian === 'big') { |
| for (var t = 8; t < this.padLength; t++) |
| res[i++] = 0; |
| |
| res[i++] = 0; |
| res[i++] = 0; |
| res[i++] = 0; |
| res[i++] = 0; |
| res[i++] = (len >>> 24) & 0xff; |
| res[i++] = (len >>> 16) & 0xff; |
| res[i++] = (len >>> 8) & 0xff; |
| res[i++] = len & 0xff; |
| } else { |
| res[i++] = len & 0xff; |
| res[i++] = (len >>> 8) & 0xff; |
| res[i++] = (len >>> 16) & 0xff; |
| res[i++] = (len >>> 24) & 0xff; |
| res[i++] = 0; |
| res[i++] = 0; |
| res[i++] = 0; |
| res[i++] = 0; |
| |
| for (t = 8; t < this.padLength; t++) |
| res[i++] = 0; |
| } |
| |
| return res; |
| }; |