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