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