123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- var Buffer = require('buffer/').Buffer;
- var hashUtils = require('./browserHashUtils');
- var BLOCK_SIZE = 64;
- var DIGEST_LENGTH = 32;
- var KEY = new Uint32Array([
- 0x428a2f98,
- 0x71374491,
- 0xb5c0fbcf,
- 0xe9b5dba5,
- 0x3956c25b,
- 0x59f111f1,
- 0x923f82a4,
- 0xab1c5ed5,
- 0xd807aa98,
- 0x12835b01,
- 0x243185be,
- 0x550c7dc3,
- 0x72be5d74,
- 0x80deb1fe,
- 0x9bdc06a7,
- 0xc19bf174,
- 0xe49b69c1,
- 0xefbe4786,
- 0x0fc19dc6,
- 0x240ca1cc,
- 0x2de92c6f,
- 0x4a7484aa,
- 0x5cb0a9dc,
- 0x76f988da,
- 0x983e5152,
- 0xa831c66d,
- 0xb00327c8,
- 0xbf597fc7,
- 0xc6e00bf3,
- 0xd5a79147,
- 0x06ca6351,
- 0x14292967,
- 0x27b70a85,
- 0x2e1b2138,
- 0x4d2c6dfc,
- 0x53380d13,
- 0x650a7354,
- 0x766a0abb,
- 0x81c2c92e,
- 0x92722c85,
- 0xa2bfe8a1,
- 0xa81a664b,
- 0xc24b8b70,
- 0xc76c51a3,
- 0xd192e819,
- 0xd6990624,
- 0xf40e3585,
- 0x106aa070,
- 0x19a4c116,
- 0x1e376c08,
- 0x2748774c,
- 0x34b0bcb5,
- 0x391c0cb3,
- 0x4ed8aa4a,
- 0x5b9cca4f,
- 0x682e6ff3,
- 0x748f82ee,
- 0x78a5636f,
- 0x84c87814,
- 0x8cc70208,
- 0x90befffa,
- 0xa4506ceb,
- 0xbef9a3f7,
- 0xc67178f2
- ]);
- var INIT = [
- 0x6a09e667,
- 0xbb67ae85,
- 0x3c6ef372,
- 0xa54ff53a,
- 0x510e527f,
- 0x9b05688c,
- 0x1f83d9ab,
- 0x5be0cd19,
- ];
- var MAX_HASHABLE_LENGTH = Math.pow(2, 53) - 1;
- /**
- * @private
- */
- function Sha256() {
- this.state = [
- 0x6a09e667,
- 0xbb67ae85,
- 0x3c6ef372,
- 0xa54ff53a,
- 0x510e527f,
- 0x9b05688c,
- 0x1f83d9ab,
- 0x5be0cd19,
- ];
- this.temp = new Int32Array(64);
- this.buffer = new Uint8Array(64);
- this.bufferLength = 0;
- this.bytesHashed = 0;
- /**
- * @private
- */
- this.finished = false;
- }
- /**
- * @api private
- */
- module.exports = exports = Sha256;
- Sha256.BLOCK_SIZE = BLOCK_SIZE;
- Sha256.prototype.update = function (data) {
- if (this.finished) {
- throw new Error('Attempted to update an already finished hash.');
- }
- if (hashUtils.isEmptyData(data)) {
- return this;
- }
- data = hashUtils.convertToBuffer(data);
- var position = 0;
- var byteLength = data.byteLength;
- this.bytesHashed += byteLength;
- if (this.bytesHashed * 8 > MAX_HASHABLE_LENGTH) {
- throw new Error('Cannot hash more than 2^53 - 1 bits');
- }
- while (byteLength > 0) {
- this.buffer[this.bufferLength++] = data[position++];
- byteLength--;
- if (this.bufferLength === BLOCK_SIZE) {
- this.hashBuffer();
- this.bufferLength = 0;
- }
- }
- return this;
- };
- Sha256.prototype.digest = function (encoding) {
- if (!this.finished) {
- var bitsHashed = this.bytesHashed * 8;
- var bufferView = new DataView(this.buffer.buffer, this.buffer.byteOffset, this.buffer.byteLength);
- var undecoratedLength = this.bufferLength;
- bufferView.setUint8(this.bufferLength++, 0x80);
- // Ensure the final block has enough room for the hashed length
- if (undecoratedLength % BLOCK_SIZE >= BLOCK_SIZE - 8) {
- for (var i = this.bufferLength; i < BLOCK_SIZE; i++) {
- bufferView.setUint8(i, 0);
- }
- this.hashBuffer();
- this.bufferLength = 0;
- }
- for (var i = this.bufferLength; i < BLOCK_SIZE - 8; i++) {
- bufferView.setUint8(i, 0);
- }
- bufferView.setUint32(BLOCK_SIZE - 8, Math.floor(bitsHashed / 0x100000000), true);
- bufferView.setUint32(BLOCK_SIZE - 4, bitsHashed);
- this.hashBuffer();
- this.finished = true;
- }
- // The value in state is little-endian rather than big-endian, so flip
- // each word into a new Uint8Array
- var out = new Buffer(DIGEST_LENGTH);
- for (var i = 0; i < 8; i++) {
- out[i * 4] = (this.state[i] >>> 24) & 0xff;
- out[i * 4 + 1] = (this.state[i] >>> 16) & 0xff;
- out[i * 4 + 2] = (this.state[i] >>> 8) & 0xff;
- out[i * 4 + 3] = (this.state[i] >>> 0) & 0xff;
- }
- return encoding ? out.toString(encoding) : out;
- };
- Sha256.prototype.hashBuffer = function () {
- var _a = this,
- buffer = _a.buffer,
- state = _a.state;
- var state0 = state[0],
- state1 = state[1],
- state2 = state[2],
- state3 = state[3],
- state4 = state[4],
- state5 = state[5],
- state6 = state[6],
- state7 = state[7];
- for (var i = 0; i < BLOCK_SIZE; i++) {
- if (i < 16) {
- this.temp[i] = (((buffer[i * 4] & 0xff) << 24) |
- ((buffer[(i * 4) + 1] & 0xff) << 16) |
- ((buffer[(i * 4) + 2] & 0xff) << 8) |
- (buffer[(i * 4) + 3] & 0xff));
- }
- else {
- var u = this.temp[i - 2];
- var t1_1 = (u >>> 17 | u << 15) ^
- (u >>> 19 | u << 13) ^
- (u >>> 10);
- u = this.temp[i - 15];
- var t2_1 = (u >>> 7 | u << 25) ^
- (u >>> 18 | u << 14) ^
- (u >>> 3);
- this.temp[i] = (t1_1 + this.temp[i - 7] | 0) +
- (t2_1 + this.temp[i - 16] | 0);
- }
- var t1 = (((((state4 >>> 6 | state4 << 26) ^
- (state4 >>> 11 | state4 << 21) ^
- (state4 >>> 25 | state4 << 7))
- + ((state4 & state5) ^ (~state4 & state6))) | 0)
- + ((state7 + ((KEY[i] + this.temp[i]) | 0)) | 0)) | 0;
- var t2 = (((state0 >>> 2 | state0 << 30) ^
- (state0 >>> 13 | state0 << 19) ^
- (state0 >>> 22 | state0 << 10)) + ((state0 & state1) ^ (state0 & state2) ^ (state1 & state2))) | 0;
- state7 = state6;
- state6 = state5;
- state5 = state4;
- state4 = (state3 + t1) | 0;
- state3 = state2;
- state2 = state1;
- state1 = state0;
- state0 = (t1 + t2) | 0;
- }
- state[0] += state0;
- state[1] += state1;
- state[2] += state2;
- state[3] += state3;
- state[4] += state4;
- state[5] += state5;
- state[6] += state6;
- state[7] += state7;
- };
|