summaryrefslogtreecommitdiff
path: root/frontend/gamma/js/Clipperz/Crypto/Base.js
Unidiff
Diffstat (limited to 'frontend/gamma/js/Clipperz/Crypto/Base.js') (more/less context) (show whitespace changes)
-rw-r--r--frontend/gamma/js/Clipperz/Crypto/Base.js1852
1 files changed, 1852 insertions, 0 deletions
diff --git a/frontend/gamma/js/Clipperz/Crypto/Base.js b/frontend/gamma/js/Clipperz/Crypto/Base.js
new file mode 100644
index 0000000..b69dcc8
--- a/dev/null
+++ b/frontend/gamma/js/Clipperz/Crypto/Base.js
@@ -0,0 +1,1852 @@
1/*
2
3Copyright 2008-2011 Clipperz Srl
4
5This file is part of Clipperz's Javascript Crypto Library.
6Javascript Crypto Library provides web developers with an extensive
7and efficient set of cryptographic functions. The library aims to
8obtain maximum execution speed while preserving modularity and
9reusability.
10For further information about its features and functionalities please
11refer to http://www.clipperz.com
12
13* Javascript Crypto Library is free software: you can redistribute
14 it and/or modify it under the terms of the GNU Affero General Public
15 License as published by the Free Software Foundation, either version
16 3 of the License, or (at your option) any later version.
17
18* Javascript Crypto Library is distributed in the hope that it will
19 be useful, but WITHOUT ANY WARRANTY; without even the implied
20 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
21 See the GNU Affero General Public License for more details.
22
23* You should have received a copy of the GNU Affero General Public
24 License along with Javascript Crypto Library. If not, see
25 <http://www.gnu.org/licenses/>.
26
27*/
28
29try { if (typeof(Clipperz.Base) == 'undefined') { throw ""; }} catch (e) {
30 throw "Clipperz.Crypto.Base depends on Clipperz.Base!";
31}
32
33if (typeof(Clipperz.Crypto) == 'undefined') { Clipperz.Crypto = {}; }
34if (typeof(Clipperz.Crypto.Base) == 'undefined') { Clipperz.Crypto.Base = {}; }
35
36Clipperz.Crypto.Base.VERSION = "0.1";
37Clipperz.Crypto.Base.NAME = "Clipperz.Crypto.Base";
38
39//#############################################################################
40 //Downloaded on March 30, 2006 from http://anmar.eu.org/projects/jssha2/files/jssha2-0.3.zip (jsSha2/sha256.js)
41//#############################################################################
42
43/* A JavaScript implementation of the Secure Hash Algorithm, SHA-256
44 * Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
45 * Distributed under the BSD License
46 * Some bits taken from Paul Johnston's SHA-1 implementation
47 */
48var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
49function safe_add (x, y) {
50 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
51 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
52 return (msw << 16) | (lsw & 0xFFFF);
53}
54function S (X, n) {return ( X >>> n ) | (X << (32 - n));}
55function R (X, n) {return ( X >>> n );}
56function Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
57function Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
58function Sigma0256(x) {return (S(x, 2) ^ S(x, 13) ^ S(x, 22));}
59function Sigma1256(x) {return (S(x, 6) ^ S(x, 11) ^ S(x, 25));}
60function Gamma0256(x) {return (S(x, 7) ^ S(x, 18) ^ R(x, 3));}
61function Gamma1256(x) {return (S(x, 17) ^ S(x, 19) ^ R(x, 10));}
62function core_sha256 (m, l) {
63 var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2);
64 var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
65 var W = new Array(64);
66 var a, b, c, d, e, f, g, h, i, j;
67 var T1, T2;
68 /* append padding */
69 m[l >> 5] |= 0x80 << (24 - l % 32);
70 m[((l + 64 >> 9) << 4) + 15] = l;
71 for ( var i = 0; i<m.length; i+=16 ) {
72 a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7];
73 for ( var j = 0; j<64; j++) {
74 if (j < 16) W[j] = m[j + i];
75 else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
76 T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
77 T2 = safe_add(Sigma0256(a), Maj(a, b, c));
78 h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2);
79 }
80 HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]); HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]);
81 }
82 return HASH;
83}
84function str2binb (str) {
85 var bin = Array();
86 var mask = (1 << chrsz) - 1;
87 for(var i = 0; i < str.length * chrsz; i += chrsz)
88 bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
89 return bin;
90}
91function binb2hex (binarray) {
92 var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
93 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
94 var str = "";
95 for (var i = 0; i < binarray.length * 4; i++) {
96 str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
97 }
98 return str;
99}
100function hex_sha256(s){return binb2hex(core_sha256(str2binb(s),s.length * chrsz));}
101
102
103
104//#############################################################################
105 //Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (entropy.js)
106//#############################################################################
107
108 // Entropy collection utilities
109
110 /*Start by declaring static storage and initialise
111 the entropy vector from the time we come through
112 here. */
113
114 var entropyData = new Array(); // Collected entropy data
115 var edlen = 0; // Keyboard array data length
116
117 addEntropyTime(); // Start entropy collection with page load time
118 ce(); // Roll milliseconds into initial entropy
119
120 //Add a byte to the entropy vector
121
122 function addEntropyByte(b) {
123 entropyData[edlen++] = b;
124 }
125
126 /*Capture entropy. When the user presses a key or performs
127 various other events for which we can request
128 notification, add the time in 255ths of a second to the
129 entropyData array. The name of the function is short
130 so it doesn't bloat the form object declarations in
131 which it appears in various "onXXX" events. */
132
133 function ce() {
134 addEntropyByte(Math.floor((((new Date).getMilliseconds()) * 255) / 999));
135 }
136
137 //Add a 32 bit quantity to the entropy vector
138
139 function addEntropy32(w) {
140 var i;
141
142 for (i = 0; i < 4; i++) {
143 addEntropyByte(w & 0xFF);
144 w >>= 8;
145 }
146 }
147
148 /*Add the current time and date (milliseconds since the epoch,
149 truncated to 32 bits) to the entropy vector. */
150
151 function addEntropyTime() {
152 addEntropy32((new Date()).getTime());
153 }
154
155 /* Start collection of entropy from mouse movements. The
156 argument specifies the number of entropy items to be
157 obtained from mouse motion, after which mouse motion
158 will be ignored. Note that you can re-enable mouse
159 motion collection at any time if not already underway. */
160
161 var mouseMotionCollect = 0;
162 var oldMoveHandler; // For saving and restoring mouse move handler in IE4
163
164 function mouseMotionEntropy(maxsamp) {
165 if (mouseMotionCollect <= 0) {
166 mouseMotionCollect = maxsamp;
167 if ((document.implementation.hasFeature("Events", "2.0")) &&
168 document.addEventListener) {
169 // Browser supports Document Object Model (DOM) 2 events
170 document.addEventListener("mousemove", mouseMoveEntropy, false);
171 } else {
172 if (document.attachEvent) {
173 // Internet Explorer 5 and above event model
174 document.attachEvent("onmousemove", mouseMoveEntropy);
175 } else {
176 //Internet Explorer 4 event model
177 oldMoveHandler = document.onmousemove;
178 document.onmousemove = mouseMoveEntropy;
179 }
180 }
181//dump("Mouse enable", mouseMotionCollect);
182 }
183 }
184
185 /*Collect entropy from mouse motion events. Note that
186 this is craftily coded to work with either DOM2 or Internet
187 Explorer style events. Note that we don't use every successive
188 mouse movement event. Instead, we XOR the three bytes collected
189 from the mouse and use that to determine how many subsequent
190 mouse movements we ignore before capturing the next one. */
191
192 var mouseEntropyTime = 0; // Delay counter for mouse entropy collection
193
194 function mouseMoveEntropy(e) {
195 if (!e) {
196 e = window.event; // Internet Explorer event model
197 }
198 if (mouseMotionCollect > 0) {
199 if (mouseEntropyTime-- <= 0) {
200 addEntropyByte(e.screenX & 0xFF);
201 addEntropyByte(e.screenY & 0xFF);
202 ce();
203 mouseMotionCollect--;
204 mouseEntropyTime = (entropyData[edlen - 3] ^ entropyData[edlen - 2] ^
205 entropyData[edlen - 1]) % 19;
206//dump("Mouse Move", byteArrayToHex(entropyData.slice(-3)));
207 }
208 if (mouseMotionCollect <= 0) {
209 if (document.removeEventListener) {
210 document.removeEventListener("mousemove", mouseMoveEntropy, false);
211 } else if (document.detachEvent) {
212 document.detachEvent("onmousemove", mouseMoveEntropy);
213 } else {
214 document.onmousemove = oldMoveHandler;
215 }
216//dump("Spung!", 0);
217 }
218 }
219 }
220
221 /*Compute a 32 byte key value from the entropy vector.
222 We compute the value by taking the MD5 sum of the even
223 and odd bytes respectively of the entropy vector, then
224 concatenating the two MD5 sums. */
225
226 function keyFromEntropy() {
227 var i, k = new Array(32);
228
229 if (edlen == 0) {
230 alert("Blooie! Entropy vector void at call to keyFromEntropy.");
231 }
232//dump("Entropy bytes", edlen);
233
234 md5_init();
235 for (i = 0; i < edlen; i += 2) {
236 md5_update(entropyData[i]);
237 }
238 md5_finish();
239 for (i = 0; i < 16; i++) {
240 k[i] = digestBits[i];
241 }
242
243 md5_init();
244 for (i = 1; i < edlen; i += 2) {
245 md5_update(entropyData[i]);
246 }
247 md5_finish();
248 for (i = 0; i < 16; i++) {
249 k[i + 16] = digestBits[i];
250 }
251
252//dump("keyFromEntropy", byteArrayToHex(k));
253 return k;
254 }
255
256//#############################################################################
257 //Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (aesprng.js)
258//#############################################################################
259
260
261 // AES based pseudorandom number generator
262
263 /* Constructor. Called with an array of 32 byte (0-255) values
264 containing the initial seed. */
265
266 function AESprng(seed) {
267 this.key = new Array();
268 this.key = seed;
269 this.itext = hexToByteArray("9F489613248148F9C27945C6AE62EECA3E3367BB14064E4E6DC67A9F28AB3BD1");
270 this.nbytes = 0; // Bytes left in buffer
271
272 this.next = AESprng_next;
273 this.nextbits = AESprng_nextbits;
274 this.nextInt = AESprng_nextInt;
275 this.round = AESprng_round;
276
277 /* Encrypt the initial text with the seed key
278 three times, feeding the output of the encryption
279 back into the key for the next round. */
280
281 bsb = blockSizeInBits;
282 blockSizeInBits = 256;
283 var i, ct;
284 for (i = 0; i < 3; i++) {
285 this.key = rijndaelEncrypt(this.itext, this.key, "ECB");
286 }
287
288 /* Now make between one and four additional
289 key-feedback rounds, with the number determined
290 by bits from the result of the first three
291 rounds. */
292
293 var n = 1 + (this.key[3] & 2) + (this.key[9] & 1);
294 for (i = 0; i < n; i++) {
295 this.key = rijndaelEncrypt(this.itext, this.key, "ECB");
296 }
297 blockSizeInBits = bsb;
298 }
299
300 function AESprng_round() {
301 bsb = blockSizeInBits;
302 blockSizeInBits = 256;
303 this.key = rijndaelEncrypt(this.itext, this.key, "ECB");
304 this.nbytes = 32;
305 blockSizeInBits = bsb;
306 }
307
308 //Return next byte from the generator
309
310 function AESprng_next() {
311 if (this.nbytes <= 0) {
312 this.round();
313 }
314 return(this.key[--this.nbytes]);
315 }
316
317 //Return n bit integer value (up to maximum integer size)
318
319 function AESprng_nextbits(n) {
320 var i, w = 0, nbytes = Math.floor((n + 7) / 8);
321
322 for (i = 0; i < nbytes; i++) {
323 w = (w << 8) | this.next();
324 }
325 return w & ((1 << n) - 1);
326 }
327
328 // Return integer between 0 and n inclusive
329
330 function AESprng_nextInt(n) {
331 var p = 1, nb = 0;
332
333 // Determine smallest p, 2^p > n
334 // nb = log_2 p
335
336 while (n >= p) {
337 p <<= 1;
338 nb++;
339 }
340 p--;
341
342 /* Generate values from 0 through n by first generating
343 values v from 0 to (2^p)-1, then discarding any results v > n.
344 For the rationale behind this (and why taking
345 values mod (n + 1) is biased toward smaller values, see
346 Ferguson and Schneier, "Practical Cryptography",
347 ISBN 0-471-22357-3, section 10.8). */
348
349 while (true) {
350 var v = this.nextbits(nb) & p;
351
352 if (v <= n) {
353 return v;
354 }
355 }
356 }
357
358//#############################################################################
359 //Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (md5.js)
360//#############################################################################
361
362/*
363 * md5.jvs 1.0b 27/06/96
364 *
365 * Javascript implementation of the RSA Data Security, Inc. MD5
366 * Message-Digest Algorithm.
367 *
368 * Copyright (c) 1996 Henri Torgemane. All Rights Reserved.
369 *
370 * Permission to use, copy, modify, and distribute this software
371 * and its documentation for any purposes and without
372 * fee is hereby granted provided that this copyright notice
373 * appears in all copies.
374 *
375 * Of course, this soft is provided "as is" without express or implied
376 * warranty of any kind.
377
378 This version contains some trivial reformatting modifications
379 by John Walker.
380
381 */
382
383function array(n) {
384 for (i = 0; i < n; i++) {
385 this[i] = 0;
386 }
387 this.length = n;
388}
389
390/* Some basic logical functions had to be rewritten because of a bug in
391 * Javascript.. Just try to compute 0xffffffff >> 4 with it..
392 * Of course, these functions are slower than the original would be, but
393 * at least, they work!
394 */
395
396function integer(n) {
397 return n % (0xffffffff + 1);
398}
399
400function shr(a, b) {
401 a = integer(a);
402 b = integer(b);
403 if (a - 0x80000000 >= 0) {
404 a = a % 0x80000000;
405 a >>= b;
406 a += 0x40000000 >> (b - 1);
407 } else {
408 a >>= b;
409 }
410 return a;
411}
412
413function shl1(a) {
414 a = a % 0x80000000;
415 if (a & 0x40000000 == 0x40000000) {
416 a -= 0x40000000;
417 a *= 2;
418 a += 0x80000000;
419 } else {
420 a *= 2;
421 }
422 return a;
423}
424
425function shl(a, b) {
426 a = integer(a);
427 b = integer(b);
428 for (var i = 0; i < b; i++) {
429 a = shl1(a);
430 }
431 return a;
432}
433
434function and(a, b) {
435 a = integer(a);
436 b = integer(b);
437 var t1 = a - 0x80000000;
438 var t2 = b - 0x80000000;
439 if (t1 >= 0) {
440 if (t2 >= 0) {
441 return ((t1 & t2) + 0x80000000);
442 } else {
443 return (t1 & b);
444 }
445 } else {
446 if (t2 >= 0) {
447 return (a & t2);
448 } else {
449 return (a & b);
450 }
451 }
452}
453
454function or(a, b) {
455 a = integer(a);
456 b = integer(b);
457 var t1 = a - 0x80000000;
458 var t2 = b - 0x80000000;
459 if (t1 >= 0) {
460 if (t2 >= 0) {
461 return ((t1 | t2) + 0x80000000);
462 } else {
463 return ((t1 | b) + 0x80000000);
464 }
465 } else {
466 if (t2 >= 0) {
467 return ((a | t2) + 0x80000000);
468 } else {
469 return (a | b);
470 }
471 }
472}
473
474function xor(a, b) {
475 a = integer(a);
476 b = integer(b);
477 var t1 = a - 0x80000000;
478 var t2 = b - 0x80000000;
479 if (t1 >= 0) {
480 if (t2 >= 0) {
481 return (t1 ^ t2);
482 } else {
483 return ((t1 ^ b) + 0x80000000);
484 }
485 } else {
486 if (t2 >= 0) {
487 return ((a ^ t2) + 0x80000000);
488 } else {
489 return (a ^ b);
490 }
491 }
492}
493
494function not(a) {
495 a = integer(a);
496 return 0xffffffff - a;
497}
498
499/* Here begin the real algorithm */
500
501var state = new array(4);
502var count = new array(2);
503 count[0] = 0;
504 count[1] = 0;
505var buffer = new array(64);
506var transformBuffer = new array(16);
507var digestBits = new array(16);
508
509var S11 = 7;
510var S12 = 12;
511var S13 = 17;
512var S14 = 22;
513var S21 = 5;
514var S22 = 9;
515var S23 = 14;
516var S24 = 20;
517var S31 = 4;
518var S32 = 11;
519var S33 = 16;
520var S34 = 23;
521var S41 = 6;
522var S42 = 10;
523var S43 = 15;
524var S44 = 21;
525
526function F(x, y, z) {
527 return or(and(x, y), and(not(x), z));
528}
529
530function G(x, y, z) {
531 return or(and(x, z), and(y, not(z)));
532}
533
534function H(x, y, z) {
535 return xor(xor(x, y), z);
536}
537
538function I(x, y, z) {
539 return xor(y ,or(x , not(z)));
540}
541
542function rotateLeft(a, n) {
543 return or(shl(a, n), (shr(a, (32 - n))));
544}
545
546function FF(a, b, c, d, x, s, ac) {
547 a = a + F(b, c, d) + x + ac;
548 a = rotateLeft(a, s);
549 a = a + b;
550 return a;
551}
552
553function GG(a, b, c, d, x, s, ac) {
554 a = a + G(b, c, d) + x + ac;
555 a = rotateLeft(a, s);
556 a = a + b;
557 return a;
558}
559
560function HH(a, b, c, d, x, s, ac) {
561 a = a + H(b, c, d) + x + ac;
562 a = rotateLeft(a, s);
563 a = a + b;
564 return a;
565}
566
567function II(a, b, c, d, x, s, ac) {
568 a = a + I(b, c, d) + x + ac;
569 a = rotateLeft(a, s);
570 a = a + b;
571 return a;
572}
573
574function transform(buf, offset) {
575 var a = 0, b = 0, c = 0, d = 0;
576 var x = transformBuffer;
577
578 a = state[0];
579 b = state[1];
580 c = state[2];
581 d = state[3];
582
583 for (i = 0; i < 16; i++) {
584 x[i] = and(buf[i * 4 + offset], 0xFF);
585 for (j = 1; j < 4; j++) {
586 x[i] += shl(and(buf[i * 4 + j + offset] ,0xFF), j * 8);
587 }
588 }
589
590 /* Round 1 */
591 a = FF( a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
592 d = FF( d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
593 c = FF( c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
594 b = FF( b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
595 a = FF( a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
596 d = FF( d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
597 c = FF( c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
598 b = FF( b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
599 a = FF( a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
600 d = FF( d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
601 c = FF( c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
602 b = FF( b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
603 a = FF( a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
604 d = FF( d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
605 c = FF( c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
606 b = FF( b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
607
608 /* Round 2 */
609 a = GG( a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
610 d = GG( d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
611 c = GG( c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
612 b = GG( b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
613 a = GG( a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
614 d = GG( d, a, b, c, x[10], S22, 0x2441453); /* 22 */
615 c = GG( c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
616 b = GG( b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
617 a = GG( a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
618 d = GG( d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
619 c = GG( c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
620 b = GG( b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
621 a = GG( a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
622 d = GG( d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
623 c = GG( c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
624 b = GG( b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
625
626 /* Round 3 */
627 a = HH( a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
628 d = HH( d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
629 c = HH( c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
630 b = HH( b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
631 a = HH( a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
632 d = HH( d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
633 c = HH( c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
634 b = HH( b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
635 a = HH( a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
636 d = HH( d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
637 c = HH( c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
638 b = HH( b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
639 a = HH( a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
640 d = HH( d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
641 c = HH( c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
642 b = HH( b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
643
644 /* Round 4 */
645 a = II( a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
646 d = II( d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
647 c = II( c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
648 b = II( b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
649 a = II( a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
650 d = II( d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
651 c = II( c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
652 b = II( b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
653 a = II( a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
654 d = II( d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
655 c = II( c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
656 b = II( b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
657 a = II( a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
658 d = II( d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
659 c = II( c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
660 b = II( b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
661
662 state[0] += a;
663 state[1] += b;
664 state[2] += c;
665 state[3] += d;
666
667}
668
669function md5_init() {
670 count[0] = count[1] = 0;
671 state[0] = 0x67452301;
672 state[1] = 0xefcdab89;
673 state[2] = 0x98badcfe;
674 state[3] = 0x10325476;
675 for (i = 0; i < digestBits.length; i++) {
676 digestBits[i] = 0;
677 }
678}
679
680function md5_update(b) {
681 var index, i;
682
683 index = and(shr(count[0],3) , 0x3F);
684 if (count[0] < 0xFFFFFFFF - 7) {
685 count[0] += 8;
686 } else {
687 count[1]++;
688 count[0] -= 0xFFFFFFFF + 1;
689 count[0] += 8;
690 }
691 buffer[index] = and(b, 0xff);
692 if (index >= 63) {
693 transform(buffer, 0);
694 }
695}
696
697function md5_finish() {
698 var bits = new array(8);
699 var padding;
700 var i = 0, index = 0, padLen = 0;
701
702 for (i = 0; i < 4; i++) {
703 bits[i] = and(shr(count[0], (i * 8)), 0xFF);
704 }
705 for (i = 0; i < 4; i++) {
706 bits[i + 4] = and(shr(count[1], (i * 8)), 0xFF);
707 }
708 index = and(shr(count[0], 3), 0x3F);
709 padLen = (index < 56) ? (56 - index) : (120 - index);
710 padding = new array(64);
711 padding[0] = 0x80;
712 for (i = 0; i < padLen; i++) {
713 md5_update(padding[i]);
714 }
715 for (i = 0; i < 8; i++) {
716 md5_update(bits[i]);
717 }
718
719 for (i = 0; i < 4; i++) {
720 for (j = 0; j < 4; j++) {
721 digestBits[i * 4 + j] = and(shr(state[i], (j * 8)) , 0xFF);
722 }
723 }
724}
725
726/* End of the MD5 algorithm */
727
728//#############################################################################
729 //Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (aes.js)
730//#############################################################################
731
732
733/* rijndael.js Rijndael Reference Implementation
734
735 This is a modified version of the software described below,
736 produced in September 2003 by John Walker for use in the
737 JavsScrypt browser-based encryption package. The principal
738 changes are replacing the original getRandomBytes function with
739 one which calls our pseudorandom generator (which must
740 be instantiated and seeded before the first call on getRandomBytes),
741 and changing keySizeInBits to 256. Some code not required by the
742 JavsScrypt application has been commented out. Please see
743 http://www.fourmilab.ch/javascrypt/ for further information on
744 JavaScrypt.
745
746 The following is the original copyright and application
747 information.
748
749 Copyright (c) 2001 Fritz Schneider
750
751 This software is provided as-is, without express or implied warranty.
752 Permission to use, copy, modify, distribute or sell this software, with or
753 without fee, for any purpose and by any individual or organization, is hereby
754 granted, provided that the above copyright notice and this paragraph appear
755 in all copies. Distribution as a part of an application or binary must
756 include the above copyright notice in the documentation and/or other materials
757 provided with the application or distribution.
758
759 As the above disclaimer notes, you are free to use this code however you
760 want. However, I would request that you send me an email
761 (fritz /at/ cs /dot/ ucsd /dot/ edu) to say hi if you find this code useful
762 or instructional. Seeing that people are using the code acts as
763 encouragement for me to continue development. If you *really* want to thank
764 me you can buy the book I wrote with Thomas Powell, _JavaScript:
765 _The_Complete_Reference_ :)
766
767 This code is an UNOPTIMIZED REFERENCE implementation of Rijndael.
768 If there is sufficient interest I can write an optimized (word-based,
769 table-driven) version, although you might want to consider using a
770 compiled language if speed is critical to your application. As it stands,
771 one run of the monte carlo test (10,000 encryptions) can take up to
772 several minutes, depending upon your processor. You shouldn't expect more
773 than a few kilobytes per second in throughput.
774
775 Also note that there is very little error checking in these functions.
776 Doing proper error checking is always a good idea, but the ideal
777 implementation (using the instanceof operator and exceptions) requires
778 IE5+/NS6+, and I've chosen to implement this code so that it is compatible
779 with IE4/NS4.
780
781 And finally, because JavaScript doesn't have an explicit byte/char data
782 type (although JavaScript 2.0 most likely will), when I refer to "byte"
783 in this code I generally mean "32 bit integer with value in the interval
784 [0,255]" which I treat as a byte.
785
786 See http://www-cse.ucsd.edu/~fritz/rijndael.html for more documentation
787 of the (very simple) API provided by this code.
788
789 Fritz Schneider
790 fritz at cs.ucsd.edu
791
792*/
793
794
795// Rijndael parameters -- Valid values are 128, 192, or 256
796
797var keySizeInBits = 256;
798var blockSizeInBits = 128;
799
800//
801// Note: in the following code the two dimensional arrays are indexed as
802// you would probably expect, as array[row][column]. The state arrays
803// are 2d arrays of the form state[4][Nb].
804
805
806// The number of rounds for the cipher, indexed by [Nk][Nb]
807var roundsArray = [ ,,,,[,,,,10,, 12,, 14],,
808 [,,,,12,, 12,, 14],,
809 [,,,,14,, 14,, 14] ];
810
811// The number of bytes to shift by in shiftRow, indexed by [Nb][row]
812var shiftOffsets = [ ,,,,[,1, 2, 3],,[,1, 2, 3],,[,1, 3, 4] ];
813
814// The round constants used in subkey expansion
815var Rcon = [
8160x01, 0x02, 0x04, 0x08, 0x10, 0x20,
8170x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
8180xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,
8190x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4,
8200xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91 ];
821
822// Precomputed lookup table for the SBox
823var SBox = [
824 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171,
825118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164,
826114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113,
827216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226,
828235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214,
829179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203,
830190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69,
831249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245,
832188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68,
83323, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42,
834144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73,
835 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109,
836141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37,
837 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62,
838181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225,
839248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223,
840140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187,
841 22 ];
842
843// Precomputed lookup table for the inverse SBox
844var SBoxInverse = [
845 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215,
846251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222,
847233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66,
848250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73,
849109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92,
850204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21,
851 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247,
852228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2,
853193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220,
854234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173,
855 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29,
856 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75,
857198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168,
858 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81,
859127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160,
860224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97,
861 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12,
862125 ];
863
864// This method circularly shifts the array left by the number of elements
865// given in its parameter. It returns the resulting array and is used for
866// the ShiftRow step. Note that shift() and push() could be used for a more
867// elegant solution, but they require IE5.5+, so I chose to do it manually.
868
869function cyclicShiftLeft(theArray, positions) {
870 var temp = theArray.slice(0, positions);
871 theArray = theArray.slice(positions).concat(temp);
872 return theArray;
873}
874
875// Cipher parameters ... do not change these
876var Nk = keySizeInBits / 32;
877var Nb = blockSizeInBits / 32;
878var Nr = roundsArray[Nk][Nb];
879
880// Multiplies the element "poly" of GF(2^8) by x. See the Rijndael spec.
881
882function xtime(poly) {
883 poly <<= 1;
884 return ((poly & 0x100) ? (poly ^ 0x11B) : (poly));
885}
886
887// Multiplies the two elements of GF(2^8) together and returns the result.
888// See the Rijndael spec, but should be straightforward: for each power of
889// the indeterminant that has a 1 coefficient in x, add y times that power
890// to the result. x and y should be bytes representing elements of GF(2^8)
891
892function mult_GF256(x, y) {
893 var bit, result = 0;
894
895 for (bit = 1; bit < 256; bit *= 2, y = xtime(y)) {
896 if (x & bit)
897 result ^= y;
898 }
899 return result;
900}
901
902// Performs the substitution step of the cipher. State is the 2d array of
903// state information (see spec) and direction is string indicating whether
904// we are performing the forward substitution ("encrypt") or inverse
905// substitution (anything else)
906
907function byteSub(state, direction) {
908 var S;
909 if (direction == "encrypt") // Point S to the SBox we're using
910 S = SBox;
911 else
912 S = SBoxInverse;
913 for (var i = 0; i < 4; i++) // Substitute for every byte in state
914 for (var j = 0; j < Nb; j++)
915 state[i][j] = S[state[i][j]];
916}
917
918// Performs the row shifting step of the cipher.
919
920function shiftRow(state, direction) {
921 for (var i=1; i<4; i++) // Row 0 never shifts
922 if (direction == "encrypt")
923 state[i] = cyclicShiftLeft(state[i], shiftOffsets[Nb][i]);
924 else
925 state[i] = cyclicShiftLeft(state[i], Nb - shiftOffsets[Nb][i]);
926
927}
928
929// Performs the column mixing step of the cipher. Most of these steps can
930// be combined into table lookups on 32bit values (at least for encryption)
931// to greatly increase the speed.
932
933function mixColumn(state, direction) {
934 var b = []; // Result of matrix multiplications
935 for (var j = 0; j < Nb; j++) { // Go through each column...
936 for (var i = 0; i < 4; i++) { // and for each row in the column...
937 if (direction == "encrypt")
938 b[i] = mult_GF256(state[i][j], 2) ^ // perform mixing
939 mult_GF256(state[(i+1)%4][j], 3) ^
940 state[(i+2)%4][j] ^
941 state[(i+3)%4][j];
942 else
943 b[i] = mult_GF256(state[i][j], 0xE) ^
944 mult_GF256(state[(i+1)%4][j], 0xB) ^
945 mult_GF256(state[(i+2)%4][j], 0xD) ^
946 mult_GF256(state[(i+3)%4][j], 9);
947 }
948 for (var i = 0; i < 4; i++) // Place result back into column
949 state[i][j] = b[i];
950 }
951}
952
953// Adds the current round key to the state information. Straightforward.
954
955function addRoundKey(state, roundKey) {
956 for (var j = 0; j < Nb; j++) { // Step through columns...
957 state[0][j] ^= (roundKey[j] & 0xFF); // and XOR
958 state[1][j] ^= ((roundKey[j]>>8) & 0xFF);
959 state[2][j] ^= ((roundKey[j]>>16) & 0xFF);
960 state[3][j] ^= ((roundKey[j]>>24) & 0xFF);
961 }
962}
963
964// This function creates the expanded key from the input (128/192/256-bit)
965// key. The parameter key is an array of bytes holding the value of the key.
966// The returned value is an array whose elements are the 32-bit words that
967// make up the expanded key.
968
969function keyExpansion(key) {
970 var expandedKey = new Array();
971 var temp;
972
973 // in case the key size or parameters were changed...
974 Nk = keySizeInBits / 32;
975 Nb = blockSizeInBits / 32;
976 Nr = roundsArray[Nk][Nb];
977
978 for (var j=0; j < Nk; j++) // Fill in input key first
979 expandedKey[j] =
980 (key[4*j]) | (key[4*j+1]<<8) | (key[4*j+2]<<16) | (key[4*j+3]<<24);
981
982 // Now walk down the rest of the array filling in expanded key bytes as
983 // per Rijndael's spec
984 for (j = Nk; j < Nb * (Nr + 1); j++) { // For each word of expanded key
985 temp = expandedKey[j - 1];
986 if (j % Nk == 0)
987 temp = ( (SBox[(temp>>8) & 0xFF]) |
988 (SBox[(temp>>16) & 0xFF]<<8) |
989 (SBox[(temp>>24) & 0xFF]<<16) |
990 (SBox[temp & 0xFF]<<24) ) ^ Rcon[Math.floor(j / Nk) - 1];
991 else if (Nk > 6 && j % Nk == 4)
992 temp = (SBox[(temp>>24) & 0xFF]<<24) |
993 (SBox[(temp>>16) & 0xFF]<<16) |
994 (SBox[(temp>>8) & 0xFF]<<8) |
995 (SBox[temp & 0xFF]);
996 expandedKey[j] = expandedKey[j-Nk] ^ temp;
997 }
998 return expandedKey;
999}
1000
1001// Rijndael's round functions...
1002
1003function Round(state, roundKey) {
1004 byteSub(state, "encrypt");
1005 shiftRow(state, "encrypt");
1006 mixColumn(state, "encrypt");
1007 addRoundKey(state, roundKey);
1008}
1009
1010function InverseRound(state, roundKey) {
1011 addRoundKey(state, roundKey);
1012 mixColumn(state, "decrypt");
1013 shiftRow(state, "decrypt");
1014 byteSub(state, "decrypt");
1015}
1016
1017function FinalRound(state, roundKey) {
1018 byteSub(state, "encrypt");
1019 shiftRow(state, "encrypt");
1020 addRoundKey(state, roundKey);
1021}
1022
1023function InverseFinalRound(state, roundKey){
1024 addRoundKey(state, roundKey);
1025 shiftRow(state, "decrypt");
1026 byteSub(state, "decrypt");
1027}
1028
1029// encrypt is the basic encryption function. It takes parameters
1030// block, an array of bytes representing a plaintext block, and expandedKey,
1031// an array of words representing the expanded key previously returned by
1032// keyExpansion(). The ciphertext block is returned as an array of bytes.
1033
1034function encrypt(block, expandedKey) {
1035 var i;
1036 if (!block || block.length*8 != blockSizeInBits)
1037 return;
1038 if (!expandedKey)
1039 return;
1040
1041 block = packBytes(block);
1042 addRoundKey(block, expandedKey);
1043 for (i=1; i<Nr; i++)
1044 Round(block, expandedKey.slice(Nb*i, Nb*(i+1)));
1045 FinalRound(block, expandedKey.slice(Nb*Nr));
1046 return unpackBytes(block);
1047}
1048
1049// decrypt is the basic decryption function. It takes parameters
1050// block, an array of bytes representing a ciphertext block, and expandedKey,
1051// an array of words representing the expanded key previously returned by
1052// keyExpansion(). The decrypted block is returned as an array of bytes.
1053
1054function decrypt(block, expandedKey) {
1055 var i;
1056 if (!block || block.length*8 != blockSizeInBits)
1057 return;
1058 if (!expandedKey)
1059 return;
1060
1061 block = packBytes(block);
1062 InverseFinalRound(block, expandedKey.slice(Nb*Nr));
1063 for (i = Nr - 1; i>0; i--)
1064 InverseRound(block, expandedKey.slice(Nb*i, Nb*(i+1)));
1065 addRoundKey(block, expandedKey);
1066 return unpackBytes(block);
1067}
1068
1069/* !NEEDED
1070// This method takes a byte array (byteArray) and converts it to a string by
1071// applying String.fromCharCode() to each value and concatenating the result.
1072// The resulting string is returned. Note that this function SKIPS zero bytes
1073// under the assumption that they are padding added in formatPlaintext().
1074// Obviously, do not invoke this method on raw data that can contain zero
1075// bytes. It is really only appropriate for printable ASCII/Latin-1
1076// values. Roll your own function for more robust functionality :)
1077
1078function byteArrayToString(byteArray) {
1079 var result = "";
1080 for(var i=0; i<byteArray.length; i++)
1081 if (byteArray[i] != 0)
1082 result += String.fromCharCode(byteArray[i]);
1083 return result;
1084}
1085*/
1086
1087// This function takes an array of bytes (byteArray) and converts them
1088// to a hexadecimal string. Array element 0 is found at the beginning of
1089// the resulting string, high nibble first. Consecutive elements follow
1090// similarly, for example [16, 255] --> "10ff". The function returns a
1091// string.
1092
1093function byteArrayToHex(byteArray) {
1094 var result = "";
1095 if (!byteArray)
1096 return;
1097 for (var i=0; i<byteArray.length; i++)
1098 result += ((byteArray[i]<16) ? "0" : "") + byteArray[i].toString(16);
1099
1100 return result;
1101}
1102
1103// This function converts a string containing hexadecimal digits to an
1104// array of bytes. The resulting byte array is filled in the order the
1105// values occur in the string, for example "10FF" --> [16, 255]. This
1106// function returns an array.
1107
1108function hexToByteArray(hexString) {
1109 var byteArray = [];
1110 if (hexString.length % 2) // must have even length
1111 return;
1112 if (hexString.indexOf("0x") == 0 || hexString.indexOf("0X") == 0)
1113 hexString = hexString.substring(2);
1114 for (var i = 0; i<hexString.length; i += 2)
1115 byteArray[Math.floor(i/2)] = parseInt(hexString.slice(i, i+2), 16);
1116 return byteArray;
1117}
1118
1119// This function packs an array of bytes into the four row form defined by
1120// Rijndael. It assumes the length of the array of bytes is divisible by
1121// four. Bytes are filled in according to the Rijndael spec (starting with
1122// column 0, row 0 to 3). This function returns a 2d array.
1123
1124function packBytes(octets) {
1125 var state = new Array();
1126 if (!octets || octets.length % 4)
1127 return;
1128
1129 state[0] = new Array(); state[1] = new Array();
1130 state[2] = new Array(); state[3] = new Array();
1131 for (var j=0; j<octets.length; j+= 4) {
1132 state[0][j/4] = octets[j];
1133 state[1][j/4] = octets[j+1];
1134 state[2][j/4] = octets[j+2];
1135 state[3][j/4] = octets[j+3];
1136 }
1137 return state;
1138}
1139
1140// This function unpacks an array of bytes from the four row format preferred
1141// by Rijndael into a single 1d array of bytes. It assumes the input "packed"
1142// is a packed array. Bytes are filled in according to the Rijndael spec.
1143// This function returns a 1d array of bytes.
1144
1145function unpackBytes(packed) {
1146 var result = new Array();
1147 for (var j=0; j<packed[0].length; j++) {
1148 result[result.length] = packed[0][j];
1149 result[result.length] = packed[1][j];
1150 result[result.length] = packed[2][j];
1151 result[result.length] = packed[3][j];
1152 }
1153 return result;
1154}
1155
1156// This function takes a prospective plaintext (string or array of bytes)
1157// and pads it with pseudorandom bytes if its length is not a multiple of the block
1158// size. If plaintext is a string, it is converted to an array of bytes
1159// in the process. The type checking can be made much nicer using the
1160// instanceof operator, but this operator is not available until IE5.0 so I
1161// chose to use the heuristic below.
1162
1163function formatPlaintext(plaintext) {
1164 var bpb = blockSizeInBits / 8; // bytes per block
1165 var fillWithRandomBits;
1166 var i;
1167
1168 // if primitive string or String instance
1169 if ((!((typeof plaintext == "object") &&
1170 ((typeof (plaintext[0])) == "number"))) &&
1171 ((typeof plaintext == "string") || plaintext.indexOf))
1172 {
1173 plaintext = plaintext.split("");
1174 // Unicode issues here (ignoring high byte)
1175 for (i=0; i<plaintext.length; i++) {
1176 plaintext[i] = plaintext[i].charCodeAt(0) & 0xFF;
1177 }
1178 }
1179
1180 i = plaintext.length % bpb;
1181 if (i > 0) {
1182//alert("adding " + (bpb - 1) + " bytes");
1183 // plaintext = plaintext.concat(getRandomBytes(bpb - i));
1184 {
1185 varpaddingBytes;
1186 var ii,cc;
1187
1188 paddingBytes = new Array();
1189 cc = bpb - i;
1190 for (ii=0; ii<cc; ii++) {
1191 paddingBytes[ii] = cc;
1192 }
1193
1194//is("cc", cc);
1195//is(getRandomBytes(bpb - i) + "", paddingBytes + "");
1196 plaintext = plaintext.concat(paddingBytes);
1197 }
1198 }
1199
1200 return plaintext;
1201}
1202
1203// Returns an array containing "howMany" random bytes.
1204
1205function getRandomBytes(howMany) {
1206 var i, bytes = new Array();
1207
1208//alert("getting some random bytes");
1209 for (i = 0; i < howMany; i++) {
1210 bytes[i] = prng.nextInt(255);
1211 }
1212 return bytes;
1213}
1214
1215// rijndaelEncrypt(plaintext, key, mode)
1216// Encrypts the plaintext using the given key and in the given mode.
1217// The parameter "plaintext" can either be a string or an array of bytes.
1218// The parameter "key" must be an array of key bytes. If you have a hex
1219// string representing the key, invoke hexToByteArray() on it to convert it
1220// to an array of bytes. The third parameter "mode" is a string indicating
1221// the encryption mode to use, either "ECB" or "CBC". If the parameter is
1222// omitted, ECB is assumed.
1223//
1224// An array of bytes representing the cihpertext is returned. To convert
1225// this array to hex, invoke byteArrayToHex() on it.
1226
1227function rijndaelEncrypt(plaintext, key, mode) {
1228 var expandedKey, i, aBlock;
1229 var bpb = blockSizeInBits / 8; // bytes per block
1230 var ct; // ciphertext
1231
1232 if (!plaintext || !key)
1233 return;
1234 if (key.length*8 != keySizeInBits)
1235 return;
1236 if (mode == "CBC") {
1237 ct = getRandomBytes(bpb); // get IV
1238//dump("IV", byteArrayToHex(ct));
1239 } else {
1240 mode = "ECB";
1241 ct = new Array();
1242 }
1243
1244 // convert plaintext to byte array and pad with zeros if necessary.
1245 plaintext = formatPlaintext(plaintext);
1246
1247 expandedKey = keyExpansion(key);
1248
1249 for (var block = 0; block < plaintext.length / bpb; block++) {
1250 aBlock = plaintext.slice(block * bpb, (block + 1) * bpb);
1251 if (mode == "CBC") {
1252 for (var i = 0; i < bpb; i++) {
1253 aBlock[i] ^= ct[(block * bpb) + i];
1254 }
1255 }
1256 ct = ct.concat(encrypt(aBlock, expandedKey));
1257 }
1258
1259 return ct;
1260}
1261
1262// rijndaelDecrypt(ciphertext, key, mode)
1263// Decrypts the using the given key and mode. The parameter "ciphertext"
1264// must be an array of bytes. The parameter "key" must be an array of key
1265// bytes. If you have a hex string representing the ciphertext or key,
1266// invoke hexToByteArray() on it to convert it to an array of bytes. The
1267// parameter "mode" is a string, either "CBC" or "ECB".
1268//
1269// An array of bytes representing the plaintext is returned. To convert
1270// this array to a hex string, invoke byteArrayToHex() on it. To convert it
1271// to a string of characters, you can use byteArrayToString().
1272
1273function rijndaelDecrypt(ciphertext, key, mode) {
1274 var expandedKey;
1275 var bpb = blockSizeInBits / 8; // bytes per block
1276 var pt = new Array(); // plaintext array
1277 var aBlock; // a decrypted block
1278 var block; // current block number
1279
1280 if (!ciphertext || !key || typeof ciphertext == "string")
1281 return;
1282 if (key.length*8 != keySizeInBits)
1283 return;
1284 if (!mode) {
1285 mode = "ECB"; // assume ECB if mode omitted
1286 }
1287
1288 expandedKey = keyExpansion(key);
1289
1290 // work backwards to accomodate CBC mode
1291 for (block=(ciphertext.length / bpb)-1; block>0; block--) {
1292 aBlock =
1293 decrypt(ciphertext.slice(block*bpb,(block+1)*bpb), expandedKey);
1294 if (mode == "CBC")
1295 for (var i=0; i<bpb; i++)
1296 pt[(block-1)*bpb + i] = aBlock[i] ^ ciphertext[(block-1)*bpb + i];
1297 else
1298 pt = aBlock.concat(pt);
1299 }
1300
1301 // do last block if ECB (skips the IV in CBC)
1302 if (mode == "ECB")
1303 pt = decrypt(ciphertext.slice(0, bpb), expandedKey).concat(pt);
1304
1305 return pt;
1306}
1307
1308//#############################################################################
1309 //Downloaded on March 30, 2006 from http://www.fourmilab.ch/javascrypt/javascrypt.zip (utf-8.js)
1310//#############################################################################
1311
1312
1313 /*Encoding and decoding of Unicode character strings as
1314 UTF-8 byte streams. */
1315
1316 //UNICODE_TO_UTF8 -- Encode Unicode argument string as UTF-8 return value
1317
1318 function unicode_to_utf8(s) {
1319 var utf8 = "";
1320
1321 for (var n = 0; n < s.length; n++) {
1322 var c = s.charCodeAt(n);
1323
1324 if (c <= 0x7F) {
1325 // 0x00 - 0x7F: Emit as single byte, unchanged
1326 utf8 += String.fromCharCode(c);
1327 } else if ((c >= 0x80) && (c <= 0x7FF)) {
1328 // 0x80 - 0x7FF: Output as two byte code, 0xC0 in first byte
1329 // 0x80 in second byte
1330 utf8 += String.fromCharCode((c >> 6) | 0xC0);
1331 utf8 += String.fromCharCode((c & 0x3F) | 0x80);
1332 } else {
1333 // 0x800 - 0xFFFF: Output as three bytes, 0xE0 in first byte
1334 // 0x80 in second byte
1335 // 0x80 in third byte
1336 utf8 += String.fromCharCode((c >> 12) | 0xE0);
1337 utf8 += String.fromCharCode(((c >> 6) & 0x3F) | 0x80);
1338 utf8 += String.fromCharCode((c & 0x3F) | 0x80);
1339 }
1340 }
1341 return utf8;
1342 }
1343
1344 //UTF8_TO_UNICODE -- Decode UTF-8 argument into Unicode string return value
1345
1346 function utf8_to_unicode(utf8) {
1347 var s = "", i = 0, b1, b2, b2;
1348
1349 while (i < utf8.length) {
1350 b1 = utf8.charCodeAt(i);
1351 if (b1 < 0x80) { // One byte code: 0x00 0x7F
1352 s += String.fromCharCode(b1);
1353 i++;
1354 } else if((b1 >= 0xC0) && (b1 < 0xE0)) {// Two byte code: 0x80 - 0x7FF
1355 b2 = utf8.charCodeAt(i + 1);
1356 s += String.fromCharCode(((b1 & 0x1F) << 6) | (b2 & 0x3F));
1357 i += 2;
1358 } else { // Three byte code: 0x800 - 0xFFFF
1359 b2 = utf8.charCodeAt(i + 1);
1360 b3 = utf8.charCodeAt(i + 2);
1361 s += String.fromCharCode(((b1 & 0xF) << 12) |
1362 ((b2 & 0x3F) << 6) |
1363 (b3 & 0x3F));
1364 i += 3;
1365 }
1366 }
1367 return s;
1368 }
1369
1370 /*ENCODE_UTF8 -- Encode string as UTF8 only if it contains
1371 a character of 0x9D (Unicode OPERATING
1372 SYSTEM COMMAND) or a character greater
1373 than 0xFF. This permits all strings
1374 consisting exclusively of 8 bit
1375 graphic characters to be encoded as
1376 themselves. We choose 0x9D as the sentinel
1377 character as opposed to one of the more
1378 logical PRIVATE USE characters because 0x9D
1379 is not overloaded by the regrettable
1380 "Windows-1252" character set. Now such characters
1381 don't belong in JavaScript strings, but you never
1382 know what somebody is going to paste into a
1383 text box, so this choice keeps Windows-encoded
1384 strings from bloating to UTF-8 encoding. */
1385
1386 function encode_utf8(s) {
1387 var i, necessary = false;
1388
1389 for (i = 0; i < s.length; i++) {
1390 if ((s.charCodeAt(i) == 0x9D) ||
1391 (s.charCodeAt(i) > 0xFF)) {
1392 necessary = true;
1393 break;
1394 }
1395 }
1396 if (!necessary) {
1397 return s;
1398 }
1399 return String.fromCharCode(0x9D) + unicode_to_utf8(s);
1400 }
1401
1402 /* DECODE_UTF8 -- Decode a string encoded with encode_utf8
1403 above. If the string begins with the
1404 sentinel character 0x9D (OPERATING
1405 SYSTEM COMMAND), then we decode the
1406 balance as a UTF-8 stream. Otherwise,
1407 the string is output unchanged, as
1408 it's guaranteed to contain only 8 bit
1409 characters excluding 0x9D. */
1410
1411 function decode_utf8(s) {
1412 if ((s.length > 0) && (s.charCodeAt(0) == 0x9D)) {
1413 return utf8_to_unicode(s.substring(1));
1414 }
1415 return s;
1416 }
1417
1418
1419//#############################################################################
1420 //Downloaded on April 26, 2006 from http://pajhome.org.uk/crypt/md5/md5.js
1421//#############################################################################
1422
1423/*
1424 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
1425 * Digest Algorithm, as defined in RFC 1321.
1426 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
1427 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
1428 * Distributed under the BSD License
1429 * See http://pajhome.org.uk/crypt/md5 for more info.
1430 */
1431
1432/*
1433 * Configurable variables. You may need to tweak these to be compatible with
1434 * the server-side, but the defaults work in most cases.
1435 */
1436var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
1437var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
1438var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
1439
1440/*
1441 * These are the functions you'll usually want to call
1442 * They take string arguments and return either hex or base-64 encoded strings
1443 */
1444function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
1445function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
1446function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
1447function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
1448function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
1449function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
1450
1451/*
1452 * Perform a simple self-test to see if the VM is working
1453 */
1454function md5_vm_test()
1455{
1456 return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
1457}
1458
1459/*
1460 * Calculate the MD5 of an array of little-endian words, and a bit length
1461 */
1462function core_md5(x, len)
1463{
1464 /* append padding */
1465 x[len >> 5] |= 0x80 << ((len) % 32);
1466 x[(((len + 64) >>> 9) << 4) + 14] = len;
1467
1468 var a = 1732584193;
1469 var b = -271733879;
1470 var c = -1732584194;
1471 var d = 271733878;
1472
1473 for(var i = 0; i < x.length; i += 16)
1474 {
1475 var olda = a;
1476 var oldb = b;
1477 var oldc = c;
1478 var oldd = d;
1479
1480 a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
1481 d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
1482 c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
1483 b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
1484 a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
1485 d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
1486 c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
1487 b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
1488 a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
1489 d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
1490 c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
1491 b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
1492 a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
1493 d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
1494 c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
1495 b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
1496
1497 a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
1498 d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
1499 c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
1500 b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
1501 a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
1502 d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
1503 c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
1504 b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
1505 a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
1506 d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
1507 c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
1508 b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
1509 a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
1510 d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
1511 c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
1512 b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
1513
1514 a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
1515 d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
1516 c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
1517 b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
1518 a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
1519 d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
1520 c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
1521 b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
1522 a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
1523 d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
1524 c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
1525 b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
1526 a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
1527 d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
1528 c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
1529 b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
1530
1531 a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
1532 d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
1533 c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
1534 b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
1535 a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
1536 d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
1537 c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
1538 b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
1539 a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
1540 d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
1541 c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
1542 b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
1543 a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
1544 d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
1545 c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
1546 b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
1547
1548 a = safe_add(a, olda);
1549 b = safe_add(b, oldb);
1550 c = safe_add(c, oldc);
1551 d = safe_add(d, oldd);
1552 }
1553 return Array(a, b, c, d);
1554
1555}
1556
1557/*
1558 * These functions implement the four basic operations the algorithm uses.
1559 */
1560function md5_cmn(q, a, b, x, s, t)
1561{
1562 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
1563}
1564function md5_ff(a, b, c, d, x, s, t)
1565{
1566 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
1567}
1568function md5_gg(a, b, c, d, x, s, t)
1569{
1570 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
1571}
1572function md5_hh(a, b, c, d, x, s, t)
1573{
1574 return md5_cmn(b ^ c ^ d, a, b, x, s, t);
1575}
1576function md5_ii(a, b, c, d, x, s, t)
1577{
1578 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
1579}
1580
1581/*
1582 * Calculate the HMAC-MD5, of a key and some data
1583 */
1584function core_hmac_md5(key, data)
1585{
1586 var bkey = str2binl(key);
1587 if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
1588
1589 var ipad = Array(16), opad = Array(16);
1590 for(var i = 0; i < 16; i++)
1591 {
1592 ipad[i] = bkey[i] ^ 0x36363636;
1593 opad[i] = bkey[i] ^ 0x5C5C5C5C;
1594 }
1595
1596 var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
1597 return core_md5(opad.concat(hash), 512 + 128);
1598}
1599
1600/*
1601 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
1602 * to work around bugs in some JS interpreters.
1603 */
1604function safe_add(x, y)
1605{
1606 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
1607 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
1608 return (msw << 16) | (lsw & 0xFFFF);
1609}
1610
1611/*
1612 * Bitwise rotate a 32-bit number to the left.
1613 */
1614function bit_rol(num, cnt)
1615{
1616 return (num << cnt) | (num >>> (32 - cnt));
1617}
1618
1619/*
1620 * Convert a string to an array of little-endian words
1621 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
1622 */
1623function str2binl(str)
1624{
1625 var bin = Array();
1626 var mask = (1 << chrsz) - 1;
1627 for(var i = 0; i < str.length * chrsz; i += chrsz)
1628 bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
1629 return bin;
1630}
1631
1632/*
1633 * Convert an array of little-endian words to a string
1634 */
1635function binl2str(bin)
1636{
1637 var str = "";
1638 var mask = (1 << chrsz) - 1;
1639 for(var i = 0; i < bin.length * 32; i += chrsz)
1640 str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
1641 return str;
1642}
1643
1644/*
1645 * Convert an array of little-endian words to a hex string.
1646 */
1647function binl2hex(binarray)
1648{
1649 var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
1650 var str = "";
1651 for(var i = 0; i < binarray.length * 4; i++)
1652 {
1653 str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
1654 hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
1655 }
1656 return str;
1657}
1658
1659/*
1660 * Convert an array of little-endian words to a base-64 string
1661 */
1662function binl2b64(binarray)
1663{
1664 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1665 var str = "";
1666 for(var i = 0; i < binarray.length * 4; i += 3)
1667 {
1668 var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
1669 | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
1670 | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
1671 for(var j = 0; j < 4; j++)
1672 {
1673 if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
1674 else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
1675 }
1676 }
1677 return str;
1678}
1679
1680
1681//#############################################################################
1682//#############################################################################
1683//#############################################################################
1684
1685
1686
1687MochiKit.Base.update(Clipperz.Crypto.Base, {
1688
1689 '__repr__': function () {
1690 return "[" + this.NAME + " " + this.VERSION + "]";
1691 },
1692
1693 'toString': function () {
1694 return this.__repr__();
1695 },
1696
1697 //-----------------------------------------------------------------------------
1698
1699 'encryptUsingSecretKey': function (aKey, aMessage) {
1700//Clipperz.Profile.start("Clipperz.Crypto.Base.encryptUsingSecretKey");
1701 var result;
1702 var plaintext;
1703 varheader;
1704 varkey;
1705
1706 key = hexToByteArray(Clipperz.Crypto.Base.computeHashValue(aKey));
1707
1708 addEntropyTime();
1709 prng = new AESprng(keyFromEntropy());
1710
1711 plaintext = encode_utf8(aMessage);
1712
1713 header = Clipperz.Base.byteArrayToString(hexToByteArray(Clipperz.Crypto.Base.computeMD5HashValue(plaintext)));
1714
1715 // Add message length in bytes to header
1716 i = plaintext.length;
1717 header += String.fromCharCode(i >>> 24);
1718 header += String.fromCharCode(i >>> 16);
1719 header += String.fromCharCode(i >>> 8);
1720 header += String.fromCharCode(i & 0xFF);
1721
1722 //The format of the actual message passed to rijndaelEncrypt
1723 //is:
1724 //
1725 // Bytes Content
1726 // 0-15 MD5 signature of plaintext
1727 // 16-19 Length of plaintext, big-endian order
1728 // 20-end Plaintext
1729 //
1730 //Note that this message will be padded with zero bytes
1731 //to an integral number of AES blocks (blockSizeInBits / 8).
1732 //This does not include the initial vector for CBC
1733 //encryption, which is added internally by rijndaelEncrypt.
1734 result = byteArrayToHex(rijndaelEncrypt(header + plaintext, key, "CBC"));
1735
1736 delete prng;
1737
1738//Clipperz.Profile.stop("Clipperz.Crypto.Base.encryptUsingSecretKey");
1739 return result;
1740 },
1741
1742 //.............................................................................
1743
1744 'decryptUsingSecretKey': function (aKey, aMessage) {
1745//Clipperz.Profile.start("Clipperz.Crypto.Base.decryptUsingSecretKey");
1746 varkey;
1747 var decryptedText;
1748 vartextLength;
1749 varheader;
1750 varheaderDigest;
1751 var plaintext;
1752 var i;
1753
1754 key = hexToByteArray(Clipperz.Crypto.Base.computeHashValue(aKey));
1755
1756 decryptedText = rijndaelDecrypt(hexToByteArray(aMessage), key, "CBC");
1757
1758 header = decryptedText.slice(0, 20);
1759 decryptedText = decryptedText.slice(20);
1760
1761 headerDigest = byteArrayToHex(header.slice(0,16));
1762 textLength = (header[16] << 24) | (header[17] << 16) | (header[18] << 8) | header[19];
1763
1764 if ((textLength < 0) || (textLength > decryptedText.length)) {
1765 // jslog.warning("Message (length " + decryptedText.length + ") truncated. " + textLength + " characters expected.");
1766 //Try to sauve qui peut by setting length to entire message
1767 textLength = decryptedText.length;
1768 }
1769
1770 plainText = "";
1771
1772 for (i=0; i<textLength; i++) {
1773 plainText += String.fromCharCode(decryptedText[i]);
1774 }
1775
1776 if (Clipperz.Crypto.Base.computeMD5HashValue(plainText) != headerDigest) {
1777 // jslog.warning("Message corrupted. Checksum of decrypted message does not match.");
1778 throw Clipperz.Crypto.Base.exception.CorruptedMessage;
1779 // throw new Error("Message corrupted. Checksum of decrypted message does not match. Parsed result: " + decode_utf8(plainText));
1780 }
1781
1782 // That's it; plug plaintext into the result field
1783
1784 result = decode_utf8(plainText);
1785
1786//Clipperz.Profile.stop("Clipperz.Crypto.Base.decryptUsingSecretKey");
1787 return result;
1788 },
1789
1790 //-----------------------------------------------------------------------------
1791
1792 'computeHashValue': function (aMessage) {
1793//Clipperz.Profile.start("Clipperz.Crypto.Base.computeHashValue");
1794 varresult;
1795
1796 result = hex_sha256(aMessage);
1797//Clipperz.Profile.stop("Clipperz.Crypto.Base.computeHashValue");
1798
1799 return result;
1800 },
1801
1802 //.........................................................................
1803
1804 'computeMD5HashValue': function (aMessage) {
1805 varresult;
1806//Clipperz.Profile.start("Clipperz.Crypto.Base.computeMD5HashValue");
1807 result = hex_md5(aMessage);
1808//Clipperz.Profile.stop("Clipperz.Crypto.Base.computeMD5HashValue");
1809
1810 return result;
1811 },
1812
1813 //-----------------------------------------------------------------------------
1814
1815 'generateRandomSeed': function () {
1816//Clipperz.Profile.start("Clipperz.Crypto.Base.generateRandomSeed");
1817 varresult;
1818 var seed;
1819 var prng;
1820 var charA;
1821 var i;
1822
1823 addEntropyTime();
1824
1825 seed = keyFromEntropy();
1826 prng = new AESprng(seed);
1827
1828 result = "";
1829 charA = ("A").charCodeAt(0);
1830
1831 for (i = 0; i < 64; i++) {
1832 result += String.fromCharCode(charA + prng.nextInt(25));
1833 }
1834
1835 delete prng;
1836
1837 result = Clipperz.Crypto.Base.computeHashValue(result);
1838
1839//Clipperz.Profile.stop("Clipperz.Crypto.Base.generateRandomSeed");
1840 return result;
1841 },
1842
1843 //-----------------------------------------------------------------------------
1844
1845 'exception': {
1846 'CorruptedMessage': new MochiKit.Base.NamedError("Clipperz.Crypto.Base.exception.CorruptedMessage")
1847 },
1848
1849 //.........................................................................
1850 __syntaxFix__: "syntax fix"
1851});
1852