sha3.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. ;(function (root, factory, undef) {
  2. if (typeof exports === "object") {
  3. // CommonJS
  4. module.exports = exports = factory(require("./core"), require("./x64-core"));
  5. } else if (typeof define === "function" && define.amd) {
  6. // AMD
  7. define(["./core", "./x64-core"], factory);
  8. } else {
  9. // Global (browser)
  10. factory(root.CryptoJS);
  11. }
  12. }(this, function (CryptoJS) {
  13. (function (Math) {
  14. // Shortcuts
  15. var C = CryptoJS;
  16. var C_lib = C.lib;
  17. var WordArray = C_lib.WordArray;
  18. var Hasher = C_lib.Hasher;
  19. var C_x64 = C.x64;
  20. var X64Word = C_x64.Word;
  21. var C_algo = C.algo;
  22. // Constants tables
  23. var RHO_OFFSETS = [];
  24. var PI_INDEXES = [];
  25. var ROUND_CONSTANTS = [];
  26. // Compute Constants
  27. (function () {
  28. // Compute rho offset constants
  29. var x = 1, y = 0;
  30. for (var t = 0; t < 24; t++) {
  31. RHO_OFFSETS[x + 5 * y] = ((t + 1) * (t + 2) / 2) % 64;
  32. var newX = y % 5;
  33. var newY = (2 * x + 3 * y) % 5;
  34. x = newX;
  35. y = newY;
  36. }
  37. // Compute pi index constants
  38. for (var x = 0; x < 5; x++) {
  39. for (var y = 0; y < 5; y++) {
  40. PI_INDEXES[x + 5 * y] = y + ((2 * x + 3 * y) % 5) * 5;
  41. }
  42. }
  43. // Compute round constants
  44. var LFSR = 0x01;
  45. for (var i = 0; i < 24; i++) {
  46. var roundConstantMsw = 0;
  47. var roundConstantLsw = 0;
  48. for (var j = 0; j < 7; j++) {
  49. if (LFSR & 0x01) {
  50. var bitPosition = (1 << j) - 1;
  51. if (bitPosition < 32) {
  52. roundConstantLsw ^= 1 << bitPosition;
  53. } else /* if (bitPosition >= 32) */ {
  54. roundConstantMsw ^= 1 << (bitPosition - 32);
  55. }
  56. }
  57. // Compute next LFSR
  58. if (LFSR & 0x80) {
  59. // Primitive polynomial over GF(2): x^8 + x^6 + x^5 + x^4 + 1
  60. LFSR = (LFSR << 1) ^ 0x71;
  61. } else {
  62. LFSR <<= 1;
  63. }
  64. }
  65. ROUND_CONSTANTS[i] = X64Word.create(roundConstantMsw, roundConstantLsw);
  66. }
  67. }());
  68. // Reusable objects for temporary values
  69. var T = [];
  70. (function () {
  71. for (var i = 0; i < 25; i++) {
  72. T[i] = X64Word.create();
  73. }
  74. }());
  75. /**
  76. * SHA-3 hash algorithm.
  77. */
  78. var SHA3 = C_algo.SHA3 = Hasher.extend({
  79. /**
  80. * Configuration options.
  81. *
  82. * @property {number} outputLength
  83. * The desired number of bits in the output hash.
  84. * Only values permitted are: 224, 256, 384, 512.
  85. * Default: 512
  86. */
  87. cfg: Hasher.cfg.extend({
  88. outputLength: 512
  89. }),
  90. _doReset: function () {
  91. var state = this._state = []
  92. for (var i = 0; i < 25; i++) {
  93. state[i] = new X64Word.init();
  94. }
  95. this.blockSize = (1600 - 2 * this.cfg.outputLength) / 32;
  96. },
  97. _doProcessBlock: function (M, offset) {
  98. // Shortcuts
  99. var state = this._state;
  100. var nBlockSizeLanes = this.blockSize / 2;
  101. // Absorb
  102. for (var i = 0; i < nBlockSizeLanes; i++) {
  103. // Shortcuts
  104. var M2i = M[offset + 2 * i];
  105. var M2i1 = M[offset + 2 * i + 1];
  106. // Swap endian
  107. M2i = (
  108. (((M2i << 8) | (M2i >>> 24)) & 0x00ff00ff) |
  109. (((M2i << 24) | (M2i >>> 8)) & 0xff00ff00)
  110. );
  111. M2i1 = (
  112. (((M2i1 << 8) | (M2i1 >>> 24)) & 0x00ff00ff) |
  113. (((M2i1 << 24) | (M2i1 >>> 8)) & 0xff00ff00)
  114. );
  115. // Absorb message into state
  116. var lane = state[i];
  117. lane.high ^= M2i1;
  118. lane.low ^= M2i;
  119. }
  120. // Rounds
  121. for (var round = 0; round < 24; round++) {
  122. // Theta
  123. for (var x = 0; x < 5; x++) {
  124. // Mix column lanes
  125. var tMsw = 0, tLsw = 0;
  126. for (var y = 0; y < 5; y++) {
  127. var lane = state[x + 5 * y];
  128. tMsw ^= lane.high;
  129. tLsw ^= lane.low;
  130. }
  131. // Temporary values
  132. var Tx = T[x];
  133. Tx.high = tMsw;
  134. Tx.low = tLsw;
  135. }
  136. for (var x = 0; x < 5; x++) {
  137. // Shortcuts
  138. var Tx4 = T[(x + 4) % 5];
  139. var Tx1 = T[(x + 1) % 5];
  140. var Tx1Msw = Tx1.high;
  141. var Tx1Lsw = Tx1.low;
  142. // Mix surrounding columns
  143. var tMsw = Tx4.high ^ ((Tx1Msw << 1) | (Tx1Lsw >>> 31));
  144. var tLsw = Tx4.low ^ ((Tx1Lsw << 1) | (Tx1Msw >>> 31));
  145. for (var y = 0; y < 5; y++) {
  146. var lane = state[x + 5 * y];
  147. lane.high ^= tMsw;
  148. lane.low ^= tLsw;
  149. }
  150. }
  151. // Rho Pi
  152. for (var laneIndex = 1; laneIndex < 25; laneIndex++) {
  153. // Shortcuts
  154. var lane = state[laneIndex];
  155. var laneMsw = lane.high;
  156. var laneLsw = lane.low;
  157. var rhoOffset = RHO_OFFSETS[laneIndex];
  158. // Rotate lanes
  159. if (rhoOffset < 32) {
  160. var tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset));
  161. var tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset));
  162. } else /* if (rhoOffset >= 32) */ {
  163. var tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset));
  164. var tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset));
  165. }
  166. // Transpose lanes
  167. var TPiLane = T[PI_INDEXES[laneIndex]];
  168. TPiLane.high = tMsw;
  169. TPiLane.low = tLsw;
  170. }
  171. // Rho pi at x = y = 0
  172. var T0 = T[0];
  173. var state0 = state[0];
  174. T0.high = state0.high;
  175. T0.low = state0.low;
  176. // Chi
  177. for (var x = 0; x < 5; x++) {
  178. for (var y = 0; y < 5; y++) {
  179. // Shortcuts
  180. var laneIndex = x + 5 * y;
  181. var lane = state[laneIndex];
  182. var TLane = T[laneIndex];
  183. var Tx1Lane = T[((x + 1) % 5) + 5 * y];
  184. var Tx2Lane = T[((x + 2) % 5) + 5 * y];
  185. // Mix rows
  186. lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high);
  187. lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low);
  188. }
  189. }
  190. // Iota
  191. var lane = state[0];
  192. var roundConstant = ROUND_CONSTANTS[round];
  193. lane.high ^= roundConstant.high;
  194. lane.low ^= roundConstant.low;
  195. ;
  196. }
  197. },
  198. _doFinalize: function () {
  199. // Shortcuts
  200. var data = this._data;
  201. var dataWords = data.words;
  202. var nBitsTotal = this._nDataBytes * 8;
  203. var nBitsLeft = data.sigBytes * 8;
  204. var blockSizeBits = this.blockSize * 32;
  205. // Add padding
  206. dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32);
  207. dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80;
  208. data.sigBytes = dataWords.length * 4;
  209. // Hash final blocks
  210. this._process();
  211. // Shortcuts
  212. var state = this._state;
  213. var outputLengthBytes = this.cfg.outputLength / 8;
  214. var outputLengthLanes = outputLengthBytes / 8;
  215. // Squeeze
  216. var hashWords = [];
  217. for (var i = 0; i < outputLengthLanes; i++) {
  218. // Shortcuts
  219. var lane = state[i];
  220. var laneMsw = lane.high;
  221. var laneLsw = lane.low;
  222. // Swap endian
  223. laneMsw = (
  224. (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) |
  225. (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00)
  226. );
  227. laneLsw = (
  228. (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) |
  229. (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00)
  230. );
  231. // Squeeze state to retrieve hash
  232. hashWords.push(laneLsw);
  233. hashWords.push(laneMsw);
  234. }
  235. // Return final computed hash
  236. return new WordArray.init(hashWords, outputLengthBytes);
  237. },
  238. clone: function () {
  239. var clone = Hasher.clone.call(this);
  240. var state = clone._state = this._state.slice(0);
  241. for (var i = 0; i < 25; i++) {
  242. state[i] = state[i].clone();
  243. }
  244. return clone;
  245. }
  246. });
  247. /**
  248. * Shortcut function to the hasher's object interface.
  249. *
  250. * @param {WordArray|string} message The message to hash.
  251. *
  252. * @return {WordArray} The hash.
  253. *
  254. * @static
  255. *
  256. * @example
  257. *
  258. * var hash = CryptoJS.SHA3('message');
  259. * var hash = CryptoJS.SHA3(wordArray);
  260. */
  261. C.SHA3 = Hasher._createHelper(SHA3);
  262. /**
  263. * Shortcut function to the HMAC's object interface.
  264. *
  265. * @param {WordArray|string} message The message to hash.
  266. * @param {WordArray|string} key The secret key.
  267. *
  268. * @return {WordArray} The HMAC.
  269. *
  270. * @static
  271. *
  272. * @example
  273. *
  274. * var hmac = CryptoJS.HmacSHA3(message, key);
  275. */
  276. C.HmacSHA3 = Hasher._createHmacHelper(SHA3);
  277. }(Math));
  278. return CryptoJS.SHA3;
  279. }));