_md.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.SHA512_IV = exports.SHA384_IV = exports.SHA224_IV = exports.SHA256_IV = exports.HashMD = void 0;
  4. exports.setBigUint64 = setBigUint64;
  5. exports.Chi = Chi;
  6. exports.Maj = Maj;
  7. /**
  8. * Internal Merkle-Damgard hash utils.
  9. * @module
  10. */
  11. const utils_ts_1 = require("./utils.js");
  12. /** Polyfill for Safari 14. https://caniuse.com/mdn-javascript_builtins_dataview_setbiguint64 */
  13. function setBigUint64(view, byteOffset, value, isLE) {
  14. if (typeof view.setBigUint64 === 'function')
  15. return view.setBigUint64(byteOffset, value, isLE);
  16. const _32n = BigInt(32);
  17. const _u32_max = BigInt(0xffffffff);
  18. const wh = Number((value >> _32n) & _u32_max);
  19. const wl = Number(value & _u32_max);
  20. const h = isLE ? 4 : 0;
  21. const l = isLE ? 0 : 4;
  22. view.setUint32(byteOffset + h, wh, isLE);
  23. view.setUint32(byteOffset + l, wl, isLE);
  24. }
  25. /** Choice: a ? b : c */
  26. function Chi(a, b, c) {
  27. return (a & b) ^ (~a & c);
  28. }
  29. /** Majority function, true if any two inputs is true. */
  30. function Maj(a, b, c) {
  31. return (a & b) ^ (a & c) ^ (b & c);
  32. }
  33. /**
  34. * Merkle-Damgard hash construction base class.
  35. * Could be used to create MD5, RIPEMD, SHA1, SHA2.
  36. */
  37. class HashMD extends utils_ts_1.Hash {
  38. constructor(blockLen, outputLen, padOffset, isLE) {
  39. super();
  40. this.finished = false;
  41. this.length = 0;
  42. this.pos = 0;
  43. this.destroyed = false;
  44. this.blockLen = blockLen;
  45. this.outputLen = outputLen;
  46. this.padOffset = padOffset;
  47. this.isLE = isLE;
  48. this.buffer = new Uint8Array(blockLen);
  49. this.view = (0, utils_ts_1.createView)(this.buffer);
  50. }
  51. update(data) {
  52. (0, utils_ts_1.aexists)(this);
  53. data = (0, utils_ts_1.toBytes)(data);
  54. (0, utils_ts_1.abytes)(data);
  55. const { view, buffer, blockLen } = this;
  56. const len = data.length;
  57. for (let pos = 0; pos < len;) {
  58. const take = Math.min(blockLen - this.pos, len - pos);
  59. // Fast path: we have at least one block in input, cast it to view and process
  60. if (take === blockLen) {
  61. const dataView = (0, utils_ts_1.createView)(data);
  62. for (; blockLen <= len - pos; pos += blockLen)
  63. this.process(dataView, pos);
  64. continue;
  65. }
  66. buffer.set(data.subarray(pos, pos + take), this.pos);
  67. this.pos += take;
  68. pos += take;
  69. if (this.pos === blockLen) {
  70. this.process(view, 0);
  71. this.pos = 0;
  72. }
  73. }
  74. this.length += data.length;
  75. this.roundClean();
  76. return this;
  77. }
  78. digestInto(out) {
  79. (0, utils_ts_1.aexists)(this);
  80. (0, utils_ts_1.aoutput)(out, this);
  81. this.finished = true;
  82. // Padding
  83. // We can avoid allocation of buffer for padding completely if it
  84. // was previously not allocated here. But it won't change performance.
  85. const { buffer, view, blockLen, isLE } = this;
  86. let { pos } = this;
  87. // append the bit '1' to the message
  88. buffer[pos++] = 0b10000000;
  89. (0, utils_ts_1.clean)(this.buffer.subarray(pos));
  90. // we have less than padOffset left in buffer, so we cannot put length in
  91. // current block, need process it and pad again
  92. if (this.padOffset > blockLen - pos) {
  93. this.process(view, 0);
  94. pos = 0;
  95. }
  96. // Pad until full block byte with zeros
  97. for (let i = pos; i < blockLen; i++)
  98. buffer[i] = 0;
  99. // Note: sha512 requires length to be 128bit integer, but length in JS will overflow before that
  100. // You need to write around 2 exabytes (u64_max / 8 / (1024**6)) for this to happen.
  101. // So we just write lowest 64 bits of that value.
  102. setBigUint64(view, blockLen - 8, BigInt(this.length * 8), isLE);
  103. this.process(view, 0);
  104. const oview = (0, utils_ts_1.createView)(out);
  105. const len = this.outputLen;
  106. // NOTE: we do division by 4 later, which should be fused in single op with modulo by JIT
  107. if (len % 4)
  108. throw new Error('_sha2: outputLen should be aligned to 32bit');
  109. const outLen = len / 4;
  110. const state = this.get();
  111. if (outLen > state.length)
  112. throw new Error('_sha2: outputLen bigger than state');
  113. for (let i = 0; i < outLen; i++)
  114. oview.setUint32(4 * i, state[i], isLE);
  115. }
  116. digest() {
  117. const { buffer, outputLen } = this;
  118. this.digestInto(buffer);
  119. const res = buffer.slice(0, outputLen);
  120. this.destroy();
  121. return res;
  122. }
  123. _cloneInto(to) {
  124. to || (to = new this.constructor());
  125. to.set(...this.get());
  126. const { blockLen, buffer, length, finished, destroyed, pos } = this;
  127. to.destroyed = destroyed;
  128. to.finished = finished;
  129. to.length = length;
  130. to.pos = pos;
  131. if (length % blockLen)
  132. to.buffer.set(buffer);
  133. return to;
  134. }
  135. clone() {
  136. return this._cloneInto();
  137. }
  138. }
  139. exports.HashMD = HashMD;
  140. /**
  141. * Initial SHA-2 state: fractional parts of square roots of first 16 primes 2..53.
  142. * Check out `test/misc/sha2-gen-iv.js` for recomputation guide.
  143. */
  144. /** Initial SHA256 state. Bits 0..32 of frac part of sqrt of primes 2..19 */
  145. exports.SHA256_IV = Uint32Array.from([
  146. 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
  147. ]);
  148. /** Initial SHA224 state. Bits 32..64 of frac part of sqrt of primes 23..53 */
  149. exports.SHA224_IV = Uint32Array.from([
  150. 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
  151. ]);
  152. /** Initial SHA384 state. Bits 0..64 of frac part of sqrt of primes 23..53 */
  153. exports.SHA384_IV = Uint32Array.from([
  154. 0xcbbb9d5d, 0xc1059ed8, 0x629a292a, 0x367cd507, 0x9159015a, 0x3070dd17, 0x152fecd8, 0xf70e5939,
  155. 0x67332667, 0xffc00b31, 0x8eb44a87, 0x68581511, 0xdb0c2e0d, 0x64f98fa7, 0x47b5481d, 0xbefa4fa4,
  156. ]);
  157. /** Initial SHA512 state. Bits 0..64 of frac part of sqrt of primes 2..19 */
  158. exports.SHA512_IV = Uint32Array.from([
  159. 0x6a09e667, 0xf3bcc908, 0xbb67ae85, 0x84caa73b, 0x3c6ef372, 0xfe94f82b, 0xa54ff53a, 0x5f1d36f1,
  160. 0x510e527f, 0xade682d1, 0x9b05688c, 0x2b3e6c1f, 0x1f83d9ab, 0xfb41bd6b, 0x5be0cd19, 0x137e2179,
  161. ]);
  162. //# sourceMappingURL=_md.js.map