Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/crypt/sha2_64bit.js
2868 views
1
// Copyright 2014 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview Base class for the 64-bit SHA-2 cryptographic hashes.
17
*
18
* Variable names follow the notation in FIPS PUB 180-3:
19
* http://csrc.nist.gov/publications/fips/fips180-3/fips180-3_final.pdf.
20
*
21
* This code borrows heavily from the 32-bit SHA2 implementation written by
22
* Yue Zhang (zysxqn@).
23
*
24
* @author [email protected] (Frank Yellin)
25
*/
26
27
goog.provide('goog.crypt.Sha2_64bit');
28
29
goog.require('goog.array');
30
goog.require('goog.asserts');
31
goog.require('goog.crypt.Hash');
32
goog.require('goog.math.Long');
33
34
35
36
/**
37
* Constructs a SHA-2 64-bit cryptographic hash.
38
* This class should not be used. Rather, one should use one of its
39
* subclasses.
40
* @constructor
41
* @param {number} numHashBlocks The size of the output in 16-byte blocks
42
* @param {!Array<number>} initHashBlocks The hash-specific initialization
43
* vector, as a sequence of sixteen 32-bit numbers.
44
* @extends {goog.crypt.Hash}
45
* @struct
46
*/
47
goog.crypt.Sha2_64bit = function(numHashBlocks, initHashBlocks) {
48
goog.crypt.Sha2_64bit.base(this, 'constructor');
49
50
/**
51
* The number of bytes that are digested in each pass of this hasher.
52
* @const {number}
53
*/
54
this.blockSize = goog.crypt.Sha2_64bit.BLOCK_SIZE_;
55
56
/**
57
* A chunk holding the currently processed message bytes. Once the chunk has
58
* {@code this.blocksize} bytes, we feed it into [@code computeChunk_}.
59
* @private {!Uint8Array|!Array<number>}
60
*/
61
this.chunk_ = goog.global['Uint8Array'] ? new Uint8Array(this.blockSize) :
62
new Array(this.blockSize);
63
64
/**
65
* Current number of bytes in {@code this.chunk_}.
66
* @private {number}
67
*/
68
this.chunkBytes_ = 0;
69
70
/**
71
* Total number of bytes in currently processed message.
72
* @private {number}
73
*/
74
this.total_ = 0;
75
76
/**
77
* Holds the previous values of accumulated hash a-h in the
78
* {@code computeChunk_} function.
79
* @private {!Array<!goog.math.Long>}
80
*/
81
this.hash_ = [];
82
83
/**
84
* The number of blocks of output produced by this hash function, where each
85
* block is eight bytes long.
86
* @private {number}
87
*/
88
this.numHashBlocks_ = numHashBlocks;
89
90
/**
91
* Temporary array used in chunk computation. Allocate here as a
92
* member rather than as a local within computeChunk_() as a
93
* performance optimization to reduce the number of allocations and
94
* reduce garbage collection.
95
* @type {!Array<!goog.math.Long>}
96
* @private
97
*/
98
this.w_ = [];
99
100
/**
101
* The value to which {@code this.hash_} should be reset when this
102
* Hasher is reset.
103
* @private @const {!Array<!goog.math.Long>}
104
*/
105
this.initHashBlocks_ = goog.crypt.Sha2_64bit.toLongArray_(initHashBlocks);
106
107
/**
108
* If true, we have taken the digest from this hasher, but we have not
109
* yet reset it.
110
*
111
* @private {boolean}
112
*/
113
this.needsReset_ = false;
114
115
this.reset();
116
};
117
goog.inherits(goog.crypt.Sha2_64bit, goog.crypt.Hash);
118
119
120
/**
121
* The number of bytes that are digested in each pass of this hasher.
122
* @private @const {number}
123
*/
124
goog.crypt.Sha2_64bit.BLOCK_SIZE_ = 1024 / 8;
125
126
127
/**
128
* Contains data needed to pad messages less than {@code blocksize} bytes.
129
* @private {!Array<number>}
130
*/
131
goog.crypt.Sha2_64bit.PADDING_ = goog.array.concat(
132
[0x80], goog.array.repeat(0, goog.crypt.Sha2_64bit.BLOCK_SIZE_ - 1));
133
134
135
/**
136
* Resets this hash function.
137
* @override
138
*/
139
goog.crypt.Sha2_64bit.prototype.reset = function() {
140
this.chunkBytes_ = 0;
141
this.total_ = 0;
142
this.hash_ = goog.array.clone(this.initHashBlocks_);
143
this.needsReset_ = false;
144
};
145
146
147
/** @override */
148
goog.crypt.Sha2_64bit.prototype.update = function(message, opt_length) {
149
var length = goog.isDef(opt_length) ? opt_length : message.length;
150
151
// Make sure this hasher is usable.
152
if (this.needsReset_) {
153
throw Error('this hasher needs to be reset');
154
}
155
// Process the message from left to right up to |length| bytes.
156
// When we get a 512-bit chunk, compute the hash of it and reset
157
// this.chunk_. The message might not be multiple of 512 bits so we
158
// might end up with a chunk that is less than 512 bits. We store
159
// such partial chunk in chunk_ and it will be filled up later
160
// in digest().
161
var chunkBytes = this.chunkBytes_;
162
163
// The input message could be either byte array or string.
164
if (goog.isString(message)) {
165
for (var i = 0; i < length; i++) {
166
var b = message.charCodeAt(i);
167
if (b > 255) {
168
throw Error('Characters must be in range [0,255]');
169
}
170
this.chunk_[chunkBytes++] = b;
171
if (chunkBytes == this.blockSize) {
172
this.computeChunk_();
173
chunkBytes = 0;
174
}
175
}
176
} else if (goog.isArrayLike(message)) {
177
for (var i = 0; i < length; i++) {
178
var b = message[i];
179
// Hack: b|0 coerces b to an integer, so the last part confirms that
180
// b has no fractional part.
181
if (!goog.isNumber(b) || b < 0 || b > 255 || b != (b | 0)) {
182
throw Error('message must be a byte array');
183
}
184
this.chunk_[chunkBytes++] = b;
185
if (chunkBytes == this.blockSize) {
186
this.computeChunk_();
187
chunkBytes = 0;
188
}
189
}
190
} else {
191
throw Error('message must be string or array');
192
}
193
194
// Record the current bytes in chunk to support partial update.
195
this.chunkBytes_ = chunkBytes;
196
197
// Record total message bytes we have processed so far.
198
this.total_ += length;
199
};
200
201
202
/** @override */
203
goog.crypt.Sha2_64bit.prototype.digest = function() {
204
if (this.needsReset_) {
205
throw Error('this hasher needs to be reset');
206
}
207
var totalBits = this.total_ * 8;
208
209
// Append pad 0x80 0x00* until this.chunkBytes_ == 112
210
if (this.chunkBytes_ < 112) {
211
this.update(goog.crypt.Sha2_64bit.PADDING_, 112 - this.chunkBytes_);
212
} else {
213
// the rest of this block, plus 112 bytes of next block
214
this.update(
215
goog.crypt.Sha2_64bit.PADDING_,
216
this.blockSize - this.chunkBytes_ + 112);
217
}
218
219
// Append # bits in the 64-bit big-endian format.
220
for (var i = 127; i >= 112; i--) {
221
this.chunk_[i] = totalBits & 255;
222
totalBits /= 256; // Don't use bit-shifting here!
223
}
224
this.computeChunk_();
225
226
// Finally, output the result digest.
227
var n = 0;
228
var digest = new Array(8 * this.numHashBlocks_);
229
for (var i = 0; i < this.numHashBlocks_; i++) {
230
var block = this.hash_[i];
231
var high = block.getHighBits();
232
var low = block.getLowBits();
233
for (var j = 24; j >= 0; j -= 8) {
234
digest[n++] = ((high >> j) & 255);
235
}
236
for (var j = 24; j >= 0; j -= 8) {
237
digest[n++] = ((low >> j) & 255);
238
}
239
}
240
241
// The next call to this hasher must be a reset
242
this.needsReset_ = true;
243
return digest;
244
};
245
246
247
/**
248
* Updates this hash by processing the 1024-bit message chunk in this.chunk_.
249
* @private
250
*/
251
goog.crypt.Sha2_64bit.prototype.computeChunk_ = function() {
252
var chunk = this.chunk_;
253
var K_ = goog.crypt.Sha2_64bit.K_;
254
255
// Divide the chunk into 16 64-bit-words.
256
var w = this.w_;
257
for (var i = 0; i < 16; i++) {
258
var offset = i * 8;
259
w[i] = new goog.math.Long(
260
(chunk[offset + 4] << 24) | (chunk[offset + 5] << 16) |
261
(chunk[offset + 6] << 8) | (chunk[offset + 7]),
262
(chunk[offset] << 24) | (chunk[offset + 1] << 16) |
263
(chunk[offset + 2] << 8) | (chunk[offset + 3]));
264
}
265
266
// Extend the w[] array to be the number of rounds.
267
for (var i = 16; i < 80; i++) {
268
var s0 = this.sigma0_(w[i - 15]);
269
var s1 = this.sigma1_(w[i - 2]);
270
w[i] = this.sum_(w[i - 16], w[i - 7], s0, s1);
271
}
272
273
var a = this.hash_[0];
274
var b = this.hash_[1];
275
var c = this.hash_[2];
276
var d = this.hash_[3];
277
var e = this.hash_[4];
278
var f = this.hash_[5];
279
var g = this.hash_[6];
280
var h = this.hash_[7];
281
for (var i = 0; i < 80; i++) {
282
var S0 = this.Sigma0_(a);
283
var maj = this.majority_(a, b, c);
284
var t2 = S0.add(maj);
285
var S1 = this.Sigma1_(e);
286
var ch = this.choose_(e, f, g);
287
var t1 = this.sum_(h, S1, ch, K_[i], w[i]);
288
h = g;
289
g = f;
290
f = e;
291
e = d.add(t1);
292
d = c;
293
c = b;
294
b = a;
295
a = t1.add(t2);
296
}
297
298
this.hash_[0] = this.hash_[0].add(a);
299
this.hash_[1] = this.hash_[1].add(b);
300
this.hash_[2] = this.hash_[2].add(c);
301
this.hash_[3] = this.hash_[3].add(d);
302
this.hash_[4] = this.hash_[4].add(e);
303
this.hash_[5] = this.hash_[5].add(f);
304
this.hash_[6] = this.hash_[6].add(g);
305
this.hash_[7] = this.hash_[7].add(h);
306
};
307
308
309
/**
310
* Calculates the SHA2 64-bit sigma0 function.
311
* rotateRight(value, 1) ^ rotateRight(value, 8) ^ (value >>> 7)
312
*
313
* @private
314
* @param {!goog.math.Long} value
315
* @return {!goog.math.Long}
316
*/
317
goog.crypt.Sha2_64bit.prototype.sigma0_ = function(value) {
318
var valueLow = value.getLowBits();
319
var valueHigh = value.getHighBits();
320
// Implementation note: We purposely do not use the shift operations defined
321
// in goog.math.Long. Inlining the code for specific values of shifting and
322
// not generating the intermediate results doubles the speed of this code.
323
var low = (valueLow >>> 1) ^ (valueHigh << 31) ^ (valueLow >>> 8) ^
324
(valueHigh << 24) ^ (valueLow >>> 7) ^ (valueHigh << 25);
325
var high = (valueHigh >>> 1) ^ (valueLow << 31) ^ (valueHigh >>> 8) ^
326
(valueLow << 24) ^ (valueHigh >>> 7);
327
return new goog.math.Long(low, high);
328
};
329
330
331
/**
332
* Calculates the SHA2 64-bit sigma1 function.
333
* rotateRight(value, 19) ^ rotateRight(value, 61) ^ (value >>> 6)
334
*
335
* @private
336
* @param {!goog.math.Long} value
337
* @return {!goog.math.Long}
338
*/
339
goog.crypt.Sha2_64bit.prototype.sigma1_ = function(value) {
340
var valueLow = value.getLowBits();
341
var valueHigh = value.getHighBits();
342
// Implementation note: See _sigma0() above
343
var low = (valueLow >>> 19) ^ (valueHigh << 13) ^ (valueHigh >>> 29) ^
344
(valueLow << 3) ^ (valueLow >>> 6) ^ (valueHigh << 26);
345
var high = (valueHigh >>> 19) ^ (valueLow << 13) ^ (valueLow >>> 29) ^
346
(valueHigh << 3) ^ (valueHigh >>> 6);
347
return new goog.math.Long(low, high);
348
};
349
350
351
/**
352
* Calculates the SHA2 64-bit Sigma0 function.
353
* rotateRight(value, 28) ^ rotateRight(value, 34) ^ rotateRight(value, 39)
354
*
355
* @private
356
* @param {!goog.math.Long} value
357
* @return {!goog.math.Long}
358
*/
359
goog.crypt.Sha2_64bit.prototype.Sigma0_ = function(value) {
360
var valueLow = value.getLowBits();
361
var valueHigh = value.getHighBits();
362
// Implementation note: See _sigma0() above
363
var low = (valueLow >>> 28) ^ (valueHigh << 4) ^ (valueHigh >>> 2) ^
364
(valueLow << 30) ^ (valueHigh >>> 7) ^ (valueLow << 25);
365
var high = (valueHigh >>> 28) ^ (valueLow << 4) ^ (valueLow >>> 2) ^
366
(valueHigh << 30) ^ (valueLow >>> 7) ^ (valueHigh << 25);
367
return new goog.math.Long(low, high);
368
};
369
370
371
/**
372
* Calculates the SHA2 64-bit Sigma1 function.
373
* rotateRight(value, 14) ^ rotateRight(value, 18) ^ rotateRight(value, 41)
374
*
375
* @private
376
* @param {!goog.math.Long} value
377
* @return {!goog.math.Long}
378
*/
379
goog.crypt.Sha2_64bit.prototype.Sigma1_ = function(value) {
380
var valueLow = value.getLowBits();
381
var valueHigh = value.getHighBits();
382
// Implementation note: See _sigma0() above
383
var low = (valueLow >>> 14) ^ (valueHigh << 18) ^ (valueLow >>> 18) ^
384
(valueHigh << 14) ^ (valueHigh >>> 9) ^ (valueLow << 23);
385
var high = (valueHigh >>> 14) ^ (valueLow << 18) ^ (valueHigh >>> 18) ^
386
(valueLow << 14) ^ (valueLow >>> 9) ^ (valueHigh << 23);
387
return new goog.math.Long(low, high);
388
};
389
390
391
/**
392
* Calculates the SHA-2 64-bit choose function.
393
*
394
* This function uses {@code value} as a mask to choose bits from either
395
* {@code one} if the bit is set or {@code two} if the bit is not set.
396
*
397
* @private
398
* @param {!goog.math.Long} value
399
* @param {!goog.math.Long} one
400
* @param {!goog.math.Long} two
401
* @return {!goog.math.Long}
402
*/
403
goog.crypt.Sha2_64bit.prototype.choose_ = function(value, one, two) {
404
var valueLow = value.getLowBits();
405
var valueHigh = value.getHighBits();
406
return new goog.math.Long(
407
(valueLow & one.getLowBits()) | (~valueLow & two.getLowBits()),
408
(valueHigh & one.getHighBits()) | (~valueHigh & two.getHighBits()));
409
};
410
411
412
/**
413
* Calculates the SHA-2 64-bit majority function.
414
* This function returns, for each bit position, the bit held by the majority
415
* of its three arguments.
416
*
417
* @private
418
* @param {!goog.math.Long} one
419
* @param {!goog.math.Long} two
420
* @param {!goog.math.Long} three
421
* @return {!goog.math.Long}
422
*/
423
goog.crypt.Sha2_64bit.prototype.majority_ = function(one, two, three) {
424
return new goog.math.Long(
425
(one.getLowBits() & two.getLowBits()) |
426
(two.getLowBits() & three.getLowBits()) |
427
(one.getLowBits() & three.getLowBits()),
428
(one.getHighBits() & two.getHighBits()) |
429
(two.getHighBits() & three.getHighBits()) |
430
(one.getHighBits() & three.getHighBits()));
431
};
432
433
434
/**
435
* Adds two or more goog.math.Long values.
436
*
437
* @private
438
* @param {!goog.math.Long} one first summand
439
* @param {!goog.math.Long} two second summand
440
* @param {...goog.math.Long} var_args more arguments to sum
441
* @return {!goog.math.Long} The resulting sum.
442
*/
443
goog.crypt.Sha2_64bit.prototype.sum_ = function(one, two, var_args) {
444
// The low bits may be signed, but they represent a 32-bit unsigned quantity.
445
// We must be careful to normalize them.
446
// This doesn't matter for the high bits.
447
// Implementation note: Performance testing shows that this method runs
448
// fastest when the first two arguments are pulled out of the loop.
449
var low = (one.getLowBits() ^ 0x80000000) + (two.getLowBits() ^ 0x80000000);
450
var high = one.getHighBits() + two.getHighBits();
451
for (var i = arguments.length - 1; i >= 2; --i) {
452
low += arguments[i].getLowBits() ^ 0x80000000;
453
high += arguments[i].getHighBits();
454
}
455
// Because of the ^0x80000000, each value we added is 0x80000000 too small.
456
// Add arguments.length * 0x80000000 to the current sum. We can do this
457
// quickly by adding 0x80000000 to low when the number of arguments is
458
// odd, and adding (number of arguments) >> 1 to high.
459
if (arguments.length & 1) {
460
low += 0x80000000;
461
}
462
high += arguments.length >> 1;
463
464
// If low is outside the range [0, 0xFFFFFFFF], its overflow or underflow
465
// should be added to high. We don't actually need to modify low or
466
// normalize high because the goog.math.Long constructor already does that.
467
high += Math.floor(low / 0x100000000);
468
return new goog.math.Long(low, high);
469
};
470
471
472
/**
473
* Converts an array of 32-bit integers into an array of goog.math.Long
474
* elements.
475
*
476
* @private
477
* @param {!Array<number>} values An array of 32-bit numbers. Its length
478
* must be even. Each pair of numbers represents a 64-bit integer
479
* in big-endian order
480
* @return {!Array<!goog.math.Long>}
481
*/
482
goog.crypt.Sha2_64bit.toLongArray_ = function(values) {
483
goog.asserts.assert(values.length % 2 == 0);
484
var result = [];
485
for (var i = 0; i < values.length; i += 2) {
486
result.push(new goog.math.Long(values[i + 1], values[i]));
487
}
488
return result;
489
};
490
491
492
/**
493
* Fixed constants used in SHA-512 variants.
494
*
495
* These values are from Section 4.2.3 of
496
* http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
497
* @const
498
* @private {!Array<!goog.math.Long>}
499
*/
500
goog.crypt.Sha2_64bit.K_ = goog.crypt.Sha2_64bit.toLongArray_([
501
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, 0xb5c0fbcf, 0xec4d3b2f,
502
0xe9b5dba5, 0x8189dbbc, 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
503
0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, 0xd807aa98, 0xa3030242,
504
0x12835b01, 0x45706fbe, 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
505
0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, 0x9bdc06a7, 0x25c71235,
506
0xc19bf174, 0xcf692694, 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
507
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, 0x2de92c6f, 0x592b0275,
508
0x4a7484aa, 0x6ea6e483, 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
509
0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, 0xb00327c8, 0x98fb213f,
510
0xbf597fc7, 0xbeef0ee4, 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
511
0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, 0x27b70a85, 0x46d22ffc,
512
0x2e1b2138, 0x5c26c926, 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
513
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, 0x81c2c92e, 0x47edaee6,
514
0x92722c85, 0x1482353b, 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
515
0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, 0xd192e819, 0xd6ef5218,
516
0xd6990624, 0x5565a910, 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
517
0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, 0x2748774c, 0xdf8eeb99,
518
0x34b0bcb5, 0xe19b48a8, 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
519
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, 0x748f82ee, 0x5defb2fc,
520
0x78a5636f, 0x43172f60, 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
521
0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, 0xbef9a3f7, 0xb2c67915,
522
0xc67178f2, 0xe372532b, 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
523
0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, 0x06f067aa, 0x72176fba,
524
0x0a637dc5, 0xa2c898a6, 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
525
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, 0x3c9ebe0a, 0x15c9bebc,
526
0x431d67c4, 0x9c100d4c, 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
527
0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
528
]);
529
530