sha3.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.shake256 = exports.shake128 = exports.keccak_512 = exports.keccak_384 = exports.keccak_256 = exports.keccak_224 = exports.sha3_512 = exports.sha3_384 = exports.sha3_256 = exports.sha3_224 = exports.Keccak = void 0;
  4. exports.keccakP = keccakP;
  5. /**
  6. * SHA3 (keccak) hash function, based on a new "Sponge function" design.
  7. * Different from older hashes, the internal state is bigger than output size.
  8. *
  9. * Check out [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf),
  10. * [Website](https://keccak.team/keccak.html),
  11. * [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub).
  12. *
  13. * Check out `sha3-addons` module for cSHAKE, k12, and others.
  14. * @module
  15. */
  16. const _u64_ts_1 = require("./_u64.js");
  17. // prettier-ignore
  18. const utils_ts_1 = require("./utils.js");
  19. // No __PURE__ annotations in sha3 header:
  20. // EVERYTHING is in fact used on every export.
  21. // Various per round constants calculations
  22. const _0n = BigInt(0);
  23. const _1n = BigInt(1);
  24. const _2n = BigInt(2);
  25. const _7n = BigInt(7);
  26. const _256n = BigInt(256);
  27. const _0x71n = BigInt(0x71);
  28. const SHA3_PI = [];
  29. const SHA3_ROTL = [];
  30. const _SHA3_IOTA = [];
  31. for (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {
  32. // Pi
  33. [x, y] = [y, (2 * x + 3 * y) % 5];
  34. SHA3_PI.push(2 * (5 * y + x));
  35. // Rotational
  36. SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64);
  37. // Iota
  38. let t = _0n;
  39. for (let j = 0; j < 7; j++) {
  40. R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n;
  41. if (R & _2n)
  42. t ^= _1n << ((_1n << /* @__PURE__ */ BigInt(j)) - _1n);
  43. }
  44. _SHA3_IOTA.push(t);
  45. }
  46. const IOTAS = (0, _u64_ts_1.split)(_SHA3_IOTA, true);
  47. const SHA3_IOTA_H = IOTAS[0];
  48. const SHA3_IOTA_L = IOTAS[1];
  49. // Left rotation (without 0, 32, 64)
  50. const rotlH = (h, l, s) => (s > 32 ? (0, _u64_ts_1.rotlBH)(h, l, s) : (0, _u64_ts_1.rotlSH)(h, l, s));
  51. const rotlL = (h, l, s) => (s > 32 ? (0, _u64_ts_1.rotlBL)(h, l, s) : (0, _u64_ts_1.rotlSL)(h, l, s));
  52. /** `keccakf1600` internal function, additionally allows to adjust round count. */
  53. function keccakP(s, rounds = 24) {
  54. const B = new Uint32Array(5 * 2);
  55. // NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js)
  56. for (let round = 24 - rounds; round < 24; round++) {
  57. // Theta θ
  58. for (let x = 0; x < 10; x++)
  59. B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];
  60. for (let x = 0; x < 10; x += 2) {
  61. const idx1 = (x + 8) % 10;
  62. const idx0 = (x + 2) % 10;
  63. const B0 = B[idx0];
  64. const B1 = B[idx0 + 1];
  65. const Th = rotlH(B0, B1, 1) ^ B[idx1];
  66. const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];
  67. for (let y = 0; y < 50; y += 10) {
  68. s[x + y] ^= Th;
  69. s[x + y + 1] ^= Tl;
  70. }
  71. }
  72. // Rho (ρ) and Pi (π)
  73. let curH = s[2];
  74. let curL = s[3];
  75. for (let t = 0; t < 24; t++) {
  76. const shift = SHA3_ROTL[t];
  77. const Th = rotlH(curH, curL, shift);
  78. const Tl = rotlL(curH, curL, shift);
  79. const PI = SHA3_PI[t];
  80. curH = s[PI];
  81. curL = s[PI + 1];
  82. s[PI] = Th;
  83. s[PI + 1] = Tl;
  84. }
  85. // Chi (χ)
  86. for (let y = 0; y < 50; y += 10) {
  87. for (let x = 0; x < 10; x++)
  88. B[x] = s[y + x];
  89. for (let x = 0; x < 10; x++)
  90. s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];
  91. }
  92. // Iota (ι)
  93. s[0] ^= SHA3_IOTA_H[round];
  94. s[1] ^= SHA3_IOTA_L[round];
  95. }
  96. (0, utils_ts_1.clean)(B);
  97. }
  98. /** Keccak sponge function. */
  99. class Keccak extends utils_ts_1.Hash {
  100. // NOTE: we accept arguments in bytes instead of bits here.
  101. constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {
  102. super();
  103. this.pos = 0;
  104. this.posOut = 0;
  105. this.finished = false;
  106. this.destroyed = false;
  107. this.enableXOF = false;
  108. this.blockLen = blockLen;
  109. this.suffix = suffix;
  110. this.outputLen = outputLen;
  111. this.enableXOF = enableXOF;
  112. this.rounds = rounds;
  113. // Can be passed from user as dkLen
  114. (0, utils_ts_1.anumber)(outputLen);
  115. // 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes
  116. // 0 < blockLen < 200
  117. if (!(0 < blockLen && blockLen < 200))
  118. throw new Error('only keccak-f1600 function is supported');
  119. this.state = new Uint8Array(200);
  120. this.state32 = (0, utils_ts_1.u32)(this.state);
  121. }
  122. clone() {
  123. return this._cloneInto();
  124. }
  125. keccak() {
  126. (0, utils_ts_1.swap32IfBE)(this.state32);
  127. keccakP(this.state32, this.rounds);
  128. (0, utils_ts_1.swap32IfBE)(this.state32);
  129. this.posOut = 0;
  130. this.pos = 0;
  131. }
  132. update(data) {
  133. (0, utils_ts_1.aexists)(this);
  134. data = (0, utils_ts_1.toBytes)(data);
  135. (0, utils_ts_1.abytes)(data);
  136. const { blockLen, state } = this;
  137. const len = data.length;
  138. for (let pos = 0; pos < len;) {
  139. const take = Math.min(blockLen - this.pos, len - pos);
  140. for (let i = 0; i < take; i++)
  141. state[this.pos++] ^= data[pos++];
  142. if (this.pos === blockLen)
  143. this.keccak();
  144. }
  145. return this;
  146. }
  147. finish() {
  148. if (this.finished)
  149. return;
  150. this.finished = true;
  151. const { state, suffix, pos, blockLen } = this;
  152. // Do the padding
  153. state[pos] ^= suffix;
  154. if ((suffix & 0x80) !== 0 && pos === blockLen - 1)
  155. this.keccak();
  156. state[blockLen - 1] ^= 0x80;
  157. this.keccak();
  158. }
  159. writeInto(out) {
  160. (0, utils_ts_1.aexists)(this, false);
  161. (0, utils_ts_1.abytes)(out);
  162. this.finish();
  163. const bufferOut = this.state;
  164. const { blockLen } = this;
  165. for (let pos = 0, len = out.length; pos < len;) {
  166. if (this.posOut >= blockLen)
  167. this.keccak();
  168. const take = Math.min(blockLen - this.posOut, len - pos);
  169. out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);
  170. this.posOut += take;
  171. pos += take;
  172. }
  173. return out;
  174. }
  175. xofInto(out) {
  176. // Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF
  177. if (!this.enableXOF)
  178. throw new Error('XOF is not possible for this instance');
  179. return this.writeInto(out);
  180. }
  181. xof(bytes) {
  182. (0, utils_ts_1.anumber)(bytes);
  183. return this.xofInto(new Uint8Array(bytes));
  184. }
  185. digestInto(out) {
  186. (0, utils_ts_1.aoutput)(out, this);
  187. if (this.finished)
  188. throw new Error('digest() was already called');
  189. this.writeInto(out);
  190. this.destroy();
  191. return out;
  192. }
  193. digest() {
  194. return this.digestInto(new Uint8Array(this.outputLen));
  195. }
  196. destroy() {
  197. this.destroyed = true;
  198. (0, utils_ts_1.clean)(this.state);
  199. }
  200. _cloneInto(to) {
  201. const { blockLen, suffix, outputLen, rounds, enableXOF } = this;
  202. to || (to = new Keccak(blockLen, suffix, outputLen, enableXOF, rounds));
  203. to.state32.set(this.state32);
  204. to.pos = this.pos;
  205. to.posOut = this.posOut;
  206. to.finished = this.finished;
  207. to.rounds = rounds;
  208. // Suffix can change in cSHAKE
  209. to.suffix = suffix;
  210. to.outputLen = outputLen;
  211. to.enableXOF = enableXOF;
  212. to.destroyed = this.destroyed;
  213. return to;
  214. }
  215. }
  216. exports.Keccak = Keccak;
  217. const gen = (suffix, blockLen, outputLen) => (0, utils_ts_1.createHasher)(() => new Keccak(blockLen, suffix, outputLen));
  218. /** SHA3-224 hash function. */
  219. exports.sha3_224 = (() => gen(0x06, 144, 224 / 8))();
  220. /** SHA3-256 hash function. Different from keccak-256. */
  221. exports.sha3_256 = (() => gen(0x06, 136, 256 / 8))();
  222. /** SHA3-384 hash function. */
  223. exports.sha3_384 = (() => gen(0x06, 104, 384 / 8))();
  224. /** SHA3-512 hash function. */
  225. exports.sha3_512 = (() => gen(0x06, 72, 512 / 8))();
  226. /** keccak-224 hash function. */
  227. exports.keccak_224 = (() => gen(0x01, 144, 224 / 8))();
  228. /** keccak-256 hash function. Different from SHA3-256. */
  229. exports.keccak_256 = (() => gen(0x01, 136, 256 / 8))();
  230. /** keccak-384 hash function. */
  231. exports.keccak_384 = (() => gen(0x01, 104, 384 / 8))();
  232. /** keccak-512 hash function. */
  233. exports.keccak_512 = (() => gen(0x01, 72, 512 / 8))();
  234. const genShake = (suffix, blockLen, outputLen) => (0, utils_ts_1.createXOFer)((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true));
  235. /** SHAKE128 XOF with 128-bit security. */
  236. exports.shake128 = (() => genShake(0x1f, 168, 128 / 8))();
  237. /** SHAKE256 XOF with 256-bit security. */
  238. exports.shake256 = (() => genShake(0x1f, 136, 256 / 8))();
  239. //# sourceMappingURL=sha3.js.map