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