common.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. 'use strict';
  2. var utils = require('./utils');
  3. var assert = require('minimalistic-assert');
  4. function BlockHash() {
  5. this.pending = null;
  6. this.pendingTotal = 0;
  7. this.blockSize = this.constructor.blockSize;
  8. this.outSize = this.constructor.outSize;
  9. this.hmacStrength = this.constructor.hmacStrength;
  10. this.padLength = this.constructor.padLength / 8;
  11. this.endian = 'big';
  12. this._delta8 = this.blockSize / 8;
  13. this._delta32 = this.blockSize / 32;
  14. }
  15. exports.BlockHash = BlockHash;
  16. BlockHash.prototype.update = function update(msg, enc) {
  17. // Convert message to array, pad it, and join into 32bit blocks
  18. msg = utils.toArray(msg, enc);
  19. if (!this.pending)
  20. this.pending = msg;
  21. else
  22. this.pending = this.pending.concat(msg);
  23. this.pendingTotal += msg.length;
  24. // Enough data, try updating
  25. if (this.pending.length >= this._delta8) {
  26. msg = this.pending;
  27. // Process pending data in blocks
  28. var r = msg.length % this._delta8;
  29. this.pending = msg.slice(msg.length - r, msg.length);
  30. if (this.pending.length === 0)
  31. this.pending = null;
  32. msg = utils.join32(msg, 0, msg.length - r, this.endian);
  33. for (var i = 0; i < msg.length; i += this._delta32)
  34. this._update(msg, i, i + this._delta32);
  35. }
  36. return this;
  37. };
  38. BlockHash.prototype.digest = function digest(enc) {
  39. this.update(this._pad());
  40. assert(this.pending === null);
  41. return this._digest(enc);
  42. };
  43. BlockHash.prototype._pad = function pad() {
  44. var len = this.pendingTotal;
  45. var bytes = this._delta8;
  46. var k = bytes - ((len + this.padLength) % bytes);
  47. var res = new Array(k + this.padLength);
  48. res[0] = 0x80;
  49. for (var i = 1; i < k; i++)
  50. res[i] = 0;
  51. // Append length
  52. len <<= 3;
  53. if (this.endian === 'big') {
  54. for (var t = 8; t < this.padLength; t++)
  55. res[i++] = 0;
  56. res[i++] = 0;
  57. res[i++] = 0;
  58. res[i++] = 0;
  59. res[i++] = 0;
  60. res[i++] = (len >>> 24) & 0xff;
  61. res[i++] = (len >>> 16) & 0xff;
  62. res[i++] = (len >>> 8) & 0xff;
  63. res[i++] = len & 0xff;
  64. } else {
  65. res[i++] = len & 0xff;
  66. res[i++] = (len >>> 8) & 0xff;
  67. res[i++] = (len >>> 16) & 0xff;
  68. res[i++] = (len >>> 24) & 0xff;
  69. res[i++] = 0;
  70. res[i++] = 0;
  71. res[i++] = 0;
  72. res[i++] = 0;
  73. for (t = 8; t < this.padLength; t++)
  74. res[i++] = 0;
  75. }
  76. return res;
  77. };