summaryrefslogtreecommitdiff
path: root/frontend/delta/js/Clipperz/Crypto/AES.js
Unidiff
Diffstat (limited to 'frontend/delta/js/Clipperz/Crypto/AES.js') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/delta/js/Clipperz/Crypto/AES.js859
1 files changed, 859 insertions, 0 deletions
diff --git a/frontend/delta/js/Clipperz/Crypto/AES.js b/frontend/delta/js/Clipperz/Crypto/AES.js
new file mode 100644
index 0000000..cb56f11
--- a/dev/null
+++ b/frontend/delta/js/Clipperz/Crypto/AES.js
@@ -0,0 +1,859 @@
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.ByteArray) == 'undefined') { throw ""; }} catch (e) {
25 throw "Clipperz.Crypto.AES depends on Clipperz.ByteArray!";
26}
27
28 //Dependency commented to avoid a circular reference
29//try { if (typeof(Clipperz.Crypto.PRNG) == 'undefined') { throw ""; }} catch (e) {
30 //throw "Clipperz.Crypto.AES depends on Clipperz.Crypto.PRNG!";
31//}
32
33if (typeof(Clipperz.Crypto.AES) == 'undefined') { Clipperz.Crypto.AES = {}; }
34
35//#############################################################################
36
37Clipperz.Crypto.AES.DeferredExecutionContext = function(args) {
38 args = args || {};
39
40 this._key = args.key;
41 this._message = args.message;
42 this._result = args.message.clone();
43 this._nonce = args.nonce;
44 this._messageLength = this._message.length();
45
46 this._messageArray = this._message.arrayValues();
47 this._resultArray = this._result.arrayValues();
48 this._nonceArray = this._nonce.arrayValues();
49
50 this._executionStep = 0;
51
52 // this._elaborationChunkSize = 1024; // 4096; // 16384; //4096;
53 this._elaborationChunks = 10;
54 this._pauseTime = 0.02; // 0.02 //0.2;
55
56 return this;
57}
58
59Clipperz.Crypto.AES.DeferredExecutionContext.prototype = MochiKit.Base.update(null, {
60
61 'key': function() {
62 return this._key;
63 },
64
65 'message': function() {
66 return this._message;
67 },
68
69 'messageLength': function() {
70 return this._messageLength;
71 },
72
73 'result': function() {
74 return new Clipperz.ByteArray(this.resultArray());
75 },
76
77 'nonce': function() {
78 return this._nonce;
79 },
80
81 'messageArray': function() {
82 return this._messageArray;
83 },
84
85 'resultArray': function() {
86 return this._resultArray;
87 },
88
89 'nonceArray': function() {
90 return this._nonceArray;
91 },
92
93 'elaborationChunkSize': function() {
94 // return Clipperz.Crypto.AES.DeferredExecution.chunkSize;
95 // return this._elaborationChunkSize;
96 return (this._elaborationChunks * 1024);
97 },
98
99 'executionStep': function() {
100 return this._executionStep;
101 },
102
103 'setExecutionStep': function(aValue) {
104 this._executionStep = aValue;
105 },
106
107 'tuneExecutionParameters': function (anElapsedTime) {
108//var originalChunks = this._elaborationChunks;
109 if (anElapsedTime > 0) {
110 this._elaborationChunks = Math.round(this._elaborationChunks * ((anElapsedTime + 1000)/(anElapsedTime * 2)));
111 }
112//Clipperz.log("tuneExecutionParameters - elapsedTime: " + anElapsedTime + /*originalChunks,*/ " chunks # " + this._elaborationChunks + " [" + this._executionStep + " / " + this._messageLength + "]");
113 },
114
115 'pause': function(aValue) {
116 // return MochiKit.Async.wait(Clipperz.Crypto.AES.DeferredExecution.pauseTime, aValue);
117 return MochiKit.Async.wait(this._pauseTime, aValue);
118 },
119
120 'isDone': function () {
121 return (this._executionStep >= this._messageLength);
122 },
123
124 //-----------------------------------------------------------------------------
125 __syntaxFix__: "syntax fix"
126
127});
128
129//#############################################################################
130
131Clipperz.Crypto.AES.Key = function(args) {
132 args = args || {};
133
134 this._key = args.key;
135 this._keySize = args.keySize || this.key().length();
136
137 if (this.keySize() == 128/8) {
138 this._b = 176;
139 this._numberOfRounds = 10;
140 } else if (this.keySize() == 256/8) {
141 this._b = 240;
142 this._numberOfRounds = 14;
143 } else {
144 Clipperz.logError("AES unsupported key size: " + (this.keySize() * 8) + " bits");
145 throw Clipperz.Crypto.AES.exception.UnsupportedKeySize;
146 }
147
148 this._stretchedKey = null;
149
150 return this;
151}
152
153Clipperz.Crypto.AES.Key.prototype = MochiKit.Base.update(null, {
154
155 'asString': function() {
156 return "Clipperz.Crypto.AES.Key (" + this.key().toHexString() + ")";
157 },
158
159 //-----------------------------------------------------------------------------
160
161 'key': function() {
162 return this._key;
163 },
164
165 'keySize': function() {
166 return this._keySize;
167 },
168
169 'b': function() {
170 return this._b;
171 },
172
173 'numberOfRounds': function() {
174 return this._numberOfRounds;
175 },
176 //=========================================================================
177
178 'keyScheduleCore': function(aWord, aRoundConstantsIndex) {
179 varresult;
180 var sbox;
181
182 sbox = Clipperz.Crypto.AES.sbox();
183
184 result = [sbox[aWord[1]] ^ Clipperz.Crypto.AES.roundConstants()[aRoundConstantsIndex],
185 sbox[aWord[2]],
186 sbox[aWord[3]],
187 sbox[aWord[0]]];
188
189 return result;
190 },
191
192 //-----------------------------------------------------------------------------
193
194 'xorWithPreviousStretchValues': function(aKey, aWord, aPreviousWordIndex) {
195 varresult;
196 var i,c;
197
198 result = [];
199 c = 4;
200 for (i=0; i<c; i++) {
201 result[i] = aWord[i] ^ aKey.byteAtIndex(aPreviousWordIndex + i);
202 }
203
204 return result;
205 },
206
207 //-----------------------------------------------------------------------------
208
209 'sboxShakeup': function(aWord) {
210 var result;
211 var sbox;
212 var i,c;
213
214 result = [];
215 sbox = Clipperz.Crypto.AES.sbox();
216 c =4;
217 for (i=0; i<c; i++) {
218 result[i] = sbox[aWord[i]];
219 }
220
221 return result;
222 },
223
224 //-----------------------------------------------------------------------------
225
226 'stretchKey': function(aKey) {
227 varcurrentWord;
228 varkeyLength;
229 varpreviousStretchIndex;
230 var i,c;
231
232 keyLength = aKey.length();
233 previousStretchIndex = keyLength - this.keySize();
234
235 currentWord = [aKey.byteAtIndex(keyLength - 4),
236 aKey.byteAtIndex(keyLength - 3),
237 aKey.byteAtIndex(keyLength - 2),
238 aKey.byteAtIndex(keyLength - 1)];
239 currentWord = this.keyScheduleCore(currentWord, keyLength / this.keySize());
240
241 if (this.keySize() == 256/8) {
242 c = 8;
243 } else if (this.keySize() == 128/8){
244 c = 4;
245 }
246
247 for (i=0; i<c; i++) {
248 if (i == 4) {
249 //fifth streatch word
250 currentWord = this.sboxShakeup(currentWord);
251 }
252
253 currentWord = this.xorWithPreviousStretchValues(aKey, currentWord, previousStretchIndex + (i*4));
254 aKey.appendBytes(currentWord);
255 }
256
257 return aKey;
258 },
259
260 //-----------------------------------------------------------------------------
261
262 'stretchedKey': function() {
263 if (this._stretchedKey == null) {
264 var stretchedKey;
265
266 stretchedKey = this.key().clone();
267
268 while (stretchedKey.length() < this.keySize()) {
269 stretchedKey.appendByte(0);
270 }
271
272 while (stretchedKey.length() < this.b()) {
273 stretchedKey = this.stretchKey(stretchedKey);
274 }
275
276 this._stretchedKey = stretchedKey.split(0, this.b());
277 }
278
279 return this._stretchedKey;
280 },
281
282 //=========================================================================
283 __syntaxFix__: "syntax fix"
284});
285
286//#############################################################################
287
288Clipperz.Crypto.AES.State = function(args) {
289 args = args || {};
290
291 this._data = args.block;
292 this._key = args.key;
293
294 return this;
295}
296
297Clipperz.Crypto.AES.State.prototype = MochiKit.Base.update(null, {
298
299 'key': function() {
300 return this._key;
301 },
302
303 //-----------------------------------------------------------------------------
304
305 'data': function() {
306 return this._data;
307 },
308
309 'setData': function(aValue) {
310 this._data = aValue;
311 },
312
313 //=========================================================================
314
315 'addRoundKey': function(aRoundNumber) {
316 //each byte of the state is combined with the round key; each round key is derived from the cipher key using a key schedule.
317 vardata;
318 varstretchedKey;
319 varfirstStretchedKeyIndex;
320 var i,c;
321
322 data = this.data();
323 stretchedKey = this.key().stretchedKey();
324 firstStretchedKeyIndex = aRoundNumber * (128/8);
325 c = 128/8;
326 for (i=0; i<c; i++) {
327 data[i] = data[i] ^ stretchedKey.byteAtIndex(firstStretchedKeyIndex + i);
328 }
329 },
330
331 //-----------------------------------------------------------------------------
332
333 'subBytes': function() {
334 // a non-linear substitution step where each byte is replaced with another according to a lookup table.
335 var i,c;
336 vardata;
337 var sbox;
338
339 data = this.data();
340 sbox = Clipperz.Crypto.AES.sbox();
341
342 c = 16;
343 for (i=0; i<c; i++) {
344 data[i] = sbox[data[i]];
345 }
346 },
347
348 //-----------------------------------------------------------------------------
349
350 'shiftRows': function() {
351 //a transposition step where each row of the state is shifted cyclically a certain number of steps.
352 varnewValue;
353 vardata;
354 varshiftMapping;
355 vari,c;
356
357 newValue = new Array(16);
358 data = this.data();
359 shiftMapping = Clipperz.Crypto.AES.shiftRowMapping();
360 // [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11];
361 c = 16;
362 for (i=0; i<c; i++) {
363 newValue[i] = data[shiftMapping[i]];
364 }
365 for (i=0; i<c; i++) {
366 data[i] = newValue[i];
367 }
368 },
369
370 //-----------------------------------------------------------------------------
371/*
372 'mixColumnsWithValues': function(someValues) {
373 varresult;
374 vara;
375 var i,c;
376
377 c = 4;
378 result = [];
379 a = [];
380 for (i=0; i<c; i++) {
381 a[i] = [];
382 a[i][1] = someValues[i]
383 if ((a[i][1] & 0x80) == 0x80) {
384 a[i][2] = (a[i][1] << 1) ^ 0x11b;
385 } else {
386 a[i][2] = a[i][1] << 1;
387 }
388
389 a[i][3] = a[i][2] ^ a[i][1];
390 }
391
392 for (i=0; i<c; i++) {
393 varx;
394
395 x = Clipperz.Crypto.AES.mixColumnsMatrix()[i];
396 result[i] = a[0][x[0]] ^ a[1][x[1]] ^ a[2][x[2]] ^ a[3][x[3]];
397 }
398
399 return result;
400 },
401
402 'mixColumns': function() {
403 //a mixing operation which operates on the columns of the state, combining the four bytes in each column using a linear transformation.
404 var data;
405 var i, c;
406
407 data = this.data();
408 c = 4;
409 for(i=0; i<c; i++) {
410 varblockIndex;
411 var mixedValues;
412
413 blockIndex = i * 4;
414 mixedValues = this.mixColumnsWithValues([data[blockIndex + 0],
415 data[blockIndex + 1],
416 data[blockIndex + 2],
417 data[blockIndex + 3]]);
418 data[blockIndex + 0] = mixedValues[0];
419 data[blockIndex + 1] = mixedValues[1];
420 data[blockIndex + 2] = mixedValues[2];
421 data[blockIndex + 3] = mixedValues[3];
422 }
423 },
424*/
425
426 'mixColumns': function() {
427 //a mixing operation which operates on the columns of the state, combining the four bytes in each column using a linear transformation.
428 var data;
429 var i, c;
430 var a_1;
431 var a_2;
432
433 a_1 = new Array(4);
434 a_2 = new Array(4);
435
436 data = this.data();
437 c = 4;
438 for(i=0; i<c; i++) {
439 varblockIndex;
440 var ii, cc;
441
442 blockIndex = i * 4;
443
444 cc = 4;
445 for (ii=0; ii<cc; ii++) {
446 var value;
447
448 value = data[blockIndex + ii];
449 a_1[ii] = value;
450 a_2[ii] = (value & 0x80) ? ((value << 1) ^ 0x011b) : (value << 1);
451 }
452
453 data[blockIndex + 0] = a_2[0] ^ a_1[1] ^ a_2[1] ^ a_1[2] ^ a_1[3];
454 data[blockIndex + 1] = a_1[0] ^ a_2[1] ^ a_1[2] ^ a_2[2] ^ a_1[3];
455 data[blockIndex + 2] = a_1[0] ^ a_1[1] ^ a_2[2] ^ a_1[3] ^ a_2[3];
456 data[blockIndex + 3] = a_1[0] ^ a_2[0] ^ a_1[1] ^ a_1[2] ^ a_2[3];
457 }
458 },
459
460 //=========================================================================
461
462 'spinRound': function(aRoundNumber) {
463 this.addRoundKey(aRoundNumber);
464 this.subBytes();
465 this.shiftRows();
466 this.mixColumns();
467 },
468
469 'spinLastRound': function() {
470 this.addRoundKey(this.key().numberOfRounds() - 1);
471 this.subBytes();
472 this.shiftRows();
473 this.addRoundKey(this.key().numberOfRounds());
474 },
475
476 //=========================================================================
477
478 'encrypt': function() {
479 vari,c;
480
481 c = this.key().numberOfRounds() - 1;
482 for (i=0; i<c; i++) {
483 this.spinRound(i);
484 }
485
486 this.spinLastRound();
487 },
488
489 //=========================================================================
490 __syntaxFix__: "syntax fix"
491});
492
493//#############################################################################
494
495Clipperz.Crypto.AES.VERSION = "0.1";
496Clipperz.Crypto.AES.NAME = "Clipperz.Crypto.AES";
497
498MochiKit.Base.update(Clipperz.Crypto.AES, {
499
500 //http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-AES.html
501 //http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
502 //http://en.wikipedia.org/wiki/Rijndael_key_schedule
503 //http://en.wikipedia.org/wiki/Rijndael_S-box
504
505 '__repr__': function () {
506 return "[" + this.NAME + " " + this.VERSION + "]";
507 },
508
509 'toString': function () {
510 return this.__repr__();
511 },
512
513 //=============================================================================
514
515 '_sbox': null,
516 'sbox': function() {
517 if (Clipperz.Crypto.AES._sbox == null) {
518 Clipperz.Crypto.AES._sbox = [
5190x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
5200xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
5210xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
5220x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
5230x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
5240x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
5250xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
5260x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
5270xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
5280x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
5290xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
5300xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
5310xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
5320x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
5330xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
5340x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
535 ];
536 }
537
538 return Clipperz.Crypto.AES._sbox;
539 },
540
541 //-----------------------------------------------------------------------------
542 //
543 // 0 4 8 12 0 4 812
544 // 1 5 9 13 => 5 9 131
545 // 2 6 10 14 10 14 26
546 // 3 7 11 15 15 3 711
547 //
548 '_shiftRowMapping': null,
549 'shiftRowMapping': function() {
550 if (Clipperz.Crypto.AES._shiftRowMapping == null) {
551 Clipperz.Crypto.AES._shiftRowMapping = [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11];
552 }
553
554 return Clipperz.Crypto.AES._shiftRowMapping;
555 },
556
557 //-----------------------------------------------------------------------------
558
559 '_mixColumnsMatrix': null,
560 'mixColumnsMatrix': function() {
561 if (Clipperz.Crypto.AES._mixColumnsMatrix == null) {
562 Clipperz.Crypto.AES._mixColumnsMatrix = [[2, 3, 1 ,1],
563 [1, 2, 3, 1],
564 [1, 1, 2, 3],
565 [3, 1, 1, 2] ];
566 }
567
568 return Clipperz.Crypto.AES._mixColumnsMatrix;
569 },
570
571 '_roundConstants': null,
572 'roundConstants': function() {
573 if (Clipperz.Crypto.AES._roundConstants == null) {
574 Clipperz.Crypto.AES._roundConstants = [ , 1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154];
575 // Clipperz.Crypto.AES._roundConstants = [ , 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a];
576 }
577
578 return Clipperz.Crypto.AES._roundConstants;
579 },
580
581 //=============================================================================
582
583 'incrementNonce': function(aNonce) {
584//Clipperz.Profile.start("Clipperz.Crypto.AES.incrementNonce");
585 var i;
586 var done;
587
588 done = false;
589 i = aNonce.length - 1;
590
591 while ((i>=0) && (done == false)) {
592 var currentByteValue;
593
594 currentByteValue = aNonce[i];
595
596 if (currentByteValue == 0xff) {
597 aNonce[i] = 0;
598 if (i>= 0) {
599 i --;
600 } else {
601 done = true;
602 }
603 } else {
604 aNonce[i] = currentByteValue + 1;
605 done = true;
606 }
607 }
608//Clipperz.Profile.stop("Clipperz.Crypto.AES.incrementNonce");
609 },
610
611 //-----------------------------------------------------------------------------
612
613 'encryptBlock': function(aKey, aBlock) {
614 varresult;
615 varstate;
616
617 state = new Clipperz.Crypto.AES.State({block:aBlock, key:aKey});
618//is(state.data(), 'before');
619 state.encrypt();
620 result = state.data();
621
622 return result;
623 },
624
625 //-----------------------------------------------------------------------------
626
627 'encryptBlocks': function(aKey, aMessage, aNonce) {
628 varresult;
629 var nonce;
630 var self;
631 varmessageIndex;
632 varmessageLength;
633 var blockSize;
634
635 self = Clipperz.Crypto.AES;
636 blockSize = 128/8;
637 messageLength = aMessage.length;
638 nonce = aNonce;
639
640 result = aMessage;
641 messageIndex = 0;
642 while (messageIndex < messageLength) {
643 var encryptedBlock;
644 var i,c;
645
646 self.incrementNonce(nonce);
647 encryptedBlock = self.encryptBlock(aKey, nonce);
648
649 if ((messageLength - messageIndex) > blockSize) {
650 c = blockSize;
651 } else {
652 c = messageLength - messageIndex;
653 }
654
655 for (i=0; i<c; i++) {
656 result[messageIndex + i] = result[messageIndex + i] ^ encryptedBlock[i];
657 }
658
659 messageIndex += blockSize;
660 }
661
662 return result;
663 },
664
665 //-----------------------------------------------------------------------------
666
667 'encrypt': function(aKey, someData, aNonce) {
668 var result;
669 var nonce;
670 varencryptedData;
671 var key;
672
673 key = new Clipperz.Crypto.AES.Key({key:aKey});
674 nonce = aNonce ? aNonce.clone() : Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(128/8);
675
676 encryptedData = Clipperz.Crypto.AES.encryptBlocks(key, someData.arrayValues(), nonce.arrayValues());
677
678 result = nonce.appendBytes(encryptedData);
679
680 return result;
681 },
682
683 //-----------------------------------------------------------------------------
684
685 'decrypt': function(aKey, someData) {
686 var result;
687 var nonce;
688 var encryptedData;
689 var decryptedData;
690 vardataIterator;
691 var key;
692
693 key = new Clipperz.Crypto.AES.Key({key:aKey});
694
695 encryptedData = someData.arrayValues();
696 nonce = encryptedData.slice(0, (128/8));
697 encryptedData = encryptedData.slice(128/8);
698 decryptedData = Clipperz.Crypto.AES.encryptBlocks(key, encryptedData, nonce);
699
700 result = new Clipperz.ByteArray(decryptedData);
701
702 return result;
703 },
704
705 //=============================================================================
706
707 'deferredEncryptExecutionChunk': function(anExecutionContext) {
708 varresult;
709 var nonce;
710 var self;
711 varmessageIndex;
712 varmessageLength;
713 var blockSize;
714 var executionLimit;
715 var startTime, endTime;
716
717 self = Clipperz.Crypto.AES;
718 startTime = new Date();
719 blockSize = 128/8;
720 messageLength = anExecutionContext.messageArray().length;
721 nonce = anExecutionContext.nonceArray();
722 result = anExecutionContext.resultArray();
723
724 messageIndex = anExecutionContext.executionStep();
725 executionLimit = messageIndex + anExecutionContext.elaborationChunkSize();
726 executionLimit = Math.min(executionLimit, messageLength);
727
728 while (messageIndex < executionLimit) {
729 var encryptedBlock;
730 var i,c;
731
732 self.incrementNonce(nonce);
733 encryptedBlock = self.encryptBlock(anExecutionContext.key(), nonce);
734
735 if ((executionLimit - messageIndex) > blockSize) {
736 c = blockSize;
737 } else {
738 c = executionLimit - messageIndex;
739 }
740
741 for (i=0; i<c; i++) {
742 result[messageIndex + i] = result[messageIndex + i] ^ encryptedBlock[i];
743 }
744
745 messageIndex += blockSize;
746 }
747 anExecutionContext.setExecutionStep(messageIndex);
748 endTime = new Date();
749 anExecutionContext.tuneExecutionParameters(endTime - startTime);
750
751 return anExecutionContext;
752 },
753
754 //-----------------------------------------------------------------------------
755/*
756 'deferredEncryptBlocks': function(anExecutionContext) {
757 vardeferredResult;
758 varmessageSize;
759 var i,c;
760
761 messageSize = anExecutionContext.messageLength();
762
763 deferredResult = new Clipperz.Async.Deferred("AES.deferredEncryptBloks");
764
765 c = Math.ceil(messageSize / anExecutionContext.elaborationChunkSize());
766 for (i=0; i<c; i++) {
767 deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncryptExecutionChunk);
768 deferredResult.addMethod(anExecutionContext, 'pause');
769 }
770
771 deferredResult.callback(anExecutionContext);
772
773 return deferredResult;
774 },
775*/
776
777 'deferredEncryptBlocks': function(anExecutionContext) {
778 vardeferredResult;
779
780 if (! anExecutionContext.isDone()) {
781 deferredResult = Clipperz.Async.callbacks("Clipperz.Crypto.AES.deferredEncryptBloks", [
782 Clipperz.Crypto.AES.deferredEncryptExecutionChunk,
783 MochiKit.Base.method(anExecutionContext, 'pause'),
784 Clipperz.Crypto.AES.deferredEncryptBlocks
785 ], {trace:false}, anExecutionContext);
786 } else {
787 deferredResult = MochiKit.Async.succeed(anExecutionContext);
788 }
789
790 return deferredResult;
791 },
792
793 //-----------------------------------------------------------------------------
794
795 'deferredEncrypt': function(aKey, someData, aNonce) {
796 var deferredResult;
797 varexecutionContext;
798 var result;
799 var nonce;
800 var key;
801
802 key = new Clipperz.Crypto.AES.Key({key:aKey});
803 nonce = aNonce ? aNonce.clone() : Clipperz.Crypto.PRNG.defaultRandomGenerator().getRandomBytes(128/8);
804
805 executionContext = new Clipperz.Crypto.AES.DeferredExecutionContext({key:key, message:someData, nonce:nonce});
806
807 deferredResult = new Clipperz.Async.Deferred("AES.deferredEncrypt");
808 deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncryptBlocks);
809 deferredResult.addCallback(function(anExecutionContext) {
810 var result;
811
812 result = anExecutionContext.nonce().clone();
813 result.appendBytes(anExecutionContext.resultArray());
814
815 return result;
816 });
817 deferredResult.callback(executionContext)
818
819 return deferredResult;
820 },
821
822 //-----------------------------------------------------------------------------
823
824 'deferredDecrypt': function(aKey, someData) {
825 var deferredResult
826 var nonce;
827 var message;
828 var key;
829
830 key = new Clipperz.Crypto.AES.Key({key:aKey});
831 nonce = someData.split(0, (128/8));
832 message = someData.split(128/8);
833 executionContext = new Clipperz.Crypto.AES.DeferredExecutionContext({key:key, message:message, nonce:nonce});
834
835 deferredResult = new Clipperz.Async.Deferred("AES.deferredDecrypt");
836 deferredResult.addCallback(Clipperz.Crypto.AES.deferredEncryptBlocks);
837 deferredResult.addCallback(function(anExecutionContext) {
838 return anExecutionContext.result();
839 });
840 deferredResult.callback(executionContext);
841
842 return deferredResult;
843 },
844
845 //-----------------------------------------------------------------------------
846 __syntaxFix__: "syntax fix"
847
848});
849
850//#############################################################################
851
852//Clipperz.Crypto.AES.DeferredExecution = {
853 // 'chunkSize': 16384, // 4096, // 1024 4096 8192 1638432768;
854 // 'pauseTime': 0.02 //0.2
855//}
856
857Clipperz.Crypto.AES.exception = {
858 'UnsupportedKeySize': new MochiKit.Base.NamedError("Clipperz.Crypto.AES.exception.UnsupportedKeySize")
859};