UNPKG

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