sha3.js 10 KB

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