1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # |
|
4 # aes.py: implements AES - Advanced Encryption Standard |
|
5 # from the SlowAES project, http://code.google.com/p/slowaes/ |
|
6 # |
|
7 # Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ), |
|
8 # Alex Martelli ( http://www.aleax.it ) |
|
9 # |
|
10 # Ported from C code written by Laurent Haan |
|
11 # ( http://www.progressive-coding.com ) |
|
12 # |
|
13 # Licensed under the Apache License, Version 2.0 |
|
14 # http://www.apache.org/licenses/ |
|
15 # |
|
16 |
|
17 # |
|
18 # Ported to Python3 |
|
19 # |
|
20 # Copyright (c) 2011 - 2024 Detlev Offenbach <detlev@die-offenbachs.de> |
|
21 # |
|
22 |
|
23 """ |
|
24 Module implementing classes for encryption according |
|
25 Advanced Encryption Standard. |
|
26 """ |
|
27 |
|
28 import math |
|
29 import os |
|
30 |
|
31 |
|
32 def append_PKCS7_padding(b): |
|
33 """ |
|
34 Function to pad the given data to a multiple of 16-bytes by PKCS7 padding. |
|
35 |
|
36 @param b data to be padded |
|
37 @type bytes |
|
38 @return padded data |
|
39 @rtype bytes |
|
40 """ |
|
41 numpads = 16 - (len(b) % 16) |
|
42 return b + numpads * bytes(chr(numpads), encoding="ascii") |
|
43 |
|
44 |
|
45 def strip_PKCS7_padding(b): |
|
46 """ |
|
47 Function to strip off PKCS7 padding. |
|
48 |
|
49 @param b data to be stripped |
|
50 @type bytes |
|
51 @return stripped data |
|
52 @rtype bytes |
|
53 @exception ValueError data padding is invalid |
|
54 """ |
|
55 if len(b) % 16 or not b: |
|
56 raise ValueError("Data of len {0} can't be PCKS7-padded".format(len(b))) |
|
57 numpads = b[-1] |
|
58 if numpads > 16: |
|
59 raise ValueError("Data ending with {0} can't be PCKS7-padded".format(b[-1])) |
|
60 return b[:-numpads] |
|
61 |
|
62 |
|
63 class AES: |
|
64 """ |
|
65 Class implementing the Advanced Encryption Standard algorithm. |
|
66 """ |
|
67 |
|
68 # valid key sizes |
|
69 KeySize = { |
|
70 "SIZE_128": 16, |
|
71 "SIZE_192": 24, |
|
72 "SIZE_256": 32, |
|
73 } |
|
74 |
|
75 # Rijndael S-box |
|
76 sbox = [ |
|
77 0x63, |
|
78 0x7C, |
|
79 0x77, |
|
80 0x7B, |
|
81 0xF2, |
|
82 0x6B, |
|
83 0x6F, |
|
84 0xC5, |
|
85 0x30, |
|
86 0x01, |
|
87 0x67, |
|
88 0x2B, |
|
89 0xFE, |
|
90 0xD7, |
|
91 0xAB, |
|
92 0x76, |
|
93 0xCA, |
|
94 0x82, |
|
95 0xC9, |
|
96 0x7D, |
|
97 0xFA, |
|
98 0x59, |
|
99 0x47, |
|
100 0xF0, |
|
101 0xAD, |
|
102 0xD4, |
|
103 0xA2, |
|
104 0xAF, |
|
105 0x9C, |
|
106 0xA4, |
|
107 0x72, |
|
108 0xC0, |
|
109 0xB7, |
|
110 0xFD, |
|
111 0x93, |
|
112 0x26, |
|
113 0x36, |
|
114 0x3F, |
|
115 0xF7, |
|
116 0xCC, |
|
117 0x34, |
|
118 0xA5, |
|
119 0xE5, |
|
120 0xF1, |
|
121 0x71, |
|
122 0xD8, |
|
123 0x31, |
|
124 0x15, |
|
125 0x04, |
|
126 0xC7, |
|
127 0x23, |
|
128 0xC3, |
|
129 0x18, |
|
130 0x96, |
|
131 0x05, |
|
132 0x9A, |
|
133 0x07, |
|
134 0x12, |
|
135 0x80, |
|
136 0xE2, |
|
137 0xEB, |
|
138 0x27, |
|
139 0xB2, |
|
140 0x75, |
|
141 0x09, |
|
142 0x83, |
|
143 0x2C, |
|
144 0x1A, |
|
145 0x1B, |
|
146 0x6E, |
|
147 0x5A, |
|
148 0xA0, |
|
149 0x52, |
|
150 0x3B, |
|
151 0xD6, |
|
152 0xB3, |
|
153 0x29, |
|
154 0xE3, |
|
155 0x2F, |
|
156 0x84, |
|
157 0x53, |
|
158 0xD1, |
|
159 0x00, |
|
160 0xED, |
|
161 0x20, |
|
162 0xFC, |
|
163 0xB1, |
|
164 0x5B, |
|
165 0x6A, |
|
166 0xCB, |
|
167 0xBE, |
|
168 0x39, |
|
169 0x4A, |
|
170 0x4C, |
|
171 0x58, |
|
172 0xCF, |
|
173 0xD0, |
|
174 0xEF, |
|
175 0xAA, |
|
176 0xFB, |
|
177 0x43, |
|
178 0x4D, |
|
179 0x33, |
|
180 0x85, |
|
181 0x45, |
|
182 0xF9, |
|
183 0x02, |
|
184 0x7F, |
|
185 0x50, |
|
186 0x3C, |
|
187 0x9F, |
|
188 0xA8, |
|
189 0x51, |
|
190 0xA3, |
|
191 0x40, |
|
192 0x8F, |
|
193 0x92, |
|
194 0x9D, |
|
195 0x38, |
|
196 0xF5, |
|
197 0xBC, |
|
198 0xB6, |
|
199 0xDA, |
|
200 0x21, |
|
201 0x10, |
|
202 0xFF, |
|
203 0xF3, |
|
204 0xD2, |
|
205 0xCD, |
|
206 0x0C, |
|
207 0x13, |
|
208 0xEC, |
|
209 0x5F, |
|
210 0x97, |
|
211 0x44, |
|
212 0x17, |
|
213 0xC4, |
|
214 0xA7, |
|
215 0x7E, |
|
216 0x3D, |
|
217 0x64, |
|
218 0x5D, |
|
219 0x19, |
|
220 0x73, |
|
221 0x60, |
|
222 0x81, |
|
223 0x4F, |
|
224 0xDC, |
|
225 0x22, |
|
226 0x2A, |
|
227 0x90, |
|
228 0x88, |
|
229 0x46, |
|
230 0xEE, |
|
231 0xB8, |
|
232 0x14, |
|
233 0xDE, |
|
234 0x5E, |
|
235 0x0B, |
|
236 0xDB, |
|
237 0xE0, |
|
238 0x32, |
|
239 0x3A, |
|
240 0x0A, |
|
241 0x49, |
|
242 0x06, |
|
243 0x24, |
|
244 0x5C, |
|
245 0xC2, |
|
246 0xD3, |
|
247 0xAC, |
|
248 0x62, |
|
249 0x91, |
|
250 0x95, |
|
251 0xE4, |
|
252 0x79, |
|
253 0xE7, |
|
254 0xC8, |
|
255 0x37, |
|
256 0x6D, |
|
257 0x8D, |
|
258 0xD5, |
|
259 0x4E, |
|
260 0xA9, |
|
261 0x6C, |
|
262 0x56, |
|
263 0xF4, |
|
264 0xEA, |
|
265 0x65, |
|
266 0x7A, |
|
267 0xAE, |
|
268 0x08, |
|
269 0xBA, |
|
270 0x78, |
|
271 0x25, |
|
272 0x2E, |
|
273 0x1C, |
|
274 0xA6, |
|
275 0xB4, |
|
276 0xC6, |
|
277 0xE8, |
|
278 0xDD, |
|
279 0x74, |
|
280 0x1F, |
|
281 0x4B, |
|
282 0xBD, |
|
283 0x8B, |
|
284 0x8A, |
|
285 0x70, |
|
286 0x3E, |
|
287 0xB5, |
|
288 0x66, |
|
289 0x48, |
|
290 0x03, |
|
291 0xF6, |
|
292 0x0E, |
|
293 0x61, |
|
294 0x35, |
|
295 0x57, |
|
296 0xB9, |
|
297 0x86, |
|
298 0xC1, |
|
299 0x1D, |
|
300 0x9E, |
|
301 0xE1, |
|
302 0xF8, |
|
303 0x98, |
|
304 0x11, |
|
305 0x69, |
|
306 0xD9, |
|
307 0x8E, |
|
308 0x94, |
|
309 0x9B, |
|
310 0x1E, |
|
311 0x87, |
|
312 0xE9, |
|
313 0xCE, |
|
314 0x55, |
|
315 0x28, |
|
316 0xDF, |
|
317 0x8C, |
|
318 0xA1, |
|
319 0x89, |
|
320 0x0D, |
|
321 0xBF, |
|
322 0xE6, |
|
323 0x42, |
|
324 0x68, |
|
325 0x41, |
|
326 0x99, |
|
327 0x2D, |
|
328 0x0F, |
|
329 0xB0, |
|
330 0x54, |
|
331 0xBB, |
|
332 0x16, |
|
333 ] |
|
334 |
|
335 # Rijndael Inverted S-box |
|
336 rsbox = [ |
|
337 0x52, |
|
338 0x09, |
|
339 0x6A, |
|
340 0xD5, |
|
341 0x30, |
|
342 0x36, |
|
343 0xA5, |
|
344 0x38, |
|
345 0xBF, |
|
346 0x40, |
|
347 0xA3, |
|
348 0x9E, |
|
349 0x81, |
|
350 0xF3, |
|
351 0xD7, |
|
352 0xFB, |
|
353 0x7C, |
|
354 0xE3, |
|
355 0x39, |
|
356 0x82, |
|
357 0x9B, |
|
358 0x2F, |
|
359 0xFF, |
|
360 0x87, |
|
361 0x34, |
|
362 0x8E, |
|
363 0x43, |
|
364 0x44, |
|
365 0xC4, |
|
366 0xDE, |
|
367 0xE9, |
|
368 0xCB, |
|
369 0x54, |
|
370 0x7B, |
|
371 0x94, |
|
372 0x32, |
|
373 0xA6, |
|
374 0xC2, |
|
375 0x23, |
|
376 0x3D, |
|
377 0xEE, |
|
378 0x4C, |
|
379 0x95, |
|
380 0x0B, |
|
381 0x42, |
|
382 0xFA, |
|
383 0xC3, |
|
384 0x4E, |
|
385 0x08, |
|
386 0x2E, |
|
387 0xA1, |
|
388 0x66, |
|
389 0x28, |
|
390 0xD9, |
|
391 0x24, |
|
392 0xB2, |
|
393 0x76, |
|
394 0x5B, |
|
395 0xA2, |
|
396 0x49, |
|
397 0x6D, |
|
398 0x8B, |
|
399 0xD1, |
|
400 0x25, |
|
401 0x72, |
|
402 0xF8, |
|
403 0xF6, |
|
404 0x64, |
|
405 0x86, |
|
406 0x68, |
|
407 0x98, |
|
408 0x16, |
|
409 0xD4, |
|
410 0xA4, |
|
411 0x5C, |
|
412 0xCC, |
|
413 0x5D, |
|
414 0x65, |
|
415 0xB6, |
|
416 0x92, |
|
417 0x6C, |
|
418 0x70, |
|
419 0x48, |
|
420 0x50, |
|
421 0xFD, |
|
422 0xED, |
|
423 0xB9, |
|
424 0xDA, |
|
425 0x5E, |
|
426 0x15, |
|
427 0x46, |
|
428 0x57, |
|
429 0xA7, |
|
430 0x8D, |
|
431 0x9D, |
|
432 0x84, |
|
433 0x90, |
|
434 0xD8, |
|
435 0xAB, |
|
436 0x00, |
|
437 0x8C, |
|
438 0xBC, |
|
439 0xD3, |
|
440 0x0A, |
|
441 0xF7, |
|
442 0xE4, |
|
443 0x58, |
|
444 0x05, |
|
445 0xB8, |
|
446 0xB3, |
|
447 0x45, |
|
448 0x06, |
|
449 0xD0, |
|
450 0x2C, |
|
451 0x1E, |
|
452 0x8F, |
|
453 0xCA, |
|
454 0x3F, |
|
455 0x0F, |
|
456 0x02, |
|
457 0xC1, |
|
458 0xAF, |
|
459 0xBD, |
|
460 0x03, |
|
461 0x01, |
|
462 0x13, |
|
463 0x8A, |
|
464 0x6B, |
|
465 0x3A, |
|
466 0x91, |
|
467 0x11, |
|
468 0x41, |
|
469 0x4F, |
|
470 0x67, |
|
471 0xDC, |
|
472 0xEA, |
|
473 0x97, |
|
474 0xF2, |
|
475 0xCF, |
|
476 0xCE, |
|
477 0xF0, |
|
478 0xB4, |
|
479 0xE6, |
|
480 0x73, |
|
481 0x96, |
|
482 0xAC, |
|
483 0x74, |
|
484 0x22, |
|
485 0xE7, |
|
486 0xAD, |
|
487 0x35, |
|
488 0x85, |
|
489 0xE2, |
|
490 0xF9, |
|
491 0x37, |
|
492 0xE8, |
|
493 0x1C, |
|
494 0x75, |
|
495 0xDF, |
|
496 0x6E, |
|
497 0x47, |
|
498 0xF1, |
|
499 0x1A, |
|
500 0x71, |
|
501 0x1D, |
|
502 0x29, |
|
503 0xC5, |
|
504 0x89, |
|
505 0x6F, |
|
506 0xB7, |
|
507 0x62, |
|
508 0x0E, |
|
509 0xAA, |
|
510 0x18, |
|
511 0xBE, |
|
512 0x1B, |
|
513 0xFC, |
|
514 0x56, |
|
515 0x3E, |
|
516 0x4B, |
|
517 0xC6, |
|
518 0xD2, |
|
519 0x79, |
|
520 0x20, |
|
521 0x9A, |
|
522 0xDB, |
|
523 0xC0, |
|
524 0xFE, |
|
525 0x78, |
|
526 0xCD, |
|
527 0x5A, |
|
528 0xF4, |
|
529 0x1F, |
|
530 0xDD, |
|
531 0xA8, |
|
532 0x33, |
|
533 0x88, |
|
534 0x07, |
|
535 0xC7, |
|
536 0x31, |
|
537 0xB1, |
|
538 0x12, |
|
539 0x10, |
|
540 0x59, |
|
541 0x27, |
|
542 0x80, |
|
543 0xEC, |
|
544 0x5F, |
|
545 0x60, |
|
546 0x51, |
|
547 0x7F, |
|
548 0xA9, |
|
549 0x19, |
|
550 0xB5, |
|
551 0x4A, |
|
552 0x0D, |
|
553 0x2D, |
|
554 0xE5, |
|
555 0x7A, |
|
556 0x9F, |
|
557 0x93, |
|
558 0xC9, |
|
559 0x9C, |
|
560 0xEF, |
|
561 0xA0, |
|
562 0xE0, |
|
563 0x3B, |
|
564 0x4D, |
|
565 0xAE, |
|
566 0x2A, |
|
567 0xF5, |
|
568 0xB0, |
|
569 0xC8, |
|
570 0xEB, |
|
571 0xBB, |
|
572 0x3C, |
|
573 0x83, |
|
574 0x53, |
|
575 0x99, |
|
576 0x61, |
|
577 0x17, |
|
578 0x2B, |
|
579 0x04, |
|
580 0x7E, |
|
581 0xBA, |
|
582 0x77, |
|
583 0xD6, |
|
584 0x26, |
|
585 0xE1, |
|
586 0x69, |
|
587 0x14, |
|
588 0x63, |
|
589 0x55, |
|
590 0x21, |
|
591 0x0C, |
|
592 0x7D, |
|
593 ] |
|
594 |
|
595 # Rijndael Rcon |
|
596 Rcon = [ |
|
597 0x8D, |
|
598 0x01, |
|
599 0x02, |
|
600 0x04, |
|
601 0x08, |
|
602 0x10, |
|
603 0x20, |
|
604 0x40, |
|
605 0x80, |
|
606 0x1B, |
|
607 0x36, |
|
608 0x6C, |
|
609 0xD8, |
|
610 0xAB, |
|
611 0x4D, |
|
612 0x9A, |
|
613 0x2F, |
|
614 0x5E, |
|
615 0xBC, |
|
616 0x63, |
|
617 0xC6, |
|
618 0x97, |
|
619 0x35, |
|
620 0x6A, |
|
621 0xD4, |
|
622 0xB3, |
|
623 0x7D, |
|
624 0xFA, |
|
625 0xEF, |
|
626 0xC5, |
|
627 0x91, |
|
628 0x39, |
|
629 0x72, |
|
630 0xE4, |
|
631 0xD3, |
|
632 0xBD, |
|
633 0x61, |
|
634 0xC2, |
|
635 0x9F, |
|
636 0x25, |
|
637 0x4A, |
|
638 0x94, |
|
639 0x33, |
|
640 0x66, |
|
641 0xCC, |
|
642 0x83, |
|
643 0x1D, |
|
644 0x3A, |
|
645 0x74, |
|
646 0xE8, |
|
647 0xCB, |
|
648 0x8D, |
|
649 0x01, |
|
650 0x02, |
|
651 0x04, |
|
652 0x08, |
|
653 0x10, |
|
654 0x20, |
|
655 0x40, |
|
656 0x80, |
|
657 0x1B, |
|
658 0x36, |
|
659 0x6C, |
|
660 0xD8, |
|
661 0xAB, |
|
662 0x4D, |
|
663 0x9A, |
|
664 0x2F, |
|
665 0x5E, |
|
666 0xBC, |
|
667 0x63, |
|
668 0xC6, |
|
669 0x97, |
|
670 0x35, |
|
671 0x6A, |
|
672 0xD4, |
|
673 0xB3, |
|
674 0x7D, |
|
675 0xFA, |
|
676 0xEF, |
|
677 0xC5, |
|
678 0x91, |
|
679 0x39, |
|
680 0x72, |
|
681 0xE4, |
|
682 0xD3, |
|
683 0xBD, |
|
684 0x61, |
|
685 0xC2, |
|
686 0x9F, |
|
687 0x25, |
|
688 0x4A, |
|
689 0x94, |
|
690 0x33, |
|
691 0x66, |
|
692 0xCC, |
|
693 0x83, |
|
694 0x1D, |
|
695 0x3A, |
|
696 0x74, |
|
697 0xE8, |
|
698 0xCB, |
|
699 0x8D, |
|
700 0x01, |
|
701 0x02, |
|
702 0x04, |
|
703 0x08, |
|
704 0x10, |
|
705 0x20, |
|
706 0x40, |
|
707 0x80, |
|
708 0x1B, |
|
709 0x36, |
|
710 0x6C, |
|
711 0xD8, |
|
712 0xAB, |
|
713 0x4D, |
|
714 0x9A, |
|
715 0x2F, |
|
716 0x5E, |
|
717 0xBC, |
|
718 0x63, |
|
719 0xC6, |
|
720 0x97, |
|
721 0x35, |
|
722 0x6A, |
|
723 0xD4, |
|
724 0xB3, |
|
725 0x7D, |
|
726 0xFA, |
|
727 0xEF, |
|
728 0xC5, |
|
729 0x91, |
|
730 0x39, |
|
731 0x72, |
|
732 0xE4, |
|
733 0xD3, |
|
734 0xBD, |
|
735 0x61, |
|
736 0xC2, |
|
737 0x9F, |
|
738 0x25, |
|
739 0x4A, |
|
740 0x94, |
|
741 0x33, |
|
742 0x66, |
|
743 0xCC, |
|
744 0x83, |
|
745 0x1D, |
|
746 0x3A, |
|
747 0x74, |
|
748 0xE8, |
|
749 0xCB, |
|
750 0x8D, |
|
751 0x01, |
|
752 0x02, |
|
753 0x04, |
|
754 0x08, |
|
755 0x10, |
|
756 0x20, |
|
757 0x40, |
|
758 0x80, |
|
759 0x1B, |
|
760 0x36, |
|
761 0x6C, |
|
762 0xD8, |
|
763 0xAB, |
|
764 0x4D, |
|
765 0x9A, |
|
766 0x2F, |
|
767 0x5E, |
|
768 0xBC, |
|
769 0x63, |
|
770 0xC6, |
|
771 0x97, |
|
772 0x35, |
|
773 0x6A, |
|
774 0xD4, |
|
775 0xB3, |
|
776 0x7D, |
|
777 0xFA, |
|
778 0xEF, |
|
779 0xC5, |
|
780 0x91, |
|
781 0x39, |
|
782 0x72, |
|
783 0xE4, |
|
784 0xD3, |
|
785 0xBD, |
|
786 0x61, |
|
787 0xC2, |
|
788 0x9F, |
|
789 0x25, |
|
790 0x4A, |
|
791 0x94, |
|
792 0x33, |
|
793 0x66, |
|
794 0xCC, |
|
795 0x83, |
|
796 0x1D, |
|
797 0x3A, |
|
798 0x74, |
|
799 0xE8, |
|
800 0xCB, |
|
801 0x8D, |
|
802 0x01, |
|
803 0x02, |
|
804 0x04, |
|
805 0x08, |
|
806 0x10, |
|
807 0x20, |
|
808 0x40, |
|
809 0x80, |
|
810 0x1B, |
|
811 0x36, |
|
812 0x6C, |
|
813 0xD8, |
|
814 0xAB, |
|
815 0x4D, |
|
816 0x9A, |
|
817 0x2F, |
|
818 0x5E, |
|
819 0xBC, |
|
820 0x63, |
|
821 0xC6, |
|
822 0x97, |
|
823 0x35, |
|
824 0x6A, |
|
825 0xD4, |
|
826 0xB3, |
|
827 0x7D, |
|
828 0xFA, |
|
829 0xEF, |
|
830 0xC5, |
|
831 0x91, |
|
832 0x39, |
|
833 0x72, |
|
834 0xE4, |
|
835 0xD3, |
|
836 0xBD, |
|
837 0x61, |
|
838 0xC2, |
|
839 0x9F, |
|
840 0x25, |
|
841 0x4A, |
|
842 0x94, |
|
843 0x33, |
|
844 0x66, |
|
845 0xCC, |
|
846 0x83, |
|
847 0x1D, |
|
848 0x3A, |
|
849 0x74, |
|
850 0xE8, |
|
851 0xCB, |
|
852 ] |
|
853 |
|
854 def __getSBoxValue(self, num): |
|
855 """ |
|
856 Private method to retrieve a given S-Box value. |
|
857 |
|
858 @param num position of the value |
|
859 @type int |
|
860 @return value of the S-Box |
|
861 @rtype int |
|
862 """ |
|
863 return self.sbox[num] |
|
864 |
|
865 def __getSBoxInvert(self, num): |
|
866 """ |
|
867 Private method to retrieve a given Inverted S-Box value. |
|
868 |
|
869 @param num position of the value |
|
870 @type int |
|
871 @return value of the Inverted S-Box |
|
872 @rtype int |
|
873 """ |
|
874 return self.rsbox[num] |
|
875 |
|
876 def __rotate(self, data): |
|
877 """ |
|
878 Private method performing Rijndael's key schedule rotate operation. |
|
879 |
|
880 Rotate the data word eight bits to the left: eg, |
|
881 rotate(1d2c3a4f) == 2c3a4f1d. |
|
882 |
|
883 @param data data of size 4 |
|
884 @type bytearray |
|
885 @return rotated data |
|
886 @rtype bytearray |
|
887 """ |
|
888 return data[1:] + data[:1] |
|
889 |
|
890 def __getRconValue(self, num): |
|
891 """ |
|
892 Private method to retrieve a given Rcon value. |
|
893 |
|
894 @param num position of the value |
|
895 @type int |
|
896 @return Rcon value |
|
897 @rtype int |
|
898 """ |
|
899 return self.Rcon[num] |
|
900 |
|
901 def __core(self, data, iteration): |
|
902 """ |
|
903 Private method performing the key schedule core operation. |
|
904 |
|
905 @param data data to operate on |
|
906 @type bytearray |
|
907 @param iteration iteration counter |
|
908 @type int |
|
909 @return modified data |
|
910 @rtype bytearray |
|
911 """ |
|
912 # rotate the 32-bit word 8 bits to the left |
|
913 data = self.__rotate(data) |
|
914 # apply S-Box substitution on all 4 parts of the 32-bit word |
|
915 for i in range(4): |
|
916 data[i] = self.__getSBoxValue(data[i]) |
|
917 # XOR the output of the rcon operation with i to the first part |
|
918 # (leftmost) only |
|
919 data[0] = data[0] ^ self.__getRconValue(iteration) |
|
920 return data |
|
921 |
|
922 def __expandKey(self, key, size, expandedKeySize): |
|
923 """ |
|
924 Private method performing Rijndael's key expansion. |
|
925 |
|
926 Expands a 128, 192 or 256 bit key into a 176, 208 or 240 bit key. |
|
927 |
|
928 @param key key to be expanded |
|
929 @type bytes or bytearray |
|
930 @param size size of the key in bytes (16, 24 or 32) |
|
931 @type int |
|
932 @param expandedKeySize size of the expanded key |
|
933 @type int |
|
934 @return expanded key |
|
935 @rtype bytearray |
|
936 """ |
|
937 # current expanded keySize, in bytes |
|
938 currentSize = 0 |
|
939 rconIteration = 1 |
|
940 expandedKey = bytearray(expandedKeySize) |
|
941 |
|
942 # set the 16, 24, 32 bytes of the expanded key to the input key |
|
943 for j in range(size): |
|
944 expandedKey[j] = key[j] |
|
945 currentSize += size |
|
946 |
|
947 while currentSize < expandedKeySize: |
|
948 # assign the previous 4 bytes to the temporary value t |
|
949 t = expandedKey[currentSize - 4 : currentSize] |
|
950 |
|
951 # every 16, 24, 32 bytes we apply the core schedule to t |
|
952 # and increment rconIteration afterwards |
|
953 if currentSize % size == 0: |
|
954 t = self.__core(t, rconIteration) |
|
955 rconIteration += 1 |
|
956 # For 256-bit keys, we add an extra sbox to the calculation |
|
957 if size == self.KeySize["SIZE_256"] and ((currentSize % size) == 16): |
|
958 for ll in range(4): |
|
959 t[ll] = self.__getSBoxValue(t[ll]) |
|
960 |
|
961 # We XOR t with the four-byte block 16, 24, 32 bytes before the new |
|
962 # expanded key. This becomes the next four bytes in the expanded |
|
963 # key. |
|
964 for m in range(4): |
|
965 expandedKey[currentSize] = expandedKey[currentSize - size] ^ t[m] |
|
966 currentSize += 1 # noqa: Y113 |
|
967 |
|
968 return expandedKey |
|
969 |
|
970 def __addRoundKey(self, state, roundKey): |
|
971 """ |
|
972 Private method to add (XORs) the round key to the state. |
|
973 |
|
974 @param state state to be changed |
|
975 @type bytearray |
|
976 @param roundKey key to be used for the modification |
|
977 @type bytearray |
|
978 @return modified state |
|
979 @rtype bytearray |
|
980 """ |
|
981 buf = state[:] |
|
982 for i in range(16): |
|
983 buf[i] ^= roundKey[i] |
|
984 return buf |
|
985 |
|
986 def __createRoundKey(self, expandedKey, roundKeyPointer): |
|
987 """ |
|
988 Private method to create a round key. |
|
989 |
|
990 @param expandedKey expanded key to be used |
|
991 @type bytearray |
|
992 @param roundKeyPointer position within the expanded key |
|
993 @type int |
|
994 @return round key |
|
995 @rtype bytearray |
|
996 """ |
|
997 roundKey = bytearray(16) |
|
998 for i in range(4): |
|
999 for j in range(4): |
|
1000 roundKey[j * 4 + i] = expandedKey[roundKeyPointer + i * 4 + j] |
|
1001 return roundKey |
|
1002 |
|
1003 def __galois_multiplication(self, a, b): |
|
1004 """ |
|
1005 Private method to perform a Galois multiplication of 8 bit characters |
|
1006 a and b. |
|
1007 |
|
1008 @param a first factor |
|
1009 @type bytes |
|
1010 @param b second factor |
|
1011 @type bytes |
|
1012 @return result |
|
1013 @rtype bytes |
|
1014 """ |
|
1015 p = 0 |
|
1016 for _counter in range(8): |
|
1017 if b & 1: |
|
1018 p ^= a |
|
1019 hi_bit_set = a & 0x80 |
|
1020 a <<= 1 |
|
1021 # keep a 8 bit |
|
1022 a &= 0xFF |
|
1023 if hi_bit_set: |
|
1024 a ^= 0x1B |
|
1025 b >>= 1 |
|
1026 return p |
|
1027 |
|
1028 def __subBytes(self, state, isInv): |
|
1029 """ |
|
1030 Private method to substitute all the values from the state with the |
|
1031 value in the SBox using the state value as index for the SBox. |
|
1032 |
|
1033 @param state state to be worked on |
|
1034 @type bytearray |
|
1035 @param isInv flag indicating an inverse operation |
|
1036 @type bool |
|
1037 @return modified state |
|
1038 @rtype bytearray |
|
1039 """ |
|
1040 state = state[:] |
|
1041 getter = self.__getSBoxInvert if isInv else self.__getSBoxValue |
|
1042 for i in range(16): |
|
1043 state[i] = getter(state[i]) |
|
1044 return state |
|
1045 |
|
1046 def __shiftRows(self, state, isInv): |
|
1047 """ |
|
1048 Private method to iterate over the 4 rows and call __shiftRow() with |
|
1049 that row. |
|
1050 |
|
1051 @param state state to be worked on |
|
1052 @type bytearray |
|
1053 @param isInv flag indicating an inverse operation |
|
1054 @type bool |
|
1055 @return modified state |
|
1056 @rtype bytearray |
|
1057 """ |
|
1058 state = state[:] |
|
1059 for i in range(4): |
|
1060 state = self.__shiftRow(state, i * 4, i, isInv) |
|
1061 return state |
|
1062 |
|
1063 def __shiftRow(self, state, statePointer, nbr, isInv): |
|
1064 """ |
|
1065 Private method to shift the bytes of a row to the left. |
|
1066 |
|
1067 @param state state to be worked on |
|
1068 @type bytearray |
|
1069 @param statePointer index into the state |
|
1070 @type int |
|
1071 @param nbr number of positions to shift |
|
1072 @type int |
|
1073 @param isInv flag indicating an inverse operation |
|
1074 @type bool |
|
1075 @return modified state |
|
1076 @rtype bytearray |
|
1077 """ |
|
1078 state = state[:] |
|
1079 for _ in range(nbr): |
|
1080 if isInv: |
|
1081 state[statePointer : statePointer + 4] = ( |
|
1082 state[statePointer + 3 : statePointer + 4] |
|
1083 + state[statePointer : statePointer + 3] |
|
1084 ) |
|
1085 else: |
|
1086 state[statePointer : statePointer + 4] = ( |
|
1087 state[statePointer + 1 : statePointer + 4] |
|
1088 + state[statePointer : statePointer + 1] |
|
1089 ) |
|
1090 return state |
|
1091 |
|
1092 def __mixColumns(self, state, isInv): |
|
1093 """ |
|
1094 Private method to perform a galois multiplication of the 4x4 matrix. |
|
1095 |
|
1096 @param state state to be worked on |
|
1097 @type bytearray |
|
1098 @param isInv flag indicating an inverse operation |
|
1099 @type bool |
|
1100 @return modified state |
|
1101 @rtype bytearray |
|
1102 """ |
|
1103 state = state[:] |
|
1104 # iterate over the 4 columns |
|
1105 for i in range(4): |
|
1106 # construct one column by slicing over the 4 rows |
|
1107 column = state[i : i + 16 : 4] |
|
1108 # apply the __mixColumn on one column |
|
1109 column = self.__mixColumn(column, isInv) |
|
1110 # put the values back into the state |
|
1111 state[i : i + 16 : 4] = column |
|
1112 |
|
1113 return state |
|
1114 |
|
1115 # galois multiplication of 1 column of the 4x4 matrix |
|
1116 def __mixColumn(self, column, isInv): |
|
1117 """ |
|
1118 Private method to perform a galois multiplication of 1 column the |
|
1119 4x4 matrix. |
|
1120 |
|
1121 @param column column to be worked on |
|
1122 @type bytearray |
|
1123 @param isInv flag indicating an inverse operation |
|
1124 @type bool |
|
1125 @return modified column |
|
1126 @rtype bytearray |
|
1127 """ |
|
1128 column = column[:] |
|
1129 mult = [14, 9, 13, 11] if isInv else [2, 1, 1, 3] |
|
1130 cpy = column[:] |
|
1131 g = self.__galois_multiplication |
|
1132 |
|
1133 column[0] = ( |
|
1134 g(cpy[0], mult[0]) |
|
1135 ^ g(cpy[3], mult[1]) |
|
1136 ^ g(cpy[2], mult[2]) |
|
1137 ^ g(cpy[1], mult[3]) |
|
1138 ) |
|
1139 column[1] = ( |
|
1140 g(cpy[1], mult[0]) |
|
1141 ^ g(cpy[0], mult[1]) |
|
1142 ^ g(cpy[3], mult[2]) |
|
1143 ^ g(cpy[2], mult[3]) |
|
1144 ) |
|
1145 column[2] = ( |
|
1146 g(cpy[2], mult[0]) |
|
1147 ^ g(cpy[1], mult[1]) |
|
1148 ^ g(cpy[0], mult[2]) |
|
1149 ^ g(cpy[3], mult[3]) |
|
1150 ) |
|
1151 column[3] = ( |
|
1152 g(cpy[3], mult[0]) |
|
1153 ^ g(cpy[2], mult[1]) |
|
1154 ^ g(cpy[1], mult[2]) |
|
1155 ^ g(cpy[0], mult[3]) |
|
1156 ) |
|
1157 return column |
|
1158 |
|
1159 def __aes_round(self, state, roundKey): |
|
1160 """ |
|
1161 Private method to apply the 4 operations of the forward round in |
|
1162 sequence. |
|
1163 |
|
1164 @param state state to be worked on |
|
1165 @type bytearray |
|
1166 @param roundKey round key to be used |
|
1167 @type bytearray |
|
1168 @return modified state |
|
1169 @rtype bytearray |
|
1170 """ |
|
1171 state = self.__subBytes(state, False) |
|
1172 state = self.__shiftRows(state, False) |
|
1173 state = self.__mixColumns(state, False) |
|
1174 state = self.__addRoundKey(state, roundKey) |
|
1175 return state |
|
1176 |
|
1177 def __aes_invRound(self, state, roundKey): |
|
1178 """ |
|
1179 Private method to apply the 4 operations of the inverse round in |
|
1180 sequence. |
|
1181 |
|
1182 @param state state to be worked on |
|
1183 @type bytearray |
|
1184 @param roundKey round key to be used |
|
1185 @type bytearray |
|
1186 @return modified state |
|
1187 @rtype bytearray |
|
1188 """ |
|
1189 state = self.__shiftRows(state, True) |
|
1190 state = self.__subBytes(state, True) |
|
1191 state = self.__addRoundKey(state, roundKey) |
|
1192 state = self.__mixColumns(state, True) |
|
1193 return state |
|
1194 |
|
1195 def __aes_main(self, state, expandedKey, nbrRounds): |
|
1196 """ |
|
1197 Private method to do the AES encryption for one round. |
|
1198 |
|
1199 Perform the initial operations, the standard round, and the |
|
1200 final operations of the forward AES, creating a round key for |
|
1201 each round. |
|
1202 |
|
1203 @param state state to be worked on |
|
1204 @type bytearray |
|
1205 @param expandedKey expanded key to be used |
|
1206 @type bytearray |
|
1207 @param nbrRounds number of rounds to be done |
|
1208 @type int |
|
1209 @return modified state |
|
1210 @rtype bytearray |
|
1211 """ |
|
1212 state = self.__addRoundKey(state, self.__createRoundKey(expandedKey, 0)) |
|
1213 i = 1 |
|
1214 while i < nbrRounds: |
|
1215 state = self.__aes_round(state, self.__createRoundKey(expandedKey, 16 * i)) |
|
1216 i += 1 |
|
1217 state = self.__subBytes(state, False) |
|
1218 state = self.__shiftRows(state, False) |
|
1219 state = self.__addRoundKey( |
|
1220 state, self.__createRoundKey(expandedKey, 16 * nbrRounds) |
|
1221 ) |
|
1222 return state |
|
1223 |
|
1224 def __aes_invMain(self, state, expandedKey, nbrRounds): |
|
1225 """ |
|
1226 Private method to do the inverse AES encryption for one round. |
|
1227 |
|
1228 Perform the initial operations, the standard round, and the |
|
1229 final operations of the inverse AES, creating a round key for |
|
1230 each round. |
|
1231 |
|
1232 @param state state to be worked on |
|
1233 @type bytearray |
|
1234 @param expandedKey expanded key to be used |
|
1235 @type bytearray |
|
1236 @param nbrRounds number of rounds to be done |
|
1237 @type int |
|
1238 @return modified state |
|
1239 @rtype bytearray |
|
1240 """ |
|
1241 state = self.__addRoundKey( |
|
1242 state, self.__createRoundKey(expandedKey, 16 * nbrRounds) |
|
1243 ) |
|
1244 i = nbrRounds - 1 |
|
1245 while i > 0: |
|
1246 state = self.__aes_invRound( |
|
1247 state, self.__createRoundKey(expandedKey, 16 * i) |
|
1248 ) |
|
1249 i -= 1 |
|
1250 state = self.__shiftRows(state, True) |
|
1251 state = self.__subBytes(state, True) |
|
1252 state = self.__addRoundKey(state, self.__createRoundKey(expandedKey, 0)) |
|
1253 return state |
|
1254 |
|
1255 def encrypt(self, iput, key, size): |
|
1256 """ |
|
1257 Public method to encrypt a 128 bit input block against the given key |
|
1258 of size specified. |
|
1259 |
|
1260 @param iput input data |
|
1261 @type bytearray |
|
1262 @param key key to be used |
|
1263 @type bytes or bytearray |
|
1264 @param size key size (16, 24 or 32) |
|
1265 @type int |
|
1266 @return encrypted data |
|
1267 @rtype bytes |
|
1268 @exception ValueError key size is invalid |
|
1269 """ |
|
1270 if size not in self.KeySize.values(): |
|
1271 raise ValueError("Wrong key size given ({0}).".format(size)) |
|
1272 |
|
1273 output = bytearray(16) |
|
1274 # the number of rounds |
|
1275 nbrRounds = 0 |
|
1276 # the 128 bit block to encode |
|
1277 block = bytearray(16) |
|
1278 # set the number of rounds |
|
1279 if size == self.KeySize["SIZE_128"]: |
|
1280 nbrRounds = 10 |
|
1281 elif size == self.KeySize["SIZE_192"]: |
|
1282 nbrRounds = 12 |
|
1283 else: |
|
1284 nbrRounds = 14 |
|
1285 |
|
1286 # the expanded keySize |
|
1287 expandedKeySize = 16 * (nbrRounds + 1) |
|
1288 |
|
1289 # Set the block values, for the block: |
|
1290 # a0,0 a0,1 a0,2 a0,3 |
|
1291 # a1,0 a1,1 a1,2 a1,3 |
|
1292 # a2,0 a2,1 a2,2 a2,3 |
|
1293 # a3,0 a3,1 a3,2 a3,3 |
|
1294 # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 |
|
1295 # |
|
1296 # iterate over the columns |
|
1297 for i in range(4): |
|
1298 # iterate over the rows |
|
1299 for j in range(4): |
|
1300 block[i + j * 4] = iput[i * 4 + j] |
|
1301 |
|
1302 # expand the key into an 176, 208, 240 bytes key |
|
1303 # the expanded key |
|
1304 expandedKey = self.__expandKey(key, size, expandedKeySize) |
|
1305 |
|
1306 # encrypt the block using the expandedKey |
|
1307 block = self.__aes_main(block, expandedKey, nbrRounds) |
|
1308 |
|
1309 # unmap the block again into the output |
|
1310 for kk in range(4): |
|
1311 # iterate over the rows |
|
1312 for ll in range(4): |
|
1313 output[kk * 4 + ll] = block[kk + ll * 4] |
|
1314 return bytes(output) |
|
1315 |
|
1316 # decrypts a 128 bit input block against the given key of size specified |
|
1317 def decrypt(self, iput, key, size): |
|
1318 """ |
|
1319 Public method to decrypt a 128 bit input block against the given key |
|
1320 of size specified. |
|
1321 |
|
1322 @param iput input data |
|
1323 @type bytearray |
|
1324 @param key key to be used |
|
1325 @type bytes or bytearray |
|
1326 @param size key size (16, 24 or 32) |
|
1327 @type int |
|
1328 @return decrypted data |
|
1329 @rtype bytes |
|
1330 @exception ValueError key size is invalid |
|
1331 """ |
|
1332 if size not in self.KeySize.values(): |
|
1333 raise ValueError("Wrong key size given ({0}).".format(size)) |
|
1334 |
|
1335 output = bytearray(16) |
|
1336 # the number of rounds |
|
1337 nbrRounds = 0 |
|
1338 # the 128 bit block to decode |
|
1339 block = bytearray(16) |
|
1340 # set the number of rounds |
|
1341 |
|
1342 if size == self.KeySize["SIZE_128"]: |
|
1343 nbrRounds = 10 |
|
1344 elif size == self.KeySize["SIZE_192"]: |
|
1345 nbrRounds = 12 |
|
1346 else: |
|
1347 nbrRounds = 14 |
|
1348 |
|
1349 # the expanded keySize |
|
1350 expandedKeySize = 16 * (nbrRounds + 1) |
|
1351 |
|
1352 # Set the block values, for the block: |
|
1353 # a0,0 a0,1 a0,2 a0,3 |
|
1354 # a1,0 a1,1 a1,2 a1,3 |
|
1355 # a2,0 a2,1 a2,2 a2,3 |
|
1356 # a3,0 a3,1 a3,2 a3,3 |
|
1357 # the mapping order is a0,0 a1,0 a2,0 a3,0 a0,1 a1,1 ... a2,3 a3,3 |
|
1358 |
|
1359 # iterate over the columns |
|
1360 for i in range(4): |
|
1361 # iterate over the rows |
|
1362 for j in range(4): |
|
1363 block[i + j * 4] = iput[i * 4 + j] |
|
1364 # expand the key into an 176, 208, 240 bytes key |
|
1365 expandedKey = self.__expandKey(key, size, expandedKeySize) |
|
1366 # decrypt the block using the expandedKey |
|
1367 block = self.__aes_invMain(block, expandedKey, nbrRounds) |
|
1368 # unmap the block again into the output |
|
1369 for kk in range(4): |
|
1370 # iterate over the rows |
|
1371 for ll in range(4): |
|
1372 output[kk * 4 + ll] = block[kk + ll * 4] |
|
1373 return output |
|
1374 |
|
1375 |
|
1376 class AESModeOfOperation: |
|
1377 """ |
|
1378 Class implementing the different AES mode of operations. |
|
1379 """ |
|
1380 |
|
1381 aes = AES() |
|
1382 |
|
1383 # structure of supported modes of operation |
|
1384 ModeOfOperation = { |
|
1385 "OFB": 0, |
|
1386 "CFB": 1, |
|
1387 "CBC": 2, |
|
1388 } |
|
1389 |
|
1390 def __extractBytes(self, inputData, start, end, mode): |
|
1391 """ |
|
1392 Private method to extract a range of bytes from the input. |
|
1393 |
|
1394 @param inputData input data |
|
1395 @type bytes |
|
1396 @param start start index |
|
1397 @type int |
|
1398 @param end end index |
|
1399 @type int |
|
1400 @param mode mode of operation (0, 1, 2) |
|
1401 @type int |
|
1402 @return extracted bytes |
|
1403 @rtype bytearray |
|
1404 """ |
|
1405 if end - start > 16: |
|
1406 end = start + 16 |
|
1407 ar = bytearray(16) if mode == self.ModeOfOperation["CBC"] else bytearray() |
|
1408 |
|
1409 i = start |
|
1410 j = 0 |
|
1411 while len(ar) < end - start: |
|
1412 ar.append(0) |
|
1413 while i < end: |
|
1414 ar[j] = inputData[i] |
|
1415 j += 1 |
|
1416 i += 1 |
|
1417 return ar |
|
1418 |
|
1419 def encrypt(self, inputData, mode, key, size, IV): |
|
1420 """ |
|
1421 Public method to perform the encryption operation. |
|
1422 |
|
1423 @param inputData data to be encrypted |
|
1424 @type bytes |
|
1425 @param mode mode of operation (0, 1 or 2) |
|
1426 @type int |
|
1427 @param key key to be used |
|
1428 @type bytes |
|
1429 @param size length of the key (16, 24 or 32) |
|
1430 @type int |
|
1431 @param IV initialisation vector |
|
1432 @type bytearray |
|
1433 @return tuple with mode of operation, length of the input data and |
|
1434 the encrypted data |
|
1435 @rtype tuple of (int, int, bytes) |
|
1436 @exception ValueError key size is invalid or decrypted data is invalid |
|
1437 """ |
|
1438 if len(key) % size: |
|
1439 raise ValueError("Illegal size ({0}) for key '{1}'.".format(size, key)) |
|
1440 if len(IV) % 16: |
|
1441 raise ValueError("IV is not a multiple of 16.") |
|
1442 # the AES input/output |
|
1443 iput = bytearray(16) |
|
1444 output = bytearray() |
|
1445 ciphertext = bytearray(16) |
|
1446 # the output cipher string |
|
1447 cipherOut = bytearray() |
|
1448 # char firstRound |
|
1449 firstRound = True |
|
1450 if inputData: |
|
1451 for j in range(int(math.ceil(float(len(inputData)) / 16))): |
|
1452 start = j * 16 |
|
1453 end = j * 16 + 16 |
|
1454 if end > len(inputData): |
|
1455 end = len(inputData) |
|
1456 plaintext = self.__extractBytes(inputData, start, end, mode) |
|
1457 if mode == self.ModeOfOperation["CFB"]: |
|
1458 if firstRound: |
|
1459 output = self.aes.encrypt(IV, key, size) |
|
1460 firstRound = False |
|
1461 else: |
|
1462 output = self.aes.encrypt(iput, key, size) |
|
1463 for i in range(16): |
|
1464 if len(plaintext) - 1 < i: |
|
1465 ciphertext[i] = 0 ^ output[i] |
|
1466 elif len(output) - 1 < i: |
|
1467 ciphertext[i] = plaintext[i] ^ 0 |
|
1468 elif len(plaintext) - 1 < i and len(output) < i: |
|
1469 ciphertext[i] = 0 ^ 0 |
|
1470 else: |
|
1471 ciphertext[i] = plaintext[i] ^ output[i] |
|
1472 for k in range(end - start): |
|
1473 cipherOut.append(ciphertext[k]) |
|
1474 iput = ciphertext |
|
1475 elif mode == self.ModeOfOperation["OFB"]: |
|
1476 if firstRound: |
|
1477 output = self.aes.encrypt(IV, key, size) |
|
1478 firstRound = False |
|
1479 else: |
|
1480 output = self.aes.encrypt(iput, key, size) |
|
1481 for i in range(16): |
|
1482 if len(plaintext) - 1 < i: |
|
1483 ciphertext[i] = 0 ^ output[i] |
|
1484 elif len(output) - 1 < i: |
|
1485 ciphertext[i] = plaintext[i] ^ 0 |
|
1486 elif len(plaintext) - 1 < i and len(output) < i: |
|
1487 ciphertext[i] = 0 ^ 0 |
|
1488 else: |
|
1489 ciphertext[i] = plaintext[i] ^ output[i] |
|
1490 for k in range(end - start): |
|
1491 cipherOut.append(ciphertext[k]) |
|
1492 iput = output |
|
1493 elif mode == self.ModeOfOperation["CBC"]: |
|
1494 for i in range(16): |
|
1495 if firstRound: |
|
1496 iput[i] = plaintext[i] ^ IV[i] |
|
1497 else: |
|
1498 iput[i] = plaintext[i] ^ ciphertext[i] |
|
1499 firstRound = False |
|
1500 ciphertext = self.aes.encrypt(iput, key, size) |
|
1501 # always 16 bytes because of the padding for CBC |
|
1502 for k in range(16): |
|
1503 cipherOut.append(ciphertext[k]) |
|
1504 return mode, len(inputData), bytes(cipherOut) |
|
1505 |
|
1506 # Mode of Operation Decryption |
|
1507 # cipherIn - Encrypted String |
|
1508 # originalsize - The unencrypted string length - required for CBC |
|
1509 # mode - mode of type modeOfOperation |
|
1510 # key - a number array of the bit length size |
|
1511 # size - the bit length of the key |
|
1512 # IV - the 128 bit number array Initilization Vector |
|
1513 def decrypt(self, cipherIn, originalsize, mode, key, size, IV): |
|
1514 """ |
|
1515 Public method to perform the decryption operation. |
|
1516 |
|
1517 @param cipherIn data to be decrypted |
|
1518 @type bytes |
|
1519 @param originalsize unencrypted string length (required for CBC) |
|
1520 @type int |
|
1521 @param mode mode of operation (0, 1 or 2) |
|
1522 @type int |
|
1523 @param key key to be used |
|
1524 @type bytes |
|
1525 @param size length of the key (16, 24 or 32) |
|
1526 @type int |
|
1527 @param IV initialisation vector |
|
1528 @type bytearray |
|
1529 @return decrypted data |
|
1530 @rtype bytes |
|
1531 @exception ValueError key size is invalid or decrypted data is invalid |
|
1532 """ |
|
1533 if len(key) % size: |
|
1534 raise ValueError("Illegal size ({0}) for key '{1}'.".format(size, key)) |
|
1535 if len(IV) % 16: |
|
1536 raise ValueError("IV is not a multiple of 16.") |
|
1537 # the AES input/output |
|
1538 ciphertext = bytearray() |
|
1539 iput = bytearray() |
|
1540 output = bytearray() |
|
1541 plaintext = bytearray(16) |
|
1542 # the output bytes |
|
1543 bytesOut = bytearray() |
|
1544 # char firstRound |
|
1545 firstRound = True |
|
1546 if cipherIn is not None: |
|
1547 for j in range(int(math.ceil(float(len(cipherIn)) / 16))): |
|
1548 start = j * 16 |
|
1549 end = j * 16 + 16 |
|
1550 if j * 16 + 16 > len(cipherIn): |
|
1551 end = len(cipherIn) |
|
1552 ciphertext = cipherIn[start:end] |
|
1553 if mode == self.ModeOfOperation["CFB"]: |
|
1554 if firstRound: |
|
1555 output = self.aes.encrypt(IV, key, size) |
|
1556 firstRound = False |
|
1557 else: |
|
1558 output = self.aes.encrypt(iput, key, size) |
|
1559 for i in range(16): |
|
1560 if len(output) - 1 < i: |
|
1561 plaintext[i] = 0 ^ ciphertext[i] |
|
1562 elif len(ciphertext) - 1 < i: |
|
1563 plaintext[i] = output[i] ^ 0 |
|
1564 elif len(output) - 1 < i and len(ciphertext) < i: |
|
1565 plaintext[i] = 0 ^ 0 |
|
1566 else: |
|
1567 plaintext[i] = output[i] ^ ciphertext[i] |
|
1568 for k in range(end - start): |
|
1569 bytesOut.append(plaintext[k]) |
|
1570 iput = ciphertext |
|
1571 elif mode == self.ModeOfOperation["OFB"]: |
|
1572 if firstRound: |
|
1573 output = self.aes.encrypt(IV, key, size) |
|
1574 firstRound = False |
|
1575 else: |
|
1576 output = self.aes.encrypt(iput, key, size) |
|
1577 for i in range(16): |
|
1578 if len(output) - 1 < i: |
|
1579 plaintext[i] = 0 ^ ciphertext[i] |
|
1580 elif len(ciphertext) - 1 < i: |
|
1581 plaintext[i] = output[i] ^ 0 |
|
1582 elif len(output) - 1 < i and len(ciphertext) < i: |
|
1583 plaintext[i] = 0 ^ 0 |
|
1584 else: |
|
1585 plaintext[i] = output[i] ^ ciphertext[i] |
|
1586 for k in range(end - start): |
|
1587 bytesOut.append(plaintext[k]) |
|
1588 iput = output |
|
1589 elif mode == self.ModeOfOperation["CBC"]: |
|
1590 output = self.aes.decrypt(ciphertext, key, size) |
|
1591 for i in range(16): |
|
1592 if firstRound: |
|
1593 plaintext[i] = IV[i] ^ output[i] |
|
1594 else: |
|
1595 plaintext[i] = iput[i] ^ output[i] |
|
1596 firstRound = False |
|
1597 if originalsize is not None and originalsize < end: |
|
1598 for k in range(originalsize - start): |
|
1599 bytesOut.append(plaintext[k]) |
|
1600 else: |
|
1601 for k in range(end - start): |
|
1602 bytesOut.append(plaintext[k]) |
|
1603 iput = ciphertext |
|
1604 return bytes(bytesOut) |
|
1605 |
|
1606 |
|
1607 def encryptData(key, data, mode=AESModeOfOperation.ModeOfOperation["CBC"]): |
|
1608 """ |
|
1609 Module function to encrypt the given data with the given key. |
|
1610 |
|
1611 @param key key to be used for encryption |
|
1612 @type bytes |
|
1613 @param data data to be encrypted |
|
1614 @type bytes |
|
1615 @param mode mode of operations (0, 1 or 2) |
|
1616 @type int |
|
1617 @return encrypted data prepended with the initialization vector |
|
1618 @rtype bytes |
|
1619 @exception ValueError raised to indicate an invalid key size |
|
1620 """ |
|
1621 key = bytearray(key) |
|
1622 if mode == AESModeOfOperation.ModeOfOperation["CBC"]: |
|
1623 data = append_PKCS7_padding(data) |
|
1624 keysize = len(key) |
|
1625 if keysize not in AES.KeySize.values(): |
|
1626 raise ValueError("invalid key size: {0}".format(keysize)) |
|
1627 # create a new iv using random data |
|
1628 iv = bytearray(list(os.urandom(16))) |
|
1629 moo = AESModeOfOperation() |
|
1630 _mode, _length, ciph = moo.encrypt(data, mode, key, keysize, iv) |
|
1631 # With padding, the original length does not need to be known. It's a bad |
|
1632 # idea to store the original message length. |
|
1633 # prepend the iv. |
|
1634 return bytes(iv) + bytes(ciph) |
|
1635 |
|
1636 |
|
1637 def decryptData(key, data, mode=AESModeOfOperation.ModeOfOperation["CBC"]): |
|
1638 """ |
|
1639 Module function to decrypt the given data with the given key. |
|
1640 |
|
1641 @param key key to be used for decryption |
|
1642 @type bytes |
|
1643 @param data data to be decrypted (with initialization vector prepended) |
|
1644 @type bytes |
|
1645 @param mode mode of operations (0, 1 or 2) |
|
1646 @type int |
|
1647 @return decrypted data |
|
1648 @rtype bytes |
|
1649 @exception ValueError raised to indicate an invalid key size |
|
1650 """ |
|
1651 key = bytearray(key) |
|
1652 keysize = len(key) |
|
1653 if keysize not in AES.KeySize.values(): |
|
1654 raise ValueError("invalid key size: {0}".format(keysize)) |
|
1655 # iv is first 16 bytes |
|
1656 iv = bytearray(data[:16]) |
|
1657 data = bytearray(data[16:]) |
|
1658 moo = AESModeOfOperation() |
|
1659 decr = moo.decrypt(data, None, mode, key, keysize, iv) |
|
1660 if mode == AESModeOfOperation.ModeOfOperation["CBC"]: |
|
1661 decr = strip_PKCS7_padding(decr) |
|
1662 return bytes(decr) |
|