Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/crypt/sha2.js
2868 views
1
// Copyright 2012 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 SHA-2 cryptographic hash.
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
* Some code similar to SHA1 are borrowed from sha1.js written by mschilder@.
22
*
23
*/
24
25
goog.provide('goog.crypt.Sha2');
26
27
goog.require('goog.array');
28
goog.require('goog.asserts');
29
goog.require('goog.crypt.Hash');
30
31
32
33
/**
34
* SHA-2 cryptographic hash constructor.
35
* This constructor should not be used directly to create the object. Rather,
36
* one should use the constructor of the sub-classes.
37
* @param {number} numHashBlocks The size of output in 16-byte blocks.
38
* @param {!Array<number>} initHashBlocks The hash-specific initialization
39
* @constructor
40
* @extends {goog.crypt.Hash}
41
* @struct
42
*/
43
goog.crypt.Sha2 = function(numHashBlocks, initHashBlocks) {
44
goog.crypt.Sha2.base(this, 'constructor');
45
46
this.blockSize = goog.crypt.Sha2.BLOCKSIZE_;
47
48
/**
49
* A chunk holding the currently processed message bytes. Once the chunk has
50
* 64 bytes, we feed it into computeChunk_ function and reset this.chunk_.
51
* @private {!Array<number>|!Uint8Array}
52
*/
53
this.chunk_ = goog.global['Uint8Array'] ? new Uint8Array(this.blockSize) :
54
new Array(this.blockSize);
55
56
/**
57
* Current number of bytes in this.chunk_.
58
* @private {number}
59
*/
60
this.inChunk_ = 0;
61
62
/**
63
* Total number of bytes in currently processed message.
64
* @private {number}
65
*/
66
this.total_ = 0;
67
68
69
/**
70
* Holds the previous values of accumulated hash a-h in the computeChunk_
71
* function.
72
* @private {!Array<number>|!Int32Array}
73
*/
74
this.hash_ = [];
75
76
/**
77
* The number of output hash blocks (each block is 4 bytes long).
78
* @private {number}
79
*/
80
this.numHashBlocks_ = numHashBlocks;
81
82
/**
83
* @private {!Array<number>} initHashBlocks
84
*/
85
this.initHashBlocks_ = initHashBlocks;
86
87
/**
88
* Temporary array used in chunk computation. Allocate here as a
89
* member rather than as a local within computeChunk_() as a
90
* performance optimization to reduce the number of allocations and
91
* reduce garbage collection.
92
* @private {!Int32Array|!Array<number>}
93
*/
94
this.w_ = goog.global['Int32Array'] ? new Int32Array(64) : new Array(64);
95
96
if (!goog.isDef(goog.crypt.Sha2.Kx_)) {
97
// This is the first time this constructor has been called.
98
if (goog.global['Int32Array']) {
99
// Typed arrays exist
100
goog.crypt.Sha2.Kx_ = new Int32Array(goog.crypt.Sha2.K_);
101
} else {
102
// Typed arrays do not exist
103
goog.crypt.Sha2.Kx_ = goog.crypt.Sha2.K_;
104
}
105
}
106
107
this.reset();
108
};
109
goog.inherits(goog.crypt.Sha2, goog.crypt.Hash);
110
111
112
/**
113
* The block size
114
* @private {number}
115
*/
116
goog.crypt.Sha2.BLOCKSIZE_ = 512 / 8;
117
118
119
/**
120
* Contains data needed to pad messages less than BLOCK_SIZE_ bytes.
121
* @private {!Array<number>}
122
*/
123
goog.crypt.Sha2.PADDING_ = goog.array.concat(
124
128, goog.array.repeat(0, goog.crypt.Sha2.BLOCKSIZE_ - 1));
125
126
127
/** @override */
128
goog.crypt.Sha2.prototype.reset = function() {
129
this.inChunk_ = 0;
130
this.total_ = 0;
131
this.hash_ = goog.global['Int32Array'] ?
132
new Int32Array(this.initHashBlocks_) :
133
goog.array.clone(this.initHashBlocks_);
134
};
135
136
137
/**
138
* Helper function to compute the hashes for a given 512-bit message chunk.
139
* @private
140
*/
141
goog.crypt.Sha2.prototype.computeChunk_ = function() {
142
var chunk = this.chunk_;
143
goog.asserts.assert(chunk.length == this.blockSize);
144
var rounds = 64;
145
146
// Divide the chunk into 16 32-bit-words.
147
var w = this.w_;
148
var index = 0;
149
var offset = 0;
150
while (offset < chunk.length) {
151
w[index++] = (chunk[offset] << 24) | (chunk[offset + 1] << 16) |
152
(chunk[offset + 2] << 8) | (chunk[offset + 3]);
153
offset = index * 4;
154
}
155
156
// Extend the w[] array to be the number of rounds.
157
for (var i = 16; i < rounds; i++) {
158
var w_15 = w[i - 15] | 0;
159
var s0 = ((w_15 >>> 7) | (w_15 << 25)) ^ ((w_15 >>> 18) | (w_15 << 14)) ^
160
(w_15 >>> 3);
161
var w_2 = w[i - 2] | 0;
162
var s1 = ((w_2 >>> 17) | (w_2 << 15)) ^ ((w_2 >>> 19) | (w_2 << 13)) ^
163
(w_2 >>> 10);
164
165
// As a performance optimization, construct the sum a pair at a time
166
// with casting to integer (bitwise OR) to eliminate unnecessary
167
// double<->integer conversions.
168
var partialSum1 = ((w[i - 16] | 0) + s0) | 0;
169
var partialSum2 = ((w[i - 7] | 0) + s1) | 0;
170
w[i] = (partialSum1 + partialSum2) | 0;
171
}
172
173
var a = this.hash_[0] | 0;
174
var b = this.hash_[1] | 0;
175
var c = this.hash_[2] | 0;
176
var d = this.hash_[3] | 0;
177
var e = this.hash_[4] | 0;
178
var f = this.hash_[5] | 0;
179
var g = this.hash_[6] | 0;
180
var h = this.hash_[7] | 0;
181
for (var i = 0; i < rounds; i++) {
182
var S0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^
183
((a >>> 22) | (a << 10));
184
var maj = ((a & b) ^ (a & c) ^ (b & c));
185
var t2 = (S0 + maj) | 0;
186
var S1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^
187
((e >>> 25) | (e << 7));
188
var ch = ((e & f) ^ ((~e) & g));
189
190
// As a performance optimization, construct the sum a pair at a time
191
// with casting to integer (bitwise OR) to eliminate unnecessary
192
// double<->integer conversions.
193
var partialSum1 = (h + S1) | 0;
194
var partialSum2 = (ch + (goog.crypt.Sha2.Kx_[i] | 0)) | 0;
195
var partialSum3 = (partialSum2 + (w[i] | 0)) | 0;
196
var t1 = (partialSum1 + partialSum3) | 0;
197
198
h = g;
199
g = f;
200
f = e;
201
e = (d + t1) | 0;
202
d = c;
203
c = b;
204
b = a;
205
a = (t1 + t2) | 0;
206
}
207
208
this.hash_[0] = (this.hash_[0] + a) | 0;
209
this.hash_[1] = (this.hash_[1] + b) | 0;
210
this.hash_[2] = (this.hash_[2] + c) | 0;
211
this.hash_[3] = (this.hash_[3] + d) | 0;
212
this.hash_[4] = (this.hash_[4] + e) | 0;
213
this.hash_[5] = (this.hash_[5] + f) | 0;
214
this.hash_[6] = (this.hash_[6] + g) | 0;
215
this.hash_[7] = (this.hash_[7] + h) | 0;
216
};
217
218
219
/** @override */
220
goog.crypt.Sha2.prototype.update = function(message, opt_length) {
221
if (!goog.isDef(opt_length)) {
222
opt_length = message.length;
223
}
224
// Process the message from left to right up to |opt_length| bytes.
225
// When we get a 512-bit chunk, compute the hash of it and reset
226
// this.chunk_. The message might not be multiple of 512 bits so we
227
// might end up with a chunk that is less than 512 bits. We store
228
// such partial chunk in this.chunk_ and it will be filled up later
229
// in digest().
230
var n = 0;
231
var inChunk = this.inChunk_;
232
233
// The input message could be either byte array of string.
234
if (goog.isString(message)) {
235
while (n < opt_length) {
236
this.chunk_[inChunk++] = message.charCodeAt(n++);
237
if (inChunk == this.blockSize) {
238
this.computeChunk_();
239
inChunk = 0;
240
}
241
}
242
} else if (goog.isArrayLike(message)) {
243
while (n < opt_length) {
244
var b = message[n++];
245
if (!('number' == typeof b && 0 <= b && 255 >= b && b == (b | 0))) {
246
throw Error('message must be a byte array');
247
}
248
this.chunk_[inChunk++] = b;
249
if (inChunk == this.blockSize) {
250
this.computeChunk_();
251
inChunk = 0;
252
}
253
}
254
} else {
255
throw Error('message must be string or array');
256
}
257
258
// Record the current bytes in chunk to support partial update.
259
this.inChunk_ = inChunk;
260
261
// Record total message bytes we have processed so far.
262
this.total_ += opt_length;
263
};
264
265
266
/** @override */
267
goog.crypt.Sha2.prototype.digest = function() {
268
var digest = [];
269
var totalBits = this.total_ * 8;
270
271
// Append pad 0x80 0x00*.
272
if (this.inChunk_ < 56) {
273
this.update(goog.crypt.Sha2.PADDING_, 56 - this.inChunk_);
274
} else {
275
this.update(
276
goog.crypt.Sha2.PADDING_, this.blockSize - (this.inChunk_ - 56));
277
}
278
279
// Append # bits in the 64-bit big-endian format.
280
for (var i = 63; i >= 56; i--) {
281
this.chunk_[i] = totalBits & 255;
282
totalBits /= 256; // Don't use bit-shifting here!
283
}
284
this.computeChunk_();
285
286
// Finally, output the result digest.
287
var n = 0;
288
for (var i = 0; i < this.numHashBlocks_; i++) {
289
for (var j = 24; j >= 0; j -= 8) {
290
digest[n++] = ((this.hash_[i] >> j) & 255);
291
}
292
}
293
return digest;
294
};
295
296
297
/**
298
* Constants used in SHA-2.
299
* @const
300
* @private {!Array<number>}
301
*/
302
goog.crypt.Sha2.K_ = [
303
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
304
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
305
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
306
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
307
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
308
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
309
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
310
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
311
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
312
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
313
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
314
];
315
316
317
/**
318
* Sha2.K as an Int32Array if this JS supports typed arrays; otherwise,
319
* the same array as Sha2.K.
320
*
321
* The compiler cannot remove an Int32Array, even if it is not needed
322
* (There are certain cases where creating an Int32Array is not
323
* side-effect free). Instead, the first time we construct a Sha2
324
* instance, we convert or assign Sha2.K as appropriate.
325
* @private {undefined|!Array<number>|!Int32Array}
326
*/
327
goog.crypt.Sha2.Kx_;
328
329