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 var tMsw;
177 var tLsw;
178
179 // Shortcuts
180 var lane = state[laneIndex];
181 var laneMsw = lane.high;
182 var laneLsw = lane.low;
183 var rhoOffset = RHO_OFFSETS[laneIndex];
184
185 // Rotate lanes
186 if (rhoOffset < 32) {
187 tMsw = (laneMsw << rhoOffset) | (laneLsw >>> (32 - rhoOffset));
188 tLsw = (laneLsw << rhoOffset) | (laneMsw >>> (32 - rhoOffset));
189 } else /* if (rhoOffset >= 32) */ {
190 tMsw = (laneLsw << (rhoOffset - 32)) | (laneMsw >>> (64 - rhoOffset));
191 tLsw = (laneMsw << (rhoOffset - 32)) | (laneLsw >>> (64 - rhoOffset));
192 }
193
194 // Transpose lanes
195 var TPiLane = T[PI_INDEXES[laneIndex]];
196 TPiLane.high = tMsw;
197 TPiLane.low = tLsw;
198 }
199
200 // Rho pi at x = y = 0
201 var T0 = T[0];
202 var state0 = state[0];
203 T0.high = state0.high;
204 T0.low = state0.low;
205
206 // Chi
207 for (var x = 0; x < 5; x++) {
208 for (var y = 0; y < 5; y++) {
209 // Shortcuts
210 var laneIndex = x + 5 * y;
211 var lane = state[laneIndex];
212 var TLane = T[laneIndex];
213 var Tx1Lane = T[((x + 1) % 5) + 5 * y];
214 var Tx2Lane = T[((x + 2) % 5) + 5 * y];
215
216 // Mix rows
217 lane.high = TLane.high ^ (~Tx1Lane.high & Tx2Lane.high);
218 lane.low = TLane.low ^ (~Tx1Lane.low & Tx2Lane.low);
219 }
220 }
221
222 // Iota
223 var lane = state[0];
224 var roundConstant = ROUND_CONSTANTS[round];
225 lane.high ^= roundConstant.high;
226 lane.low ^= roundConstant.low;
227 }
228 },
229
230 _doFinalize: function () {
231 // Shortcuts
232 var data = this._data;
233 var dataWords = data.words;
234 var nBitsTotal = this._nDataBytes * 8;
235 var nBitsLeft = data.sigBytes * 8;
236 var blockSizeBits = this.blockSize * 32;
237
238 // Add padding
239 dataWords[nBitsLeft >>> 5] |= 0x1 << (24 - nBitsLeft % 32);
240 dataWords[((Math.ceil((nBitsLeft + 1) / blockSizeBits) * blockSizeBits) >>> 5) - 1] |= 0x80;
241 data.sigBytes = dataWords.length * 4;
242
243 // Hash final blocks
244 this._process();
245
246 // Shortcuts
247 var state = this._state;
248 var outputLengthBytes = this.cfg.outputLength / 8;
249 var outputLengthLanes = outputLengthBytes / 8;
250
251 // Squeeze
252 var hashWords = [];
253 for (var i = 0; i < outputLengthLanes; i++) {
254 // Shortcuts
255 var lane = state[i];
256 var laneMsw = lane.high;
257 var laneLsw = lane.low;
258
259 // Swap endian
260 laneMsw = (
261 (((laneMsw << 8) | (laneMsw >>> 24)) & 0x00ff00ff) |
262 (((laneMsw << 24) | (laneMsw >>> 8)) & 0xff00ff00)
263 );
264 laneLsw = (
265 (((laneLsw << 8) | (laneLsw >>> 24)) & 0x00ff00ff) |
266 (((laneLsw << 24) | (laneLsw >>> 8)) & 0xff00ff00)
267 );
268
269 // Squeeze state to retrieve hash
270 hashWords.push(laneLsw);
271 hashWords.push(laneMsw);
272 }
273
274 // Return final computed hash
275 return new WordArray.init(hashWords, outputLengthBytes);
276 },
277
278 clone: function () {
279 var clone = Hasher.clone.call(this);
280
281 var state = clone._state = this._state.slice(0);
282 for (var i = 0; i < 25; i++) {
283 state[i] = state[i].clone();
284 }
285
286 return clone;
287 }
288 });
289
290 /**
291 * Shortcut function to the hasher's object interface.
292 *
293 * @param {WordArray|string} message The message to hash.
294 *
295 * @return {WordArray} The hash.
296 *
297 * @static
298 *
299 * @example
300 *
301 * var hash = CryptoJS.SHA3('message');
302 * var hash = CryptoJS.SHA3(wordArray);
303 */
304 C.SHA3 = Hasher._createHelper(SHA3);
305
306 /**
307 * Shortcut function to the HMAC's object interface.
308 *
309 * @param {WordArray|string} message The message to hash.
310 * @param {WordArray|string} key The secret key.
311 *
312 * @return {WordArray} The HMAC.
313 *
314 * @static
315 *
316 * @example
317 *
318 * var hmac = CryptoJS.HmacSHA3(message, key);
319 */
320 C.HmacSHA3 = Hasher._createHmacHelper(SHA3);
321 }(Math));
322
323
324 return CryptoJS.SHA3;
325
326}));
\No newline at end of file