Wed, 03 Feb 2010 21:02:21 +0000
Match and fire handler callbacks for incoming stanzas
0 | 1 | /* |
2 | * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined | |
3 | * in FIPS PUB 180-1 | |
4 | * Version 2.1a Copyright Paul Johnston 2000 - 2002. | |
5 | * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
6 | * Modifications by Matthew Wild to export functions for CommonJS | |
7 | * Distributed under the BSD License | |
8 | * See http://pajhome.org.uk/crypt/md5 for details. | |
9 | */ | |
10 | ||
11 | /* | |
12 | * Configurable variables. You may need to tweak these to be compatible with | |
13 | * the server-side, but the defaults work in most cases. | |
14 | */ | |
15 | var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ | |
16 | var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ | |
17 | var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ | |
18 | ||
19 | /* | |
20 | * These are the functions you'll usually want to call | |
21 | * They take string arguments and return either hex or base-64 encoded strings | |
22 | */ | |
23 | exports.hex = function (s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} | |
24 | exports.b64 = function (s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} | |
25 | exports.str = function (s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} | |
26 | exports.hex_hmac = function (key, data){ return binb2hex(core_hmac_sha1(key, data));} | |
27 | exports.b64_hmac = function (key, data){ return binb2b64(core_hmac_sha1(key, data));} | |
28 | exports.str_hmac = function (key, data){ return binb2str(core_hmac_sha1(key, data));} | |
29 | ||
30 | /* | |
31 | * Perform a simple self-test to see if the VM is working | |
32 | */ | |
33 | function sha1_vm_test() | |
34 | { | |
35 | return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; | |
36 | } | |
37 | ||
38 | /* | |
39 | * Calculate the SHA-1 of an array of big-endian words, and a bit length | |
40 | */ | |
41 | function core_sha1(x, len) | |
42 | { | |
43 | /* append padding */ | |
44 | x[len >> 5] |= 0x80 << (24 - len % 32); | |
45 | x[((len + 64 >> 9) << 4) + 15] = len; | |
46 | ||
47 | var w = new Array(80); | |
48 | var a = 1732584193; | |
49 | var b = -271733879; | |
50 | var c = -1732584194; | |
51 | var d = 271733878; | |
52 | var e = -1009589776; | |
53 | ||
54 | var i, j, t, olda, oldb, oldc, oldd, olde; | |
55 | for (i = 0; i < x.length; i += 16) | |
56 | { | |
57 | olda = a; | |
58 | oldb = b; | |
59 | oldc = c; | |
60 | oldd = d; | |
61 | olde = e; | |
62 | ||
63 | for (j = 0; j < 80; j++) | |
64 | { | |
65 | if (j < 16) { w[j] = x[i + j]; } | |
66 | else { w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); } | |
67 | t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), | |
68 | safe_add(safe_add(e, w[j]), sha1_kt(j))); | |
69 | e = d; | |
70 | d = c; | |
71 | c = rol(b, 30); | |
72 | b = a; | |
73 | a = t; | |
74 | } | |
75 | ||
76 | a = safe_add(a, olda); | |
77 | b = safe_add(b, oldb); | |
78 | c = safe_add(c, oldc); | |
79 | d = safe_add(d, oldd); | |
80 | e = safe_add(e, olde); | |
81 | } | |
82 | return [a, b, c, d, e]; | |
83 | } | |
84 | ||
85 | /* | |
86 | * Perform the appropriate triplet combination function for the current | |
87 | * iteration | |
88 | */ | |
89 | function sha1_ft(t, b, c, d) | |
90 | { | |
91 | if (t < 20) { return (b & c) | ((~b) & d); } | |
92 | if (t < 40) { return b ^ c ^ d; } | |
93 | if (t < 60) { return (b & c) | (b & d) | (c & d); } | |
94 | return b ^ c ^ d; | |
95 | } | |
96 | ||
97 | /* | |
98 | * Determine the appropriate additive constant for the current iteration | |
99 | */ | |
100 | function sha1_kt(t) | |
101 | { | |
102 | return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : | |
103 | (t < 60) ? -1894007588 : -899497514; | |
104 | } | |
105 | ||
106 | /* | |
107 | * Calculate the HMAC-SHA1 of a key and some data | |
108 | */ | |
109 | function core_hmac_sha1(key, data) | |
110 | { | |
111 | var bkey = str2binb(key); | |
112 | if (bkey.length > 16) { bkey = core_sha1(bkey, key.length * chrsz); } | |
113 | ||
114 | var ipad = new Array(16), opad = new Array(16); | |
115 | for (var i = 0; i < 16; i++) | |
116 | { | |
117 | ipad[i] = bkey[i] ^ 0x36363636; | |
118 | opad[i] = bkey[i] ^ 0x5C5C5C5C; | |
119 | } | |
120 | ||
121 | var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); | |
122 | return core_sha1(opad.concat(hash), 512 + 160); | |
123 | } | |
124 | ||
125 | /* | |
126 | * Add integers, wrapping at 2^32. This uses 16-bit operations internally | |
127 | * to work around bugs in some JS interpreters. | |
128 | */ | |
129 | function safe_add(x, y) | |
130 | { | |
131 | var lsw = (x & 0xFFFF) + (y & 0xFFFF); | |
132 | var msw = (x >> 16) + (y >> 16) + (lsw >> 16); | |
133 | return (msw << 16) | (lsw & 0xFFFF); | |
134 | } | |
135 | ||
136 | /* | |
137 | * Bitwise rotate a 32-bit number to the left. | |
138 | */ | |
139 | function rol(num, cnt) | |
140 | { | |
141 | return (num << cnt) | (num >>> (32 - cnt)); | |
142 | } | |
143 | ||
144 | /* | |
145 | * Convert an 8-bit or 16-bit string to an array of big-endian words | |
146 | * In 8-bit function, characters >255 have their hi-byte silently ignored. | |
147 | */ | |
148 | function str2binb(str) | |
149 | { | |
150 | var bin = []; | |
151 | var mask = (1 << chrsz) - 1; | |
152 | for (var i = 0; i < str.length * chrsz; i += chrsz) | |
153 | { | |
154 | bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); | |
155 | } | |
156 | return bin; | |
157 | } | |
158 | ||
159 | /* | |
160 | * Convert an array of big-endian words to a string | |
161 | */ | |
162 | function binb2str(bin) | |
163 | { | |
164 | var str = ""; | |
165 | var mask = (1 << chrsz) - 1; | |
166 | for (var i = 0; i < bin.length * 32; i += chrsz) | |
167 | { | |
168 | str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); | |
169 | } | |
170 | return str; | |
171 | } | |
172 | ||
173 | /* | |
174 | * Convert an array of big-endian words to a hex string. | |
175 | */ | |
176 | function binb2hex(binarray) | |
177 | { | |
178 | var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; | |
179 | var str = ""; | |
180 | for (var i = 0; i < binarray.length * 4; i++) | |
181 | { | |
182 | str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + | |
183 | hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); | |
184 | } | |
185 | return str; | |
186 | } | |
187 | ||
188 | /* | |
189 | * Convert an array of big-endian words to a base-64 string | |
190 | */ | |
191 | function binb2b64(binarray) | |
192 | { | |
193 | var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
194 | var str = ""; | |
195 | var triplet, j; | |
196 | for (var i = 0; i < binarray.length * 4; i += 3) | |
197 | { | |
198 | triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) | | |
199 | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) | | |
200 | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); | |
201 | for (j = 0; j < 4; j++) | |
202 | { | |
203 | if (i * 8 + j * 6 > binarray.length * 32) { str += b64pad; } | |
204 | else { str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); } | |
205 | } | |
206 | } | |
207 | return str; | |
208 | } |