sha3.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  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. // Shortcuts
  156. var lane = state[laneIndex];
  157. var laneMsw = lane.high;
  158. var laneLsw = lane.low;
  159. var rhoOffset = RHO_OFFSETS[laneIndex];
  160. // Rotate lanes
  161. if (rhoOffset < 32) {
  162. var tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset));
  163. var tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset));
  164. } else /* if (rhoOffset >= 32) */ {
  165. var tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset));
  166. var tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset));
  167. }
  168. // Transpose lanes
  169. var TPiLane = T[PI_INDEXES[laneIndex]];
  170. TPiLane.high = tMsw;
  171. TPiLane.low = tLsw;
  172. }
  173. // Rho pi at x = y = 0
  174. var T0 = T[0];
  175. var state0 = state[0];
  176. T0.high = state0.high;
  177. T0.low = state0.low;
  178. // Chi
  179. for (var x = 0; x < 5; x++) {
  180. for (var y = 0; y < 5; y++) {
  181. // Shortcuts
  182. var laneIndex = x + 5 * y;
  183. var lane = state[laneIndex];
  184. var TLane = T[laneIndex];
  185. var Tx1Lane = T[((x + 1) % 5) + 5 * y];
  186. var Tx2Lane = T[((x + 2) % 5) + 5 * y];
  187. // Mix rows
  188. lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high);
  189. lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low);
  190. }
  191. }
  192. // Iota
  193. var lane = state[0];
  194. var roundConstant = ROUND_CONSTANTS[round];
  195. lane.high ^= roundConstant.high;
  196. lane.low ^= roundConstant.low;;
  197. }
  198. },
  199. _doFinalize: function () {
  200. // Shortcuts
  201. var data = this._data;
  202. var dataWords = data.words;
  203. var nBitsTotal = this._nDataBytes * 8;
  204. var nBitsLeft = data.sigBytes * 8;
  205. var blockSizeBits = this.blockSize * 32;
  206. // Add padding
  207. dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32);
  208. dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80;
  209. data.sigBytes = dataWords.length * 4;
  210. // Hash final blocks
  211. this._process();
  212. // Shortcuts
  213. var state = this._state;
  214. var outputLengthBytes = this.cfg.outputLength / 8;
  215. var outputLengthLanes = outputLengthBytes / 8;
  216. // Squeeze
  217. var hashWords = [];
  218. for (var i = 0; i < outputLengthLanes; i++) {
  219. // Shortcuts
  220. var lane = state[i];
  221. var laneMsw = lane.high;
  222. var laneLsw = lane.low;
  223. // Swap endian
  224. laneMsw = (
  225. (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) |
  226. (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00)
  227. );
  228. laneLsw = (
  229. (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) |
  230. (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00)
  231. );
  232. // Squeeze state to retrieve hash
  233. hashWords.push(laneLsw);
  234. hashWords.push(laneMsw);
  235. }
  236. // Return final computed hash
  237. return new WordArray.init(hashWords, outputLengthBytes);
  238. },
  239. clone: function () {
  240. var clone = Hasher.clone.call(this);
  241. var state = clone._state = this._state.slice(0);
  242. for (var i = 0; i < 25; i++) {
  243. state[i] = state[i].clone();
  244. }
  245. return clone;
  246. }
  247. });
  248. /**
  249. * Shortcut function to the hasher's object interface.
  250. *
  251. * @param {WordArray|string} message The message to hash.
  252. *
  253. * @return {WordArray} The hash.
  254. *
  255. * @static
  256. *
  257. * @example
  258. *
  259. * var hash = CryptoJS.SHA3('message');
  260. * var hash = CryptoJS.SHA3(wordArray);
  261. */
  262. C.SHA3 = Hasher._createHelper(SHA3);
  263. /**
  264. * Shortcut function to the HMAC's object interface.
  265. *
  266. * @param {WordArray|string} message The message to hash.
  267. * @param {WordArray|string} key The secret key.
  268. *
  269. * @return {WordArray} The HMAC.
  270. *
  271. * @static
  272. *
  273. * @example
  274. *
  275. * var hmac = CryptoJS.HmacSHA3(message, key);
  276. */
  277. C.HmacSHA3 = Hasher._createHmacHelper(SHA3);
  278. }(Math));
  279. return CryptoJS.SHA3;
  280. }));