src/eric7/EricUtilities/crypto/py3AES.py

branch
eric7
changeset 10928
46651e194fbe
parent 10908
ef1b3cd9a6ca
child 11090
f5f5f5803935
equal deleted inserted replaced
10927:ce599998be7d 10928:46651e194fbe
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)

eric ide

mercurial