sha3.js 9.8 KB

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