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