1
+ /*
2
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
3
+ * in FIPS 180-1
4
+ * Version 2.2 Copyright Paul Johnston 2000 - 2009.
5
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
6
+ * Distributed under the BSD License
7
+ * See http://pajhome.org.uk/crypt/md5 for details.
8
+ */
9
+
10
+ /*
11
+ * Configurable variables. You may need to tweak these to be compatible with
12
+ * the server-side, but the defaults work in most cases.
13
+ */
14
+ var hexcase = 1 ; /* hex output format. 0 - lowercase; 1 - uppercase */
15
+ var b64pad = "=" ; /* base-64 pad character. "=" for strict RFC compliance */
16
+
17
+ /*
18
+ * These are the functions you'll usually want to call
19
+ * They take string arguments and return either hex or base-64 encoded strings
20
+ */
21
+ function hex_sha1 ( s ) { return rstr2hex ( rstr_sha1 ( str2rstr_utf8 ( s ) ) ) ; }
22
+ function b64_sha1 ( s ) { return rstr2b64 ( rstr_sha1 ( str2rstr_utf8 ( s ) ) ) ; }
23
+ function any_sha1 ( s , e ) { return rstr2any ( rstr_sha1 ( str2rstr_utf8 ( s ) ) , e ) ; }
24
+ function hex_hmac_sha1 ( k , d )
25
+ { return rstr2hex ( rstr_hmac_sha1 ( str2rstr_utf8 ( k ) , str2rstr_utf8 ( d ) ) ) ; }
26
+ function b64_hmac_sha1 ( k , d )
27
+ { return rstr2b64 ( rstr_hmac_sha1 ( str2rstr_utf8 ( k ) , str2rstr_utf8 ( d ) ) ) ; }
28
+ function any_hmac_sha1 ( k , d , e )
29
+ { return rstr2any ( rstr_hmac_sha1 ( str2rstr_utf8 ( k ) , str2rstr_utf8 ( d ) ) , e ) ; }
30
+
31
+ /*
32
+ * Perform a simple self-test to see if the VM is working
33
+ */
34
+ function sha1_vm_test ( )
35
+ {
36
+ return hex_sha1 ( "abc" ) . toLowerCase ( ) == "a9993e364706816aba3e25717850c26c9cd0d89d" ;
37
+ }
38
+
39
+ /*
40
+ * Calculate the SHA1 of a raw string
41
+ */
42
+ function rstr_sha1 ( s )
43
+ {
44
+ return binb2rstr ( binb_sha1 ( rstr2binb ( s ) , s . length * 8 ) ) ;
45
+ }
46
+
47
+ /*
48
+ * Calculate the HMAC-SHA1 of a key and some data (raw strings)
49
+ */
50
+ function rstr_hmac_sha1 ( key , data )
51
+ {
52
+ var bkey = rstr2binb ( key ) ;
53
+ if ( bkey . length > 16 ) bkey = binb_sha1 ( bkey , key . length * 8 ) ;
54
+
55
+ var ipad = Array ( 16 ) , opad = Array ( 16 ) ;
56
+ for ( var i = 0 ; i < 16 ; i ++ )
57
+ {
58
+ ipad [ i ] = bkey [ i ] ^ 0x36363636 ;
59
+ opad [ i ] = bkey [ i ] ^ 0x5C5C5C5C ;
60
+ }
61
+
62
+ var hash = binb_sha1 ( ipad . concat ( rstr2binb ( data ) ) , 512 + data . length * 8 ) ;
63
+ return binb2rstr ( binb_sha1 ( opad . concat ( hash ) , 512 + 160 ) ) ;
64
+ }
65
+
66
+ /*
67
+ * Convert a raw string to a hex string
68
+ */
69
+ function rstr2hex ( input )
70
+ {
71
+ try { hexcase } catch ( e ) { hexcase = 0 ; }
72
+ var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef" ;
73
+ var output = "" ;
74
+ var x ;
75
+ for ( var i = 0 ; i < input . length ; i ++ )
76
+ {
77
+ x = input . charCodeAt ( i ) ;
78
+ output += hex_tab . charAt ( ( x >>> 4 ) & 0x0F )
79
+ + hex_tab . charAt ( x & 0x0F ) ;
80
+ }
81
+ return output ;
82
+ }
83
+
84
+ /*
85
+ * Convert a raw string to a base-64 string
86
+ */
87
+ function rstr2b64 ( input )
88
+ {
89
+ try { b64pad } catch ( e ) { b64pad = '' ; }
90
+ var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" ;
91
+ var output = "" ;
92
+ var len = input . length ;
93
+ for ( var i = 0 ; i < len ; i += 3 )
94
+ {
95
+ var triplet = ( input . charCodeAt ( i ) << 16 )
96
+ | ( i + 1 < len ? input . charCodeAt ( i + 1 ) << 8 : 0 )
97
+ | ( i + 2 < len ? input . charCodeAt ( i + 2 ) : 0 ) ;
98
+ for ( var j = 0 ; j < 4 ; j ++ )
99
+ {
100
+ if ( i * 8 + j * 6 > input . length * 8 ) output += b64pad ;
101
+ else output += tab . charAt ( ( triplet >>> 6 * ( 3 - j ) ) & 0x3F ) ;
102
+ }
103
+ }
104
+ return output ;
105
+ }
106
+
107
+ /*
108
+ * Convert a raw string to an arbitrary string encoding
109
+ */
110
+ function rstr2any ( input , encoding )
111
+ {
112
+ var divisor = encoding . length ;
113
+ var remainders = Array ( ) ;
114
+ var i , q , x , quotient ;
115
+
116
+ /* Convert to an array of 16-bit big-endian values, forming the dividend */
117
+ var dividend = Array ( Math . ceil ( input . length / 2 ) ) ;
118
+ for ( i = 0 ; i < dividend . length ; i ++ )
119
+ {
120
+ dividend [ i ] = ( input . charCodeAt ( i * 2 ) << 8 ) | input . charCodeAt ( i * 2 + 1 ) ;
121
+ }
122
+
123
+ /*
124
+ * Repeatedly perform a long division. The binary array forms the dividend,
125
+ * the length of the encoding is the divisor. Once computed, the quotient
126
+ * forms the dividend for the next step. We stop when the dividend is zero.
127
+ * All remainders are stored for later use.
128
+ */
129
+ while ( dividend . length > 0 )
130
+ {
131
+ quotient = Array ( ) ;
132
+ x = 0 ;
133
+ for ( i = 0 ; i < dividend . length ; i ++ )
134
+ {
135
+ x = ( x << 16 ) + dividend [ i ] ;
136
+ q = Math . floor ( x / divisor ) ;
137
+ x -= q * divisor ;
138
+ if ( quotient . length > 0 || q > 0 )
139
+ quotient [ quotient . length ] = q ;
140
+ }
141
+ remainders [ remainders . length ] = x ;
142
+ dividend = quotient ;
143
+ }
144
+
145
+ /* Convert the remainders to the output string */
146
+ var output = "" ;
147
+ for ( i = remainders . length - 1 ; i >= 0 ; i -- )
148
+ output += encoding . charAt ( remainders [ i ] ) ;
149
+
150
+ /* Append leading zero equivalents */
151
+ var full_length = Math . ceil ( input . length * 8 /
152
+ ( Math . log ( encoding . length ) / Math . log ( 2 ) ) )
153
+ for ( i = output . length ; i < full_length ; i ++ )
154
+ output = encoding [ 0 ] + output ;
155
+
156
+ return output ;
157
+ }
158
+
159
+ /*
160
+ * Encode a string as utf-8.
161
+ * For efficiency, this assumes the input is valid utf-16.
162
+ */
163
+ function str2rstr_utf8 ( input )
164
+ {
165
+ var output = "" ;
166
+ var i = - 1 ;
167
+ var x , y ;
168
+
169
+ while ( ++ i < input . length )
170
+ {
171
+ /* Decode utf-16 surrogate pairs */
172
+ x = input . charCodeAt ( i ) ;
173
+ y = i + 1 < input . length ? input . charCodeAt ( i + 1 ) : 0 ;
174
+ if ( 0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF )
175
+ {
176
+ x = 0x10000 + ( ( x & 0x03FF ) << 10 ) + ( y & 0x03FF ) ;
177
+ i ++ ;
178
+ }
179
+
180
+ /* Encode output as utf-8 */
181
+ if ( x <= 0x7F )
182
+ output += String . fromCharCode ( x ) ;
183
+ else if ( x <= 0x7FF )
184
+ output += String . fromCharCode ( 0xC0 | ( ( x >>> 6 ) & 0x1F ) ,
185
+ 0x80 | ( x & 0x3F ) ) ;
186
+ else if ( x <= 0xFFFF )
187
+ output += String . fromCharCode ( 0xE0 | ( ( x >>> 12 ) & 0x0F ) ,
188
+ 0x80 | ( ( x >>> 6 ) & 0x3F ) ,
189
+ 0x80 | ( x & 0x3F ) ) ;
190
+ else if ( x <= 0x1FFFFF )
191
+ output += String . fromCharCode ( 0xF0 | ( ( x >>> 18 ) & 0x07 ) ,
192
+ 0x80 | ( ( x >>> 12 ) & 0x3F ) ,
193
+ 0x80 | ( ( x >>> 6 ) & 0x3F ) ,
194
+ 0x80 | ( x & 0x3F ) ) ;
195
+ }
196
+ return output ;
197
+ }
198
+
199
+ /*
200
+ * Encode a string as utf-16
201
+ */
202
+ function str2rstr_utf16le ( input )
203
+ {
204
+ var output = "" ;
205
+ for ( var i = 0 ; i < input . length ; i ++ )
206
+ output += String . fromCharCode ( input . charCodeAt ( i ) & 0xFF ,
207
+ ( input . charCodeAt ( i ) >>> 8 ) & 0xFF ) ;
208
+ return output ;
209
+ }
210
+
211
+ function str2rstr_utf16be ( input )
212
+ {
213
+ var output = "" ;
214
+ for ( var i = 0 ; i < input . length ; i ++ )
215
+ output += String . fromCharCode ( ( input . charCodeAt ( i ) >>> 8 ) & 0xFF ,
216
+ input . charCodeAt ( i ) & 0xFF ) ;
217
+ return output ;
218
+ }
219
+
220
+ /*
221
+ * Convert a raw string to an array of big-endian words
222
+ * Characters >255 have their high-byte silently ignored.
223
+ */
224
+ function rstr2binb ( input )
225
+ {
226
+ var output = Array ( input . length >> 2 ) ;
227
+ for ( var i = 0 ; i < output . length ; i ++ )
228
+ output [ i ] = 0 ;
229
+ for ( var i = 0 ; i < input . length * 8 ; i += 8 )
230
+ output [ i >> 5 ] |= ( input . charCodeAt ( i / 8 ) & 0xFF ) << ( 24 - i % 32 ) ;
231
+ return output ;
232
+ }
233
+
234
+ /*
235
+ * Convert an array of big-endian words to a string
236
+ */
237
+ function binb2rstr ( input )
238
+ {
239
+ var output = "" ;
240
+ for ( var i = 0 ; i < input . length * 32 ; i += 8 )
241
+ output += String . fromCharCode ( ( input [ i >> 5 ] >>> ( 24 - i % 32 ) ) & 0xFF ) ;
242
+ return output ;
243
+ }
244
+
245
+ /*
246
+ * Calculate the SHA-1 of an array of big-endian words, and a bit length
247
+ */
248
+ function binb_sha1 ( x , len )
249
+ {
250
+ /* append padding */
251
+ x [ len >> 5 ] |= 0x80 << ( 24 - len % 32 ) ;
252
+ x [ ( ( len + 64 >> 9 ) << 4 ) + 15 ] = len ;
253
+
254
+ var w = Array ( 80 ) ;
255
+ var a = 1732584193 ;
256
+ var b = - 271733879 ;
257
+ var c = - 1732584194 ;
258
+ var d = 271733878 ;
259
+ var e = - 1009589776 ;
260
+
261
+ for ( var i = 0 ; i < x . length ; i += 16 )
262
+ {
263
+ var olda = a ;
264
+ var oldb = b ;
265
+ var oldc = c ;
266
+ var oldd = d ;
267
+ var olde = e ;
268
+
269
+ for ( var j = 0 ; j < 80 ; j ++ )
270
+ {
271
+ if ( j < 16 ) w [ j ] = x [ i + j ] ;
272
+ else w [ j ] = bit_rol ( w [ j - 3 ] ^ w [ j - 8 ] ^ w [ j - 14 ] ^ w [ j - 16 ] , 1 ) ;
273
+ var t = safe_add ( safe_add ( bit_rol ( a , 5 ) , sha1_ft ( j , b , c , d ) ) ,
274
+ safe_add ( safe_add ( e , w [ j ] ) , sha1_kt ( j ) ) ) ;
275
+ e = d ;
276
+ d = c ;
277
+ c = bit_rol ( b , 30 ) ;
278
+ b = a ;
279
+ a = t ;
280
+ }
281
+
282
+ a = safe_add ( a , olda ) ;
283
+ b = safe_add ( b , oldb ) ;
284
+ c = safe_add ( c , oldc ) ;
285
+ d = safe_add ( d , oldd ) ;
286
+ e = safe_add ( e , olde ) ;
287
+ }
288
+ return Array ( a , b , c , d , e ) ;
289
+
290
+ }
291
+
292
+ /*
293
+ * Perform the appropriate triplet combination function for the current
294
+ * iteration
295
+ */
296
+ function sha1_ft ( t , b , c , d )
297
+ {
298
+ if ( t < 20 ) return ( b & c ) | ( ( ~ b ) & d ) ;
299
+ if ( t < 40 ) return b ^ c ^ d ;
300
+ if ( t < 60 ) return ( b & c ) | ( b & d ) | ( c & d ) ;
301
+ return b ^ c ^ d ;
302
+ }
303
+
304
+ /*
305
+ * Determine the appropriate additive constant for the current iteration
306
+ */
307
+ function sha1_kt ( t )
308
+ {
309
+ return ( t < 20 ) ? 1518500249 : ( t < 40 ) ? 1859775393 :
310
+ ( t < 60 ) ? - 1894007588 : - 899497514 ;
311
+ }
312
+
313
+ /*
314
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally
315
+ * to work around bugs in some JS interpreters.
316
+ */
317
+ function safe_add ( x , y )
318
+ {
319
+ var lsw = ( x & 0xFFFF ) + ( y & 0xFFFF ) ;
320
+ var msw = ( x >> 16 ) + ( y >> 16 ) + ( lsw >> 16 ) ;
321
+ return ( msw << 16 ) | ( lsw & 0xFFFF ) ;
322
+ }
323
+
324
+ /*
325
+ * Bitwise rotate a 32-bit number to the left.
326
+ */
327
+ function bit_rol ( num , cnt )
328
+ {
329
+ return ( num << cnt ) | ( num >>> ( 32 - cnt ) ) ;
330
+ }
331
+
332
+ exports . HMACSHA1 = function ( key , data ) {
333
+ return b64_hmac_sha1 ( key , data ) ;
334
+ }
0 commit comments