Commit | Line | Data |
---|---|---|
e5b254d5 FB |
1 | /*************************************************************************** |
2 | * Copyright (C) 2003-2011 Polytechnique.org * | |
3 | * http://opensource.polytechnique.org/ * | |
4 | * * | |
5 | * This program is free software; you can redistribute it and/or modify * | |
6 | * it under the terms of the GNU General Public License as published by * | |
7 | * the Free Software Foundation; either version 2 of the License, or * | |
8 | * (at your option) any later version. * | |
9 | * * | |
10 | * This program is distributed in the hope that it will be useful, * | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
13 | * GNU General Public License for more details. * | |
14 | * * | |
15 | * You should have received a copy of the GNU General Public License * | |
16 | * along with this program; if not, write to the Free Software * | |
17 | * Foundation, Inc., * | |
18 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * | |
19 | ***************************************************************************/ | |
20 | ||
21 | /* {{{ SHA1 Implementation */ | |
22 | ||
23 | /* | |
24 | * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined | |
25 | * in FIPS PUB 180-1 | |
26 | * Version 2.1a Copyright Paul Johnston 2000 - 2002. | |
27 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
28 | * Distributed under the BSD License | |
29 | * See http://pajhome.org.uk/crypt/md5 for details. | |
30 | */ | |
31 | ||
32 | /* | |
33 | * Configurable variables. You may need to tweak these to be compatible with | |
34 | * the server-side, but the defaults work in most cases. | |
35 | */ | |
36 | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ | |
37 | var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ | |
38 | var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ | |
39 | ||
40 | /* | |
41 | * These are the functions you'll usually want to call | |
42 | * They take string arguments and return either hex or base-64 encoded strings | |
43 | */ | |
44 | function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} | |
45 | function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} | |
46 | function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} | |
47 | function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));} | |
48 | function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));} | |
49 | function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));} | |
50 | ||
51 | /* | |
52 | * Perform a simple self-test to see if the VM is working | |
53 | */ | |
54 | function sha1_vm_test() | |
55 | { | |
56 | return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; | |
57 | } | |
58 | ||
59 | /* | |
60 | * Calculate the SHA-1 of an array of big-endian words, and a bit length | |
61 | */ | |
62 | function core_sha1(x, len) | |
63 | { | |
64 | /* append padding */ | |
65 | x[len >> 5] |= 0x80 << (24 - len % 32); | |
66 | x[((len + 64 >> 9) << 4) + 15] = len; | |
67 | ||
68 | var w = Array(80); | |
69 | var a = 1732584193; | |
70 | var b = -271733879; | |
71 | var c = -1732584194; | |
72 | var d = 271733878; | |
73 | var e = -1009589776; | |
74 | ||
75 | for(var i = 0; i < x.length; i += 16) | |
76 | { | |
77 | var olda = a; | |
78 | var oldb = b; | |
79 | var oldc = c; | |
80 | var oldd = d; | |
81 | var olde = e; | |
82 | ||
83 | for(var j = 0; j < 80; j++) | |
84 | { | |
85 | if(j < 16) w[j] = x[i + j]; | |
86 | else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); | |
87 | var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), | |
88 | safe_add(safe_add(e, w[j]), sha1_kt(j))); | |
89 | e = d; | |
90 | d = c; | |
91 | c = rol(b, 30); | |
92 | b = a; | |
93 | a = t; | |
94 | } | |
95 | ||
96 | a = safe_add(a, olda); | |
97 | b = safe_add(b, oldb); | |
98 | c = safe_add(c, oldc); | |
99 | d = safe_add(d, oldd); | |
100 | e = safe_add(e, olde); | |
101 | } | |
102 | return Array(a, b, c, d, e); | |
103 | ||
104 | } | |
105 | ||
106 | /* | |
107 | * Perform the appropriate triplet combination function for the current | |
108 | * iteration | |
109 | */ | |
110 | function sha1_ft(t, b, c, d) | |
111 | { | |
112 | if(t < 20) return (b & c) | ((~b) & d); | |
113 | if(t < 40) return b ^ c ^ d; | |
114 | if(t < 60) return (b & c) | (b & d) | (c & d); | |
115 | return b ^ c ^ d; | |
116 | } | |
117 | ||
118 | /* | |
119 | * Determine the appropriate additive constant for the current iteration | |
120 | */ | |
121 | function sha1_kt(t) | |
122 | { | |
123 | return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : | |
124 | (t < 60) ? -1894007588 : -899497514; | |
125 | } | |
126 | ||
127 | /* | |
128 | * Calculate the HMAC-SHA1 of a key and some data | |
129 | */ | |
130 | function core_hmac_sha1(key, data) | |
131 | { | |
132 | var bkey = str2binb(key); | |
133 | if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz); | |
134 | ||
135 | var ipad = Array(16), opad = Array(16); | |
136 | for(var i = 0; i < 16; i++) | |
137 | { | |
138 | ipad[i] = bkey[i] ^ 0x36363636; | |
139 | opad[i] = bkey[i] ^ 0x5C5C5C5C; | |
140 | } | |
141 | ||
142 | var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); | |
143 | return core_sha1(opad.concat(hash), 512 + 160); | |
144 | } | |
145 | ||
146 | /* | |
147 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally | |
148 | * to work around bugs in some JS interpreters. | |
149 | */ | |
150 | function safe_add(x, y) | |
151 | { | |
152 | var lsw = (x & 0xFFFF) + (y & 0xFFFF); | |
153 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16); | |
154 | return (msw << 16) | (lsw & 0xFFFF); | |
155 | } | |
156 | ||
157 | /* | |
158 | * Bitwise rotate a 32-bit number to the left. | |
159 | */ | |
160 | function rol(num, cnt) | |
161 | { | |
162 | return (num << cnt) | (num >>> (32 - cnt)); | |
163 | } | |
164 | ||
165 | /* | |
166 | * Convert an 8-bit or 16-bit string to an array of big-endian words | |
167 | * In 8-bit function, characters >255 have their hi-byte silently ignored. | |
168 | */ | |
169 | function str2binb(str) | |
170 | { | |
171 | var bin = Array(); | |
172 | var mask = (1 << chrsz) - 1; | |
173 | for(var i = 0; i < str.length * chrsz; i += chrsz) | |
174 | bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); | |
175 | return bin; | |
176 | } | |
177 | ||
178 | /* | |
179 | * Convert an array of big-endian words to a string | |
180 | */ | |
181 | function binb2str(bin) | |
182 | { | |
183 | var str = ""; | |
184 | var mask = (1 << chrsz) - 1; | |
185 | for(var i = 0; i < bin.length * 32; i += chrsz) | |
186 | str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); | |
187 | return str; | |
188 | } | |
189 | ||
190 | /* | |
191 | * Convert an array of big-endian words to a hex string. | |
192 | */ | |
193 | function binb2hex(binarray) | |
194 | { | |
195 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; | |
196 | var str = ""; | |
197 | for(var i = 0; i < binarray.length * 4; i++) | |
198 | { | |
199 | str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + | |
200 | hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); | |
201 | } | |
202 | return str; | |
203 | } | |
204 | ||
205 | /* | |
206 | * Convert an array of big-endian words to a base-64 string | |
207 | */ | |
208 | function binb2b64(binarray) | |
209 | { | |
210 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
211 | var str = ""; | |
212 | for(var i = 0; i < binarray.length * 4; i += 3) | |
213 | { | |
214 | var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) | |
215 | | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) | |
216 | | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); | |
217 | for(var j = 0; j < 4; j++) | |
218 | { | |
219 | if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; | |
220 | else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); | |
221 | } | |
222 | } | |
223 | return str; | |
224 | } | |
225 | ||
226 | /* }}} */ | |
227 | ||
228 | function hash_encrypt(a) { | |
229 | return hex_sha1(a); | |
230 | } | |
231 | ||
232 | var hexa_h = "0123456789abcdef"; | |
233 | ||
234 | function dechex(a) { | |
235 | return hexa_h.charAt(a); | |
236 | } | |
237 | ||
238 | function hexdec(a) { | |
239 | return hexa_h.indexOf(a); | |
240 | } | |
241 | ||
242 | function hash_xor(a, b) { | |
243 | var c,i,j,k; | |
244 | c = ""; | |
245 | i = a.length; | |
246 | j = b.length; | |
247 | if (i < j) { | |
248 | var d; | |
249 | d = a; a = b; b = d; | |
250 | k = i; i = j; j = k; | |
251 | } | |
252 | for (k = 0; k < j; k++) | |
253 | c += dechex(hexdec(a.charAt(k)) ^ hexdec(b.charAt(k))); | |
254 | for (; k < i; k++) | |
255 | c += a.charAt(k); | |
256 | return c; | |
257 | } | |
a14159bf | 258 | // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: |