DLMS-SPODES-client 0.19.35__py3-none-any.whl → 0.19.37__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. DLMS_SPODES_client/FCS16.py +39 -39
  2. DLMS_SPODES_client/__init__.py +12 -12
  3. DLMS_SPODES_client/client.py +2093 -2093
  4. DLMS_SPODES_client/gurux_common/enums/TraceLevel.py +21 -21
  5. DLMS_SPODES_client/gurux_dlms/AesGcmParameter.py +37 -37
  6. DLMS_SPODES_client/gurux_dlms/CountType.py +16 -16
  7. DLMS_SPODES_client/gurux_dlms/GXByteBuffer.py +545 -545
  8. DLMS_SPODES_client/gurux_dlms/GXCiphering.py +196 -196
  9. DLMS_SPODES_client/gurux_dlms/GXDLMS.py +426 -426
  10. DLMS_SPODES_client/gurux_dlms/GXDLMSChippering.py +237 -237
  11. DLMS_SPODES_client/gurux_dlms/GXDLMSChipperingStream.py +977 -977
  12. DLMS_SPODES_client/gurux_dlms/GXDLMSConfirmedServiceError.py +90 -90
  13. DLMS_SPODES_client/gurux_dlms/GXDLMSException.py +139 -139
  14. DLMS_SPODES_client/gurux_dlms/GXDLMSLNParameters.py +33 -33
  15. DLMS_SPODES_client/gurux_dlms/GXDLMSSNParameters.py +21 -21
  16. DLMS_SPODES_client/gurux_dlms/GXDLMSSettings.py +254 -254
  17. DLMS_SPODES_client/gurux_dlms/GXReplyData.py +87 -87
  18. DLMS_SPODES_client/gurux_dlms/HdlcControlFrame.py +9 -9
  19. DLMS_SPODES_client/gurux_dlms/MBusCommand.py +8 -8
  20. DLMS_SPODES_client/gurux_dlms/MBusEncryptionMode.py +27 -27
  21. DLMS_SPODES_client/gurux_dlms/ResponseType.py +8 -8
  22. DLMS_SPODES_client/gurux_dlms/SetResponseType.py +29 -29
  23. DLMS_SPODES_client/gurux_dlms/_HDLCInfo.py +9 -9
  24. DLMS_SPODES_client/gurux_dlms/__init__.py +75 -75
  25. DLMS_SPODES_client/gurux_dlms/enums/Access.py +12 -12
  26. DLMS_SPODES_client/gurux_dlms/enums/ApplicationReference.py +14 -14
  27. DLMS_SPODES_client/gurux_dlms/enums/Authentication.py +41 -41
  28. DLMS_SPODES_client/gurux_dlms/enums/BerType.py +35 -35
  29. DLMS_SPODES_client/gurux_dlms/enums/Command.py +285 -285
  30. DLMS_SPODES_client/gurux_dlms/enums/Definition.py +9 -9
  31. DLMS_SPODES_client/gurux_dlms/enums/ErrorCode.py +46 -46
  32. DLMS_SPODES_client/gurux_dlms/enums/ExceptionServiceError.py +12 -12
  33. DLMS_SPODES_client/gurux_dlms/enums/HardwareResource.py +10 -10
  34. DLMS_SPODES_client/gurux_dlms/enums/HdlcFrameType.py +9 -9
  35. DLMS_SPODES_client/gurux_dlms/enums/Initiate.py +10 -10
  36. DLMS_SPODES_client/gurux_dlms/enums/LoadDataSet.py +13 -13
  37. DLMS_SPODES_client/gurux_dlms/enums/ObjectType.py +306 -306
  38. DLMS_SPODES_client/gurux_dlms/enums/Priority.py +7 -7
  39. DLMS_SPODES_client/gurux_dlms/enums/RequestTypes.py +9 -9
  40. DLMS_SPODES_client/gurux_dlms/enums/Security.py +14 -14
  41. DLMS_SPODES_client/gurux_dlms/enums/Service.py +16 -16
  42. DLMS_SPODES_client/gurux_dlms/enums/ServiceClass.py +9 -9
  43. DLMS_SPODES_client/gurux_dlms/enums/ServiceError.py +8 -8
  44. DLMS_SPODES_client/gurux_dlms/enums/Standard.py +18 -18
  45. DLMS_SPODES_client/gurux_dlms/enums/StateError.py +7 -7
  46. DLMS_SPODES_client/gurux_dlms/enums/Task.py +10 -10
  47. DLMS_SPODES_client/gurux_dlms/enums/VdeStateError.py +10 -10
  48. DLMS_SPODES_client/gurux_dlms/enums/__init__.py +33 -33
  49. DLMS_SPODES_client/gurux_dlms/internal/_GXCommon.py +1673 -1673
  50. DLMS_SPODES_client/logger.py +56 -56
  51. DLMS_SPODES_client/services.py +90 -90
  52. DLMS_SPODES_client/session.py +363 -363
  53. DLMS_SPODES_client/settings.py +48 -48
  54. DLMS_SPODES_client/task.py +1884 -1884
  55. {dlms_spodes_client-0.19.35.dist-info → dlms_spodes_client-0.19.37.dist-info}/METADATA +29 -29
  56. dlms_spodes_client-0.19.37.dist-info/RECORD +61 -0
  57. {dlms_spodes_client-0.19.35.dist-info → dlms_spodes_client-0.19.37.dist-info}/WHEEL +1 -1
  58. dlms_spodes_client-0.19.35.dist-info/RECORD +0 -61
  59. {dlms_spodes_client-0.19.35.dist-info → dlms_spodes_client-0.19.37.dist-info}/entry_points.txt +0 -0
  60. {dlms_spodes_client-0.19.35.dist-info → dlms_spodes_client-0.19.37.dist-info}/top_level.txt +0 -0
@@ -1,977 +1,977 @@
1
- from __future__ import print_function
2
- from .GXByteBuffer import GXByteBuffer
3
- from .enums.Security import Security
4
-
5
-
6
- class GXDLMSChipperingStream:
7
- """
8
- Implements GMAC. This class is based to this doc:
9
- http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
10
- """
11
-
12
- # Consts.
13
- BLOCK_SIZE = 16
14
- TAG_SIZE = 0x10
15
- IV = [0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6]
16
-
17
- #schedule Vector (powers of x).
18
- R_CON = (0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,\
19
- 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,\
20
- 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,\
21
- 0xc5, 0x91)
22
-
23
- #S box
24
- @classmethod
25
- def aes1Encrypt(cls, data: bytearray, offset: int, secret: bytearray):
26
- round_ = 0
27
- i = 0
28
- key = secret.copy()
29
- while round_ < 10:
30
- i = 0
31
- while i < 16:
32
- data[i + offset] = cls.S_BOX[(data[i + offset] ^ key[i]) & 0xFF]
33
- i += 1
34
- buf1 = data[1 + offset]
35
- data[1 + offset] = data[5 + offset]
36
- data[5 + offset] = data[9 + offset]
37
- data[9 + offset] = data[13 + offset]
38
- data[13 + offset] = buf1
39
- buf1 = data[2 + offset]
40
- buf2 = data[6 + offset]
41
- data[2 + offset] = data[10 + offset]
42
- data[6 + offset] = data[14 + offset]
43
- data[10 + offset] = buf1
44
- data[14 + offset] = buf2
45
- buf1 = data[15 + offset]
46
- data[15 + offset] = data[11 + offset]
47
- data[11 + offset] = data[7 + offset]
48
- data[7 + offset] = data[3 + offset]
49
- data[3 + offset] = buf1
50
- if round_ < 9:
51
- i = 0
52
- while i < 4:
53
- buf4 = (i << 2) & 0xFF
54
- buf1 = (data[buf4 + offset] ^ data[buf4 + 1 + offset] ^ data[buf4 + 2 + offset] ^ data[buf4 + 3 + offset]) & 0xFF
55
- buf2 = data[buf4 + offset] & 0xFF
56
- buf3 = (data[buf4 + offset] ^ data[buf4 + 1 + offset]) & 0xFF
57
- buf3 = cls.galoisMultiply(buf3) & 0xFF
58
- data[buf4 + offset] = (data[buf4 + offset] ^ buf3 ^ buf1) & 0xFF
59
- buf3 = (data[buf4 + 1 + offset] ^ data[buf4 + 2 + offset]) & 0xFF
60
- buf3 = cls.galoisMultiply(buf3) & 0xFF
61
- data[buf4 + 1 + offset] = (data[buf4 + 1 + offset] ^ buf3 ^ buf1) & 0xFF
62
- buf3 = (data[buf4 + 2 + offset] ^ data[buf4 + 3 + offset]) & 0xFF
63
- buf3 = cls.galoisMultiply(buf3) & 0xFF
64
- data[buf4 + 2 + offset] = (data[buf4 + 2 + offset] ^ buf3 ^ buf1) & 0xFF
65
- buf3 = (data[buf4 + 3 + offset] ^ buf2) & 0xFF
66
- buf3 = cls.galoisMultiply(buf3) & 0xFF
67
- data[buf4 + 3 + offset] = (data[buf4 + 3 + offset] ^ buf3 ^ buf1) & 0xFF
68
- i += 1
69
- key[0] = (cls.S_BOX[key[13] & 0xFF] ^ key[0] ^ cls.R_CON[round_]) & 0xFF
70
- key[1] = (cls.S_BOX[key[14] & 0xFF] ^ key[1]) & 0xFF
71
- key[2] = (cls.S_BOX[key[15] & 0xFF] ^ key[2]) & 0xFF
72
- key[3] = (cls.S_BOX[key[12] & 0xFF] ^ key[3]) & 0xFF
73
- i = 4
74
- while i < 16:
75
- key[i] = (key[i] ^ key[i - 4]) & 0xFF
76
- i += 1
77
- round_ += 1
78
- i = 0
79
- while i < 16:
80
- data[i + offset] = (data[i + offset] ^ key[i])
81
- i += 1
82
-
83
- S_BOX = (0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,\
84
- 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82,\
85
- 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF,\
86
- 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F,\
87
- 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,\
88
- 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12,\
89
- 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A,\
90
- 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3,\
91
- 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,\
92
- 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF,\
93
- 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,\
94
- 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D,\
95
- 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,\
96
- 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7,\
97
- 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC,\
98
- 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E,\
99
- 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,\
100
- 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8,\
101
- 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA,\
102
- 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6,\
103
- 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,\
104
- 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35,\
105
- 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,\
106
- 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55,\
107
- 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,\
108
- 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16)
109
-
110
- #Inverse sbox
111
- S_BOX_REVERSED = (0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5,\
112
- 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c,\
113
- 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43,\
114
- 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6,\
115
- 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3,\
116
- 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76,\
117
- 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6,\
118
- 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d,\
119
- 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9,\
120
- 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90,\
121
- 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58,\
122
- 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca,\
123
- 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a,\
124
- 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97,\
125
- 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74,\
126
- 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c,\
127
- 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5,\
128
- 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc,\
129
- 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0,\
130
- 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88,\
131
- 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec,\
132
- 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d,\
133
- 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b,\
134
- 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83,\
135
- 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6,\
136
- 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d)
137
-
138
- #Rijndael (AES) Encryption fast table.
139
- AES = (0xa56363c6, 0x847c7cf8, 0x997777ee,\
140
- 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,\
141
- 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7,\
142
- 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f,\
143
- 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e,\
144
- 0x0bf0f0fb, 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45,\
145
- 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, 0xc2b7b775,\
146
- 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e,\
147
- 0x02f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551, 0x34e5e5d1,\
148
- 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,\
149
- 0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830,\
150
- 0xa1969637, 0x0f05050a, 0xb59a9a2f, 0x0907070e, 0x36121224,\
151
- 0x9b80801b, 0x3de2e2df, 0x26ebebcd, 0x6927274e, 0xcdb2b27f,\
152
- 0x9f7575ea, 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34,\
153
- 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, 0xf65252a4,\
154
- 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd,\
155
- 0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x00000000,\
156
- 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6,\
157
- 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94,\
158
- 0xd44c4c98, 0xe85858b0, 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5,\
159
- 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366,\
160
- 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,\
161
- 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2,\
162
- 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21,\
163
- 0x48383870, 0x04f5f5f1, 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf,\
164
- 0x63212142, 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf,\
165
- 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 0xe15f5fbe,\
166
- 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755,\
167
- 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932,\
168
- 0x957373e6, 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3,\
169
- 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, 0xca46468c,\
170
- 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc,\
171
- 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264, 0x4e3a3a74,\
172
- 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,\
173
- 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139,\
174
- 0xa4959531, 0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b,\
175
- 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c,\
176
- 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf,\
177
- 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, 0xd5baba6f,\
178
- 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657,\
179
- 0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8,\
180
- 0x211f1f3e, 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f,\
181
- 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890,\
182
- 0x05030306, 0x01f6f6f7, 0x120e0e1c, 0xa36161c2, 0x5f35356a,\
183
- 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, 0x271d1d3a,\
184
- 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,\
185
- 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d,\
186
- 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa,\
187
- 0x78282850, 0x7adfdfa5, 0x8f8c8c03, 0xf8a1a159, 0x80898909,\
188
- 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,\
189
- 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b,\
190
- 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c)
191
-
192
- AES1_REVERSED = (0x50a7f451, 0x5365417e,\
193
- 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, 0xab58faac,\
194
- 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5,\
195
- 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, 0x495ab1de,\
196
- 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x02752fc3, 0x12f04c81,\
197
- 0xa397468d, 0xc6f9d36b, 0xe75f8f03, 0x959c9215, 0xeb7a6dbf,\
198
- 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e,\
199
- 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be,\
200
- 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5,\
201
- 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe,\
202
- 0x942b08f9, 0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52,\
203
- 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, 0x0728ebb2,\
204
- 0x03c2b52f, 0x9a7bc586, 0xa50837d3, 0xf2872830, 0xb2a5bf23,\
205
- 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3,\
206
- 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4,\
207
- 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b,\
208
- 0xaaef6040, 0x069f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96,\
209
- 0xae053edd, 0x46bde64d, 0xb58d5491, 0x055dc471, 0x6fd40604,\
210
- 0xff155060, 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967,\
211
- 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, 0x470a7ca1,\
212
- 0xe90f427c, 0xc91e84f8, 0x00000000, 0x83868009, 0x48ed2b32,\
213
- 0xac70111e, 0x4e725a6c, 0xfbff0efd, 0x5638850f, 0x1ed5ae3d,\
214
- 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624,\
215
- 0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b, 0x4fc5c080,\
216
- 0xa220dc61, 0x694b775a, 0x161a121c, 0x0aba93e2, 0xe52aa0c0,\
217
- 0x43e0223c, 0x1d171b12, 0x0b0d090e, 0xadc78bf2, 0xb9a8b62d,\
218
- 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3,\
219
- 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b,\
220
- 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342,\
221
- 0x40229713, 0x2011c684, 0x7d244a85, 0xf83dbbd2, 0x1132f9ae,\
222
- 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177,\
223
- 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8,\
224
- 0x1a3ff0a0, 0xd82c7d56, 0xef903322, 0xc74e4987, 0xc1d138d9,\
225
- 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da,\
226
- 0xa4bfad3f, 0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54,\
227
- 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, 0xbe805d9f,\
228
- 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810,\
229
- 0x6e639ce8, 0x7bbb3bdb, 0x097826cd, 0xf418596e, 0x01b79aec,\
230
- 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef,\
231
- 0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431,\
232
- 0x31233f2a, 0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc,\
233
- 0xb0d090e0, 0x15d8a733, 0x4a9804f1, 0xf7daec41, 0x0e50cd7f,\
234
- 0x2ff69117, 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4,\
235
- 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, 0x04ea5e9d,\
236
- 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92,\
237
- 0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859,\
238
- 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a,\
239
- 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753,\
240
- 0x5baafd5f, 0x146f3ddf, 0x86db4478, 0x81f3afca, 0x3ec468b9,\
241
- 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0x0c25e2bc, 0x8b493c28,\
242
- 0x41950dff, 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664,\
243
- 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0)
244
-
245
- blockSize = 16
246
-
247
- #
248
- # * Constructor.
249
- # *
250
- # * @param forSecurity
251
- # * Used security level.
252
- # * @param forEncrypt
253
- # * @param blockCipherKey
254
- # * @param forAad
255
- # * @param iv
256
- # * @param forTag
257
- #
258
- def __init__(self, forSecurity, forEncrypt, blockCipherKey, forAad, iv, forTag):
259
- self.security = forSecurity
260
- self.tag = forTag
261
- if not self.tag:
262
- # Tag size is 12 bytes.
263
- self.tag = bytearray(12)
264
- elif len(self.tag) != 12:
265
- raise ValueError("Invalid tag.")
266
- self.encrypt = forEncrypt
267
- self.workingKey = self.generateKey(forEncrypt, blockCipherKey)
268
- if self.encrypt:
269
- bufLength = GXDLMSChipperingStream.BLOCK_SIZE
270
- else:
271
- bufLength = (GXDLMSChipperingStream.BLOCK_SIZE + GXDLMSChipperingStream.TAG_SIZE)
272
- self.bufBlock = bytearray(bufLength)
273
- self.aad = forAad
274
- self.h = bytearray(GXDLMSChipperingStream.BLOCK_SIZE)
275
- if iv:
276
- self.processBlock(self.h, 0, self.h, 0)
277
- self.mArray = [[None] * 32] * 32
278
- self.init(self.h)
279
- self.j0 = bytearray(16)
280
- self.j0[0:len(iv)] = iv[0:]
281
- self.j0[15] = 0x01
282
- if self.aad:
283
- self.s = self.getGHash(self.aad)
284
- if iv:
285
- self.counter = self.clone(self.j0)
286
- self.bytesRemaining = 0
287
- self.totalLength = 0
288
- self.output = GXByteBuffer()
289
- self.c0 = self.c1 = self.c2 = self.c3 = 0
290
- self.blockSize = 16
291
-
292
- @classmethod
293
- def clone(cls, value):
294
- """ Clone byte array. """
295
- tmp = value[0:]
296
- return tmp
297
-
298
- #
299
- # * Convert byte array to Little Endian.
300
- # *
301
- # * @param data
302
- # * @param offset
303
- # * @return
304
- #
305
- @classmethod
306
- def toUInt32(cls, value, offset):
307
- tmp = value[offset] & 0xFF
308
- tmp |= (value[offset + 1] << 8) & 0xFF00
309
- tmp |= (value[offset + 2] << 16) & 0xFF0000
310
- tmp |= (value[offset + 3] << 24) & 0xFF000000
311
- return tmp
312
-
313
- @classmethod
314
- def subWord(cls, value):
315
- tmp = cls.S_BOX[value & 0xFF] & 0xFF
316
- tmp |= (((cls.S_BOX[(value >> 8) & 0xFF]) & 0xFF) << 8) & 0xFF00
317
- tmp |= (((cls.S_BOX[(value >> 16) & 0xFF]) & 0xFF) << 16) & 0xFF0000
318
- tmp |= (((cls.S_BOX[(value >> 24) & 0xFF]) & 0xFF) << 24) & 0xFF000000
319
- return tmp
320
-
321
- @classmethod
322
- def shift(cls, value, shift):
323
- """
324
- Shift value.
325
- """
326
- return (value >> shift) | (value << (32 - shift)) & 0xFFFFFFFF
327
-
328
- #
329
- # * Initialise the key schedule from the user supplied key.
330
- # *
331
- # * @return
332
- #
333
- @classmethod
334
- def starX(cls, value):
335
- m1 = 0x80808080
336
- m2 = 0x7f7f7f7f
337
- m3 = 0x0000001b
338
- return ((value & m2) << 1) ^ (((value & m1) >> 7) * m3)
339
-
340
- def imixCol(self, x):
341
- f2 = self.starX(x)
342
- f4 = self.starX(f2)
343
- f8 = self.starX(f4)
344
- f9 = x ^ f8
345
- return f2 ^ f4 ^ f8 ^ self.shift(f2 ^ f9, 8) ^ self.shift(f4 ^ f9, 16) ^ self.shift(f9, 24)
346
-
347
- #
348
- # * Get bytes from UIn32.
349
- # *
350
- # * @param value
351
- # * @param data
352
- # * @param offset
353
- #
354
- @classmethod
355
- def getUInt32(cls, value, data, offset):
356
- data[offset] = value & 0xFF
357
- data[offset + 1] = (value >> 8) & 0xFF
358
- data[offset + 2] = (value >> 16) & 0xFF
359
- data[offset + 3] = (value >> 24) & 0xFF
360
-
361
- def unPackBlock(self, bytes_, offset):
362
- self.c0 = self.toUInt32(bytes_, offset)
363
- self.c1 = self.toUInt32(bytes_, offset + 4)
364
- self.c2 = self.toUInt32(bytes_, offset + 8)
365
- self.c3 = self.toUInt32(bytes_, offset + 12)
366
-
367
- def packBlock(self, bytes_, offset):
368
- self.getUInt32(self.c0, bytes_, offset)
369
- self.getUInt32(self.c1, bytes_, offset + 4)
370
- self.getUInt32(self.c2, bytes_, offset + 8)
371
- self.getUInt32(self.c3, bytes_, offset + 12)
372
-
373
- #
374
- # * Encrypt data block.
375
- # *
376
- # * @param key
377
- #
378
- def encryptBlock(self, key):
379
- r = 1
380
- self.c0 ^= key[0][0]
381
- self.c1 ^= key[0][1]
382
- self.c2 ^= key[0][2]
383
- self.c3 ^= key[0][3]
384
- while r < self.rounds - 1:
385
- r0 = (self.AES[self.c0 & 0xFF] & 0xFFFFFFFF)
386
- r0 ^= (self.shift(self.AES[(self.c1 >> 8) & 0xFF], 24) & 0xFFFFFFFF)
387
- r0 ^= (self.shift(self.AES[(self.c2 >> 16) & 0xFF], 16) & 0xFFFFFFFF)
388
- r0 ^= (self.shift(self.AES[(self.c3 >> 24) & 0xFF], 8) & 0xFFFFFFFF)
389
- r0 ^= (key[r][0] & 0xFFFFFFFF)
390
- r1 = (self.AES[self.c1 & 0xFF] & 0xFFFFFFFF)
391
- r1 ^= self.shift(self.AES[(self.c2 >> 8) & 0xFF], 24) & 0xFFFFFFFF
392
- r1 ^= self.shift(self.AES[(self.c3 >> 16) & 0xFF], 16) & 0xFFFFFFFF
393
- r1 ^= self.shift(self.AES[(self.c0 >> 24) & 0xFF], 8) & 0xFFFFFFFF
394
- r1 ^= key[r][1] & 0xFFFFFFFF
395
- r2 = self.AES[self.c2 & 0xFF] & 0xFFFFFFFF
396
- r2 ^= self.shift(self.AES[(self.c3 >> 8) & 0xFF], 24) & 0xFFFFFFFF
397
- r2 ^= self.shift(self.AES[(self.c0 >> 16) & 0xFF], 16) & 0xFFFFFFFF
398
- r2 ^= self.shift(self.AES[(self.c1 >> 24) & 0xFF], 8) & 0xFFFFFFFF
399
- r2 ^= key[r][2] & 0xFFFFFFFF
400
- r3 = self.AES[self.c3 & 0xFF] & 0xFFFFFFFF
401
- r3 ^= self.shift(self.AES[(self.c0 >> 8) & 0xFF], 24) & 0xFFFFFFFF
402
- r3 ^= self.shift(self.AES[(self.c1 >> 16) & 0xFF], 16) & 0xFFFFFFFF
403
- r3 ^= self.shift(self.AES[(self.c2 >> 24) & 0xFF], 8) & 0xFFFFFFFF
404
- r3 ^= key[r][3] & 0xFFFFFFFF
405
- r = r + 1
406
- self.c0 = self.AES[r0 & 0xFF] & 0xFFFFFFFF
407
- self.c0 ^= self.shift(self.AES[(r1 >> 8) & 0xFF], 24) & 0xFFFFFFFF
408
- self.c0 ^= self.shift(self.AES[(r2 >> 16) & 0xFF], 16) & 0xFFFFFFFF
409
- self.c0 ^= self.shift(self.AES[(r3 >> 24) & 0xFF], 8) & 0xFFFFFFFF
410
- self.c0 ^= key[r][0] & 0xFFFFFFFF
411
- self.c1 = self.AES[r1 & 0xFF] & 0xFFFFFFFF
412
- self.c1 ^= self.shift(self.AES[(r2 >> 8) & 0xFF], 24) & 0xFFFFFFFF
413
- self.c1 ^= self.shift(self.AES[(r3 >> 16) & 0xFF], 16) & 0xFFFFFFFF
414
- self.c1 ^= self.shift(self.AES[(r0 >> 24) & 0xFF], 8) & 0xFFFFFFFF
415
- self.c1 ^= key[r][1] & 0xFFFFFFFF
416
- self.c2 = self.AES[r2 & 0xFF] & 0xFFFFFFFF
417
- self.c2 ^= self.shift(self.AES[(r3 >> 8) & 0xFF], 24) & 0xFFFFFFFF
418
- self.c2 ^= self.shift(self.AES[(r0 >> 16) & 0xFF], 16) & 0xFFFFFFFF
419
- self.c2 ^= self.shift(self.AES[(r1 >> 24) & 0xFF], 8) & 0xFFFFFFFF
420
- self.c2 ^= key[r][2] & 0xFFFFFFFF
421
- self.c3 = self.AES[r3 & 0xFF] & 0xFFFFFFFF
422
- self.c3 ^= self.shift(self.AES[(r0 >> 8) & 0xFF], 24) & 0xFFFFFFFF
423
- self.c3 ^= self.shift(self.AES[(r1 >> 16) & 0xFF], 16) & 0xFFFFFFFF
424
- self.c3 ^= self.shift(self.AES[(r2 >> 24) & 0xFF], 8) & 0xFFFFFFFF
425
- self.c3 ^= key[r][3] & 0xFFFFFFFF
426
- r = r + 1
427
-
428
- r0 = self.AES[self.c0 & 0xFF] & 0xFFFFFFFF
429
- r0 ^= self.shift(self.AES[(self.c1 >> 8) & 0xFF], 24) & 0xFFFFFFFF
430
- r0 ^= self.shift(self.AES[(self.c2 >> 16) & 0xFF], 16) & 0xFFFFFFFF
431
- r0 ^= self.shift(self.AES[self.c3 >> 24], 8) & 0xFFFFFFFF
432
- r0 ^= key[r][0] & 0xFFFFFFFF
433
- r1 = self.AES[self.c1 & 0xFF] & 0xFFFFFFFF
434
- r1 ^= self.shift(self.AES[(self.c2 >> 8) & 0xFF], 24) & 0xFFFFFFFF
435
- r1 ^= self.shift(self.AES[(self.c3 >> 16) & 0xFF], 16) & 0xFFFFFFFF
436
- r1 ^= self.shift(self.AES[self.c0 >> 24], 8) & 0xFFFFFFFF
437
- r1 ^= key[r][1] & 0xFFFFFFFF
438
- r2 = self.AES[self.c2 & 0xFF] & 0xFFFFFFFF
439
- r2 ^= self.shift(self.AES[(self.c3 >> 8) & 0xFF], 24) & 0xFFFFFFFF
440
- r2 ^= self.shift(self.AES[(self.c0 >> 16) & 0xFF], 16) & 0xFFFFFFFF
441
- r2 ^= self.shift(self.AES[self.c1 >> 24], 8) & 0xFFFFFFFF
442
- r2 ^= key[r][2] & 0xFFFFFFFF
443
- r3 = self.AES[self.c3 & 0xFF] & 0xFFFFFFFF
444
- r3 ^= self.shift(self.AES[(self.c0 >> 8) & 0xFF], 24) & 0xFFFFFFFF
445
- r3 ^= self.shift(self.AES[(self.c1 >> 16) & 0xFF], 16) & 0xFFFFFFFF
446
- r3 ^= self.shift(self.AES[self.c2 >> 24], 8) & 0xFFFFFFFF
447
- r3 ^= key[r][3] & 0xFFFFFFFF
448
- r += 1
449
- self.c0 = (self.S_BOX[r0 & 0xFF] & 0xFF) & 0xFFFFFFFF
450
- self.c0 ^= ((self.S_BOX[(r1 >> 8) & 0xFF] & 0xFF) << 8) & 0xFFFFFFFF
451
- self.c0 ^= ((self.S_BOX[(r2 >> 16) & 0xFF] & 0xFF) << 16) & 0xFFFFFFFF
452
- self.c0 ^= ((self.S_BOX[r3 >> 24] & 0xFF) << 24) & 0xFFFFFFFF
453
- self.c0 ^= key[r][0] & 0xFFFFFFFF
454
- self.c1 = (self.S_BOX[r1 & 0xFF] & 0xFF) & 0xFFFFFFFF
455
- self.c1 ^= ((self.S_BOX[(r2 >> 8) & 0xFF] & 0xFF) << 8) & 0xFFFFFFFF
456
- self.c1 ^= ((self.S_BOX[(r3 >> 16) & 0xFF] & 0xFF) << 16) & 0xFFFFFFFF
457
- self.c1 ^= ((self.S_BOX[r0 >> 24] & 0xFF) << 24) & 0xFFFFFFFF
458
- self.c1 ^= key[r][1] & 0xFFFFFFFF
459
- self.c2 = (self.S_BOX[r2 & 0xFF] & 0xFF) & 0xFFFFFFFF
460
- self.c2 ^= ((self.S_BOX[(r3 >> 8) & 0xFF] & 0xFF) << 8) & 0xFFFFFFFF
461
- self.c2 ^= ((self.S_BOX[(r0 >> 16) & 0xFF] & 0xFF) << 16) & 0xFFFFFFFF
462
- self.c2 ^= ((self.S_BOX[r1 >> 24] & 0xFF) << 24) & 0xFFFFFFFF
463
- self.c2 ^= key[r][2] & 0xFFFFFFFF
464
- self.c3 = (self.S_BOX[r3 & 0xFF] & 0xFF) & 0xFFFFFFFF
465
- self.c3 ^= ((self.S_BOX[(r0 >> 8) & 0xFF] & 0xFF) << 8) & 0xFFFFFFFF
466
- self.c3 ^= ((self.S_BOX[(r1 >> 16) & 0xFF] & 0xFF) << 16) & 0xFFFFFFFF
467
- self.c3 ^= ((self.S_BOX[r2 >> 24] & 0xFF) << 24) & 0xFFFFFFFF
468
- self.c3 ^= key[r][3] & 0xFFFFFFFF
469
-
470
- def decryptBlock(self, key):
471
- t0 = self.c0 ^ key[self.rounds][0]
472
- t1 = self.c1 ^ key[self.rounds][1]
473
- t2 = self.c2 ^ key[self.rounds][2]
474
- r0 = r1 = r2 = 0
475
- r3 = self.c3 ^ key[self.rounds][3]
476
- r = self.rounds - 1
477
- while r > 1:
478
- r0 = (self.AES1_REVERSED[t0 & 255] & 0xFFFFFFFF) ^ self.shift(self.AES1_REVERSED[(r3 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t2 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t1 >> 24) & 255], 8) ^ key[r][0]
479
- r1 = self.AES1_REVERSED[t1 & 255] ^ self.shift(self.AES1_REVERSED[(t0 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r3 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t2 >> 24) & 255], 8) ^ key[r][1]
480
- r2 = self.AES1_REVERSED[t2 & 255] ^ self.shift(self.AES1_REVERSED[(t1 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t0 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r3 >> 24) & 255], 8) ^ key[r][2]
481
- r3 = self.AES1_REVERSED[r3 & 255] ^ self.shift(self.AES1_REVERSED[(t2 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t1 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t0 >> 24) & 255], 8) ^ key[r][3]
482
- r -= 1
483
- t0 = self.AES1_REVERSED[r0 & 255] ^ self.shift(self.AES1_REVERSED[(r3 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r2 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r1 >> 24) & 255], 8) ^ key[r][0]
484
- t1 = self.AES1_REVERSED[r1 & 255] ^ self.shift(self.AES1_REVERSED[(r0 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r3 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r2 >> 24) & 255], 8) ^ key[r][1]
485
- t2 = self.AES1_REVERSED[r2 & 255] ^ self.shift(self.AES1_REVERSED[(r1 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r0 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r3 >> 24) & 255], 8) ^ key[r][2]
486
- r3 = self.AES1_REVERSED[r3 & 255] ^ self.shift(self.AES1_REVERSED[(r2 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r1 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r0 >> 24) & 255], 8) ^ key[r][3]
487
- r -= 1
488
- r = 1
489
- r0 = self.AES1_REVERSED[t0 & 255] ^ self.shift(self.AES1_REVERSED[(r3 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t2 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t1 >> 24) & 255], 8) ^ key[r][0]
490
- r1 = self.AES1_REVERSED[t1 & 255] ^ self.shift(self.AES1_REVERSED[(t0 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r3 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t2 >> 24) & 255], 8) ^ key[r][1]
491
- r2 = self.AES1_REVERSED[t2 & 255] ^ self.shift(self.AES1_REVERSED[(t1 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t0 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r3 >> 24) & 255], 8) ^ key[r][2]
492
- r3 = self.AES1_REVERSED[r3 & 255] ^ self.shift(self.AES1_REVERSED[(t2 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t1 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t0 >> 24) & 255], 8) ^ key[r][3]
493
- r = 0
494
- self.c0 = (self.S_BOX_REVERSED[r0 & 255] & 0xFF) ^ ((((self.S_BOX_REVERSED[(r3 >> 8) & 255]) & 0xFF) << 8)) ^ ((((self.S_BOX_REVERSED[(r2 >> 16) & 255]) & 0xFF) << 16)) ^ ((((self.S_BOX_REVERSED[(r1 >> 24) & 255]) & 0xFF) << 24)) ^ key[r][0]
495
- self.c1 = (self.S_BOX_REVERSED[r1 & 255] & 0xFF) ^ (((self.S_BOX_REVERSED[(r0 >> 8) & 255]) & 0xFF) << 8) ^ (((self.S_BOX_REVERSED[(r3 >> 16) & 255]) & 0xFF) << 16) ^ (((self.S_BOX_REVERSED[(r2 >> 24) & 255]) & 0xFF) << 24) ^ key[r][1]
496
- self.c2 = (self.S_BOX_REVERSED[r2 & 255] & 0xFF) ^ (((self.S_BOX_REVERSED[(r1 >> 8) & 255]) & 0xFF) << 8) ^ (((self.S_BOX_REVERSED[(r0 >> 16) & 255]) & 0xFF) << 16) ^ (((self.S_BOX_REVERSED[(r3 >> 24) & 255]) & 0xFF) << 24) ^ key[r][2]
497
- self.c3 = (self.S_BOX_REVERSED[r3 & 255] & 0xFF) ^ (((self.S_BOX_REVERSED[(r2 >> 8) & 255]) & 0xFF) << 8) ^ (((self.S_BOX_REVERSED[(r1 >> 16) & 255]) & 0xFF) << 16) ^ (((self.S_BOX_REVERSED[(r0 >> 24) & 255]) & 0xFF) << 24) ^ key[r][3]
498
-
499
- def processBlock(self, input_, inOffset, forOutput, outOffset):
500
- if inOffset + (32 / 2) > len(input_):
501
- raise ValueError("input buffer too short")
502
- if outOffset + (32 / 2) > len(forOutput):
503
- raise ValueError("output buffer too short")
504
- self.unPackBlock(input_, inOffset)
505
- if self.encrypt:
506
- self.encryptBlock(self.workingKey)
507
- else:
508
- self.decryptBlock(self.workingKey)
509
- self.packBlock(forOutput, outOffset)
510
- return self.BLOCK_SIZE
511
-
512
- @classmethod
513
- def bEToUInt32(cls, buff, offset):
514
- value = (buff[offset] << 24)
515
- value |= (buff[offset + 1] << 16) & 0xFF0000
516
- value |= (buff[offset + 2] << 8) & 0xFF00
517
- value |= buff[offset + 3] & 0xFF
518
- return value
519
-
520
- @classmethod
521
- def shiftRight(cls, block, count):
522
- bit = 0
523
- i = 0
524
- while i < 4:
525
- b = block[i]
526
- block[i] = (b >> count) | bit
527
- bit = (b << (32 - count)) & 0xFFFFFFFF
528
- i += 1
529
-
530
- @classmethod
531
- def multiplyP(cls, x):
532
- lsb = (x[3] & 1) != 0
533
- cls.shiftRight(x, 1)
534
- if lsb:
535
- x[0] ^= 0xe1000000
536
-
537
- @classmethod
538
- def getUint128(cls, buff):
539
- us = [None] * 4
540
- us[0] = cls.bEToUInt32(buff, 0)
541
- us[1] = cls.bEToUInt32(buff, 4)
542
- us[2] = cls.bEToUInt32(buff, 8)
543
- us[3] = cls.bEToUInt32(buff, 12)
544
- return us
545
-
546
- @classmethod
547
- def xor(cls, block, value):
548
- pos = 0
549
- while pos != 16:
550
- block[pos] ^= value[pos]
551
- pos += 1
552
-
553
- @classmethod
554
- def xor128(cls, block, value):
555
- pos = 0
556
- while pos != 4:
557
- block[pos] ^= value[pos]
558
- pos += 1
559
-
560
- @classmethod
561
- def multiplyP8(cls, x):
562
- lsw = x[3]
563
- cls.shiftRight(x, 8)
564
- pos = 0
565
- while pos != 8:
566
- if (lsw & (1 << pos)) != 0:
567
- x[0] ^= ((0xe1000000 >> (7 - pos)) & 0xFFFFFFFF)
568
- pos += 1
569
-
570
- def getGHash(self, b):
571
- y = bytearray(16)
572
- pos = 0
573
- while pos < len(b):
574
- x = bytearray(16)
575
- cnt = min(len(b) - pos, 16)
576
- x[0:cnt] = b[pos:pos + cnt]
577
- self.xor(y, x)
578
- self.multiplyH(y)
579
- pos += 16
580
- return y
581
-
582
- @classmethod
583
- def uInt32ToBE(cls, value, buff, offset):
584
- buff[offset] = (value >> 24) & 0xFF
585
- buff[offset + 1] = (value >> 16) & 0xFF
586
- buff[offset + 2] = (value >> 8) & 0xFF
587
- buff[offset + 3] = value & 0xFF
588
-
589
- def multiplyH(self, value):
590
- tmp = [0] * 4
591
- pos = 0
592
- while pos != 16:
593
- m = self.mArray[pos + pos][value[pos] & 0x0f]
594
- tmp[0] ^= m[0]
595
- tmp[1] ^= m[1]
596
- tmp[2] ^= m[2]
597
- tmp[3] ^= m[3]
598
- m = self.mArray[pos + pos + 1][(value[pos] & 0xf0) >> 4]
599
- tmp[0] ^= m[0]
600
- tmp[1] ^= m[1]
601
- tmp[2] ^= m[2]
602
- tmp[3] ^= m[3]
603
- pos += 1
604
- self.uInt32ToBE(tmp[0], value, 0)
605
- self.uInt32ToBE(tmp[1], value, 4)
606
- self.uInt32ToBE(tmp[2], value, 8)
607
- self.uInt32ToBE(tmp[3], value, 12)
608
-
609
- def init(self, value):
610
- self.mArray[0] = [0] * 16
611
- self.mArray[1] = [0] * 16
612
- self.mArray[0][0] = [0] * 4
613
- self.mArray[1][0] = [0] * 4
614
- self.mArray[1][8] = self.getUint128(value)
615
- tmp = []
616
- pos = 4
617
- while pos >= 1:
618
- tmp = self.clone(self.mArray[1][pos + pos])
619
- self.multiplyP(tmp)
620
- self.mArray[1][pos] = tmp
621
- pos >>= 1
622
- tmp = self.clone(self.mArray[1][1])
623
- self.multiplyP(tmp)
624
- self.mArray[0][8] = tmp
625
- pos = 4
626
- while pos >= 1:
627
- tmp = self.clone(self.mArray[0][pos + pos])
628
- self.multiplyP(tmp)
629
- self.mArray[0][pos] = tmp
630
- pos >>= 1
631
- pos1 = 0
632
- while True:
633
- pos2 = 2
634
- while pos2 < 16:
635
- k = 1
636
- while k < pos2:
637
- tmp = self.clone(self.mArray[pos1][pos2])
638
- self.xor128(tmp, self.mArray[pos1][k])
639
- self.mArray[pos1][pos2 + k] = tmp
640
- k += 1
641
- pos2 += pos2
642
- pos1 += 1
643
- if pos1 == 32:
644
- return
645
- if pos1 > 1:
646
- self.mArray[pos1] = [0] * 16
647
- self.mArray[pos1][0] = [0] * 4
648
- pos = 8
649
- while pos > 0:
650
- tmp = self.clone(self.mArray[pos1 - 2][pos])
651
- self.multiplyP8(tmp)
652
- self.mArray[pos1][pos] = tmp
653
- pos >>= 1
654
-
655
-
656
- def gCTRBlock(self, buf, bufCount):
657
- i = 15
658
- while i >= 12:
659
- self.counter[i] += 1
660
- if self.counter[i] != 0:
661
- break
662
- i -= 1
663
- tmp = bytearray(self.BLOCK_SIZE)
664
- self.processBlock(self.counter, 0, tmp, 0)
665
- if self.encrypt:
666
- zeroes = bytearray(self.BLOCK_SIZE)
667
- tmp[bufCount:self.BLOCK_SIZE] = zeroes[bufCount:self.BLOCK_SIZE]
668
- hashBytes = tmp
669
- else:
670
- hashBytes = buf
671
- pos = 0
672
- while pos != bufCount:
673
- tmp[pos] ^= buf[pos]
674
- self.output.setUInt8(tmp[pos])
675
- pos += 1
676
- self.xor(self.s, hashBytes)
677
- self.multiplyH(self.s)
678
- self.totalLength += bufCount
679
-
680
- @classmethod
681
- def setPackLength(cls, length, buff, offset):
682
- cls.uInt32ToBE(int((length >> 32)), buff, offset)
683
- cls.uInt32ToBE(int(length), buff, offset + 4)
684
-
685
- def reset(self):
686
- self.s = self.getGHash(self.aad)
687
- self.counter = self.clone(self.j0)
688
- self.bytesRemaining = 0
689
- self.totalLength = 0
690
-
691
- @classmethod
692
- def tagsEquals(cls, tag1, tag2):
693
- pos = 0
694
- while pos != 12:
695
- if tag1[pos] != tag2[pos]:
696
- return False
697
- pos += 1
698
- return True
699
-
700
- def write(self, input_):
701
- for it in input_:
702
- self.bufBlock[self.bytesRemaining] = it
703
- self.bytesRemaining += 1
704
- if self.bytesRemaining == self.BLOCK_SIZE:
705
- self.gCTRBlock(self.bufBlock, self.BLOCK_SIZE)
706
- if not self.encrypt:
707
- #System.arraycopy(self.bufBlock, self.BLOCK_SIZE,
708
- #self.bufBlock, 0,)
709
- self.bufBlock[0:len(self.tag)] = self.bufBlock[self.blockSize:self.blockSize + len(self.tag)]
710
- self.bytesRemaining = 0
711
-
712
- def flushFinalBlock(self):
713
- if self.bytesRemaining > 0:
714
- tmp = self.bufBlock[0:self.bytesRemaining]
715
- self.gCTRBlock(tmp, self.bytesRemaining)
716
- if self.security == Security.ENCRYPTION:
717
- self.reset()
718
- return self.output.array()
719
- x = bytearray(16)
720
- self.setPackLength(8 * len(self.aad), x, 0)
721
- self.setPackLength(self.totalLength * 8, x, 8)
722
- self.xor(self.s, x)
723
- self.multiplyH(self.s)
724
- generatedTag = bytearray(self.BLOCK_SIZE)
725
- self.processBlock(self.j0, 0, generatedTag, 0)
726
- self.xor(generatedTag, self.s)
727
- if not self.encrypt:
728
- if not self.tagsEquals(self.tag, generatedTag):
729
- print(GXByteBuffer.hex(self.tag, False) + "-" + GXByteBuffer.hex(generatedTag, False))
730
- raise ValueError("Decrypt failed. Invalid tag.")
731
- else:
732
- #Tag size is 12 bytes.
733
- self.tag = generatedTag[0:12]
734
- self.reset()
735
- return self.output.array()
736
-
737
- def generateKey(self, isEncrypt, key):
738
- #Key length in words.
739
- keyLen = int(len(key) / 4)
740
- self.rounds = keyLen + 6
741
- w = [[0 for x in range(4)] for y in range(self.rounds + 1)]
742
- t = 0
743
- i = 0
744
- while i < len(key):
745
- w[t >> 2][t & 3] = self.toUInt32(key, i)
746
- i += 4
747
- t += 1
748
- k = (self.rounds + 1) << 2
749
- i = keyLen
750
- while i < k:
751
- temp = w[(i - 1) >> 2][(i - 1) & 3]
752
- if (i % keyLen) == 0:
753
- temp = self.subWord(self.shift(temp, 8)) ^ (self.R_CON[int(i / keyLen) - 1] & 0xFF)
754
- elif (keyLen > 6) and ((i % keyLen) == 4):
755
- temp = self.subWord(temp)
756
- w[i >> 2][i & 3] = w[(i - keyLen) >> 2][(i - keyLen) & 3] ^ temp
757
- i += 1
758
- if not isEncrypt:
759
- j = 1
760
- while j < self.rounds:
761
- i = 0
762
- while i < 4:
763
- w[j][i] = self.imixCol(w[j][i])
764
- i += 1
765
- j += 1
766
- return w
767
-
768
- @classmethod
769
- def galoisMultiply(cls, value):
770
- if value >> 7 != 0:
771
- value = value << 1
772
- return (value ^ 0x1b) & 0xFF
773
-
774
- return (value << 1) & 0xFF
775
- # temp = (value >> 7) & 0xFF
776
- # temp = temp & 0x1b
777
- # return ((value << 1) ^ temp) & 0xFF
778
-
779
- @classmethod
780
- def aes1Encrypt(cls, data: bytearray, offset: int, secret: bytearray):
781
- round_ = 0
782
- i = 0
783
- key = secret.copy()
784
- while round_ < 10:
785
- i = 0
786
- while i < 16:
787
- data[i + offset] = cls.S_BOX[(data[i + offset] ^ key[i]) & 0xFF]
788
- i += 1
789
- buf1 = data[1 + offset]
790
- data[1 + offset] = data[5 + offset]
791
- data[5 + offset] = data[9 + offset]
792
- data[9 + offset] = data[13 + offset]
793
- data[13 + offset] = buf1
794
- buf1 = data[2 + offset]
795
- buf2 = data[6 + offset]
796
- data[2 + offset] = data[10 + offset]
797
- data[6 + offset] = data[14 + offset]
798
- data[10 + offset] = buf1
799
- data[14 + offset] = buf2
800
- buf1 = data[15 + offset]
801
- data[15 + offset] = data[11 + offset]
802
- data[11 + offset] = data[7 + offset]
803
- data[7 + offset] = data[3 + offset]
804
- data[3 + offset] = buf1
805
- if round_ < 9:
806
- i = 0
807
- while i < 4:
808
- buf4 = (i << 2) & 0xFF
809
- buf1 = (data[buf4 + offset] ^ data[buf4 + 1 + offset] ^ data[buf4 + 2 + offset] ^ data[buf4 + 3 + offset]) & 0xFF
810
- buf2 = data[buf4 + offset] & 0xFF
811
- buf3 = (data[buf4 + offset] ^ data[buf4 + 1 + offset]) & 0xFF
812
- buf3 = cls.galoisMultiply(buf3) & 0xFF
813
- data[buf4 + offset] = (data[buf4 + offset] ^ buf3 ^ buf1) & 0xFF
814
- buf3 = (data[buf4 + 1 + offset] ^ data[buf4 + 2 + offset]) & 0xFF
815
- buf3 = cls.galoisMultiply(buf3) & 0xFF
816
- data[buf4 + 1 + offset] = (data[buf4 + 1 + offset] ^ buf3 ^ buf1) & 0xFF
817
- buf3 = (data[buf4 + 2 + offset] ^ data[buf4 + 3 + offset]) & 0xFF
818
- buf3 = cls.galoisMultiply(buf3) & 0xFF
819
- data[buf4 + 2 + offset] = (data[buf4 + 2 + offset] ^ buf3 ^ buf1) & 0xFF
820
- buf3 = (data[buf4 + 3 + offset] ^ buf2) & 0xFF
821
- buf3 = cls.galoisMultiply(buf3) & 0xFF
822
- data[buf4 + 3 + offset] = (data[buf4 + 3 + offset] ^ buf3 ^ buf1) & 0xFF
823
- i += 1
824
- key[0] = (cls.S_BOX[key[13] & 0xFF] ^ key[0] ^ cls.R_CON[round_]) & 0xFF
825
- key[1] = (cls.S_BOX[key[14] & 0xFF] ^ key[1]) & 0xFF
826
- key[2] = (cls.S_BOX[key[15] & 0xFF] ^ key[2]) & 0xFF
827
- key[3] = (cls.S_BOX[key[12] & 0xFF] ^ key[3]) & 0xFF
828
- i = 4
829
- while i < 16:
830
- key[i] = (key[i] ^ key[i - 4]) & 0xFF
831
- i += 1
832
- round_ += 1
833
- i = 0
834
- while i < 16:
835
- data[i + offset] = (data[i + offset] ^ key[i])
836
- i += 1
837
-
838
- def encryptAes(self, data):
839
- n = len(data) / 8
840
- if (n * 8) != len(data):
841
- raise ValueError("Invalid data.")
842
- iv = bytearray([0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6])
843
- block = bytearray(len(data) + len(iv))
844
- buf = bytearray(8 + len(iv))
845
- block[0:len(self.IV)] = self.IV[0:len(self.IV)]
846
- block[len(self.IV):len(self.IV) + len(data)] = data[0:len(data)]
847
- j = 0
848
- while j != 6:
849
- i = 1
850
- while i <= n:
851
- buf[0:len(self.IV)] = block[0: len(self.IV)]
852
- buf[len(self.IV):8 + len(self.IV)] = block[8 * i:8 * i + 8]
853
- self.processBlock(buf, 0, buf, 0)
854
- t = int(n * j + i)
855
- k = 1
856
- while t != 0:
857
- v = int(t)
858
- buf[len(self.IV) - k] ^= v
859
- t = int(t >> 8)
860
- k += 1
861
- block[0:8] = buf[0:8]
862
- block[8 * i:8 * i + 8] = buf[8:16]
863
- i += 1
864
- j += 1
865
- return block
866
-
867
- def decryptAes(self, input_):
868
- n = len(input_) / 8
869
- if (n * 8) != len(input_):
870
- raise ValueError("Invalid data.")
871
- iv = bytearray([0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6])
872
- if len(input_) > len(iv):
873
- block = bytearray(len(input_) - len(iv))
874
- else:
875
- block = bytearray(len(iv))
876
- a = bytearray(len(iv))
877
- buf = bytearray(8 + len(iv))
878
- a[0:] = input_[0:len(iv)]
879
- block[0:] = input_[len(iv):len(input_)]
880
- n = n - 1
881
- if n == 0:
882
- n = 1
883
- j = 5
884
- while j >= 0:
885
- i = n
886
- while i >= 1:
887
- buf[0:len(iv)] = a[0:len(iv)]
888
- buf[len(iv):8 + len(iv)] = block[8 * int(i - 1):8 * int(i)]
889
- t = n * j + i
890
- k = 1
891
- while t != 0:
892
- v = int(t)
893
- buf[len(self.IV)] ^= v
894
- t = int((int(t) >> 8))
895
- k += 1
896
- self.processBlock(buf, 0, buf, 0)
897
- a[0:] = buf[0:8]
898
- block[8:16] = buf[8 * (i - 1):8*i]
899
- i -= 1
900
- j -= 1
901
- if a != self.IV:
902
- raise ValueError("Invalid data")
903
- return block
904
-
905
- @classmethod
906
- def aes1Decrypt(cls, data, secret):
907
- buf1 = 0
908
- buf2 = 0
909
- buf3 = 0
910
- round_ = 0
911
- i = 0
912
- buf4 = 0
913
- key = secret[0:]
914
- while round_ < 10:
915
- key[0] = int((cls.S_BOX[key[13] & 0xFF] ^ key[0] ^ cls.R_CON[round_]))
916
- key[1] = int((cls.S_BOX[key[14] & 0xFF] ^ key[1]))
917
- key[2] = int((cls.S_BOX[key[15] & 0xFF] ^ key[2]))
918
- key[3] = int((cls.S_BOX[key[12] & 0xFF] ^ key[3]))
919
- while i < 16:
920
- key[i] = int((key[i] ^ key[i - 4]))
921
- i += 1
922
- round_ += 1
923
- while i < 16:
924
- data[i] = int((data[i] ^ key[i]))
925
- i += 1
926
- while round_ < 10:
927
- while i > 3:
928
- key[i] = int((key[i] ^ key[i - 4]))
929
- i -= 1
930
- key[0] = int((cls.S_BOX[key[13] & 0xFF] ^ key[0] ^ cls.R_CON[9 - round_]))
931
- key[1] = int((cls.S_BOX[key[14] & 0xFF] ^ key[1]))
932
- key[2] = int((cls.S_BOX[key[15] & 0xFF] ^ key[2]))
933
- key[3] = int((cls.S_BOX[key[12] & 0xFF] ^ key[3]))
934
- if round_ > 0:
935
- while i < 4:
936
- buf4 = (i << 2) & 0xFF
937
- buf1 = cls.galoisMultiply(cls.galoisMultiply(data[buf4] ^ data[buf4 + 2]))
938
- buf2 = cls.galoisMultiply(cls.galoisMultiply(data[buf4 + 1] ^ data[buf4 + 3]))
939
- data[buf4] ^= buf1
940
- data[buf4 + 1] ^= buf2
941
- data[buf4 + 2] ^= buf1
942
- data[buf4 + 3] ^= buf2
943
- buf1 = int((data[buf4] ^ data[buf4 + 1] ^ data[buf4 + 2] ^ data[buf4 + 3]))
944
- buf2 = data[buf4]
945
- buf3 = int((data[buf4] ^ data[buf4 + 1]))
946
- buf3 = cls.galoisMultiply(buf3)
947
- data[buf4] = int((data[buf4] ^ buf3 ^ buf1))
948
- buf3 = int((data[buf4 + 1] ^ data[buf4 + 2]))
949
- buf3 = cls.galoisMultiply(buf3)
950
- data[buf4 + 1] = int((data[buf4 + 1] ^ buf3 ^ buf1))
951
- buf3 = int((data[buf4 + 2] ^ data[buf4 + 3]))
952
- buf3 = cls.galoisMultiply(buf3)
953
- data[buf4 + 2] = int((data[buf4 + 2] ^ buf3 ^ buf1))
954
- buf3 = int((data[buf4 + 3] ^ buf2))
955
- buf3 = cls.galoisMultiply(buf3)
956
- data[buf4 + 3] = int((data[buf4 + 3] ^ buf3 ^ buf1))
957
- i += 1
958
- buf1 = data[13]
959
- data[13] = data[9]
960
- data[9] = data[5]
961
- data[5] = data[1]
962
- data[1] = buf1
963
- buf1 = data[10]
964
- buf2 = data[14]
965
- data[10] = data[2]
966
- data[14] = data[6]
967
- data[2] = buf1
968
- data[6] = buf2
969
- buf1 = data[3]
970
- data[3] = data[7]
971
- data[7] = data[11]
972
- data[11] = data[15]
973
- data[15] = buf1
974
- while i < 16:
975
- data[i] = int((cls.S_BOX_REVERSED[data[i] & 0xFF] ^ key[i]))
976
- i += 1
977
- round_ += 1
1
+ from __future__ import print_function
2
+ from .GXByteBuffer import GXByteBuffer
3
+ from .enums.Security import Security
4
+
5
+
6
+ class GXDLMSChipperingStream:
7
+ """
8
+ Implements GMAC. This class is based to this doc:
9
+ http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
10
+ """
11
+
12
+ # Consts.
13
+ BLOCK_SIZE = 16
14
+ TAG_SIZE = 0x10
15
+ IV = [0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6]
16
+
17
+ #schedule Vector (powers of x).
18
+ R_CON = (0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,\
19
+ 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc,\
20
+ 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,\
21
+ 0xc5, 0x91)
22
+
23
+ #S box
24
+ @classmethod
25
+ def aes1Encrypt(cls, data: bytearray, offset: int, secret: bytearray):
26
+ round_ = 0
27
+ i = 0
28
+ key = secret.copy()
29
+ while round_ < 10:
30
+ i = 0
31
+ while i < 16:
32
+ data[i + offset] = cls.S_BOX[(data[i + offset] ^ key[i]) & 0xFF]
33
+ i += 1
34
+ buf1 = data[1 + offset]
35
+ data[1 + offset] = data[5 + offset]
36
+ data[5 + offset] = data[9 + offset]
37
+ data[9 + offset] = data[13 + offset]
38
+ data[13 + offset] = buf1
39
+ buf1 = data[2 + offset]
40
+ buf2 = data[6 + offset]
41
+ data[2 + offset] = data[10 + offset]
42
+ data[6 + offset] = data[14 + offset]
43
+ data[10 + offset] = buf1
44
+ data[14 + offset] = buf2
45
+ buf1 = data[15 + offset]
46
+ data[15 + offset] = data[11 + offset]
47
+ data[11 + offset] = data[7 + offset]
48
+ data[7 + offset] = data[3 + offset]
49
+ data[3 + offset] = buf1
50
+ if round_ < 9:
51
+ i = 0
52
+ while i < 4:
53
+ buf4 = (i << 2) & 0xFF
54
+ buf1 = (data[buf4 + offset] ^ data[buf4 + 1 + offset] ^ data[buf4 + 2 + offset] ^ data[buf4 + 3 + offset]) & 0xFF
55
+ buf2 = data[buf4 + offset] & 0xFF
56
+ buf3 = (data[buf4 + offset] ^ data[buf4 + 1 + offset]) & 0xFF
57
+ buf3 = cls.galoisMultiply(buf3) & 0xFF
58
+ data[buf4 + offset] = (data[buf4 + offset] ^ buf3 ^ buf1) & 0xFF
59
+ buf3 = (data[buf4 + 1 + offset] ^ data[buf4 + 2 + offset]) & 0xFF
60
+ buf3 = cls.galoisMultiply(buf3) & 0xFF
61
+ data[buf4 + 1 + offset] = (data[buf4 + 1 + offset] ^ buf3 ^ buf1) & 0xFF
62
+ buf3 = (data[buf4 + 2 + offset] ^ data[buf4 + 3 + offset]) & 0xFF
63
+ buf3 = cls.galoisMultiply(buf3) & 0xFF
64
+ data[buf4 + 2 + offset] = (data[buf4 + 2 + offset] ^ buf3 ^ buf1) & 0xFF
65
+ buf3 = (data[buf4 + 3 + offset] ^ buf2) & 0xFF
66
+ buf3 = cls.galoisMultiply(buf3) & 0xFF
67
+ data[buf4 + 3 + offset] = (data[buf4 + 3 + offset] ^ buf3 ^ buf1) & 0xFF
68
+ i += 1
69
+ key[0] = (cls.S_BOX[key[13] & 0xFF] ^ key[0] ^ cls.R_CON[round_]) & 0xFF
70
+ key[1] = (cls.S_BOX[key[14] & 0xFF] ^ key[1]) & 0xFF
71
+ key[2] = (cls.S_BOX[key[15] & 0xFF] ^ key[2]) & 0xFF
72
+ key[3] = (cls.S_BOX[key[12] & 0xFF] ^ key[3]) & 0xFF
73
+ i = 4
74
+ while i < 16:
75
+ key[i] = (key[i] ^ key[i - 4]) & 0xFF
76
+ i += 1
77
+ round_ += 1
78
+ i = 0
79
+ while i < 16:
80
+ data[i + offset] = (data[i + offset] ^ key[i])
81
+ i += 1
82
+
83
+ S_BOX = (0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,\
84
+ 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82,\
85
+ 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF,\
86
+ 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F,\
87
+ 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,\
88
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12,\
89
+ 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A,\
90
+ 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3,\
91
+ 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,\
92
+ 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF,\
93
+ 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,\
94
+ 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D,\
95
+ 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,\
96
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7,\
97
+ 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC,\
98
+ 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E,\
99
+ 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,\
100
+ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8,\
101
+ 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA,\
102
+ 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6,\
103
+ 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,\
104
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35,\
105
+ 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,\
106
+ 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55,\
107
+ 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,\
108
+ 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16)
109
+
110
+ #Inverse sbox
111
+ S_BOX_REVERSED = (0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5,\
112
+ 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c,\
113
+ 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43,\
114
+ 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6,\
115
+ 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3,\
116
+ 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76,\
117
+ 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6,\
118
+ 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d,\
119
+ 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9,\
120
+ 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90,\
121
+ 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58,\
122
+ 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca,\
123
+ 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a,\
124
+ 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97,\
125
+ 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74,\
126
+ 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c,\
127
+ 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5,\
128
+ 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc,\
129
+ 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0,\
130
+ 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88,\
131
+ 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec,\
132
+ 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d,\
133
+ 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b,\
134
+ 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83,\
135
+ 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6,\
136
+ 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d)
137
+
138
+ #Rijndael (AES) Encryption fast table.
139
+ AES = (0xa56363c6, 0x847c7cf8, 0x997777ee,\
140
+ 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591,\
141
+ 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7,\
142
+ 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f,\
143
+ 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e,\
144
+ 0x0bf0f0fb, 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45,\
145
+ 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, 0xc2b7b775,\
146
+ 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e,\
147
+ 0x02f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551, 0x34e5e5d1,\
148
+ 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,\
149
+ 0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830,\
150
+ 0xa1969637, 0x0f05050a, 0xb59a9a2f, 0x0907070e, 0x36121224,\
151
+ 0x9b80801b, 0x3de2e2df, 0x26ebebcd, 0x6927274e, 0xcdb2b27f,\
152
+ 0x9f7575ea, 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34,\
153
+ 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, 0xf65252a4,\
154
+ 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd,\
155
+ 0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x00000000,\
156
+ 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6,\
157
+ 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94,\
158
+ 0xd44c4c98, 0xe85858b0, 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5,\
159
+ 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366,\
160
+ 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,\
161
+ 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2,\
162
+ 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21,\
163
+ 0x48383870, 0x04f5f5f1, 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf,\
164
+ 0x63212142, 0x30101020, 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf,\
165
+ 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 0xe15f5fbe,\
166
+ 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755,\
167
+ 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932,\
168
+ 0x957373e6, 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3,\
169
+ 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, 0xca46468c,\
170
+ 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc,\
171
+ 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264, 0x4e3a3a74,\
172
+ 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,\
173
+ 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139,\
174
+ 0xa4959531, 0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b,\
175
+ 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c,\
176
+ 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf,\
177
+ 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, 0xd5baba6f,\
178
+ 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657,\
179
+ 0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8,\
180
+ 0x211f1f3e, 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f,\
181
+ 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890,\
182
+ 0x05030306, 0x01f6f6f7, 0x120e0e1c, 0xa36161c2, 0x5f35356a,\
183
+ 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, 0x271d1d3a,\
184
+ 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,\
185
+ 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d,\
186
+ 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa,\
187
+ 0x78282850, 0x7adfdfa5, 0x8f8c8c03, 0xf8a1a159, 0x80898909,\
188
+ 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0,\
189
+ 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b,\
190
+ 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c)
191
+
192
+ AES1_REVERSED = (0x50a7f451, 0x5365417e,\
193
+ 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, 0xab58faac,\
194
+ 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5,\
195
+ 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, 0x495ab1de,\
196
+ 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x02752fc3, 0x12f04c81,\
197
+ 0xa397468d, 0xc6f9d36b, 0xe75f8f03, 0x959c9215, 0xeb7a6dbf,\
198
+ 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e,\
199
+ 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be,\
200
+ 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5,\
201
+ 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe,\
202
+ 0x942b08f9, 0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52,\
203
+ 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, 0x0728ebb2,\
204
+ 0x03c2b52f, 0x9a7bc586, 0xa50837d3, 0xf2872830, 0xb2a5bf23,\
205
+ 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3,\
206
+ 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4,\
207
+ 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b,\
208
+ 0xaaef6040, 0x069f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96,\
209
+ 0xae053edd, 0x46bde64d, 0xb58d5491, 0x055dc471, 0x6fd40604,\
210
+ 0xff155060, 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967,\
211
+ 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, 0x470a7ca1,\
212
+ 0xe90f427c, 0xc91e84f8, 0x00000000, 0x83868009, 0x48ed2b32,\
213
+ 0xac70111e, 0x4e725a6c, 0xfbff0efd, 0x5638850f, 0x1ed5ae3d,\
214
+ 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624,\
215
+ 0xb1670a0c, 0x0fe75793, 0xd296eeb4, 0x9e919b1b, 0x4fc5c080,\
216
+ 0xa220dc61, 0x694b775a, 0x161a121c, 0x0aba93e2, 0xe52aa0c0,\
217
+ 0x43e0223c, 0x1d171b12, 0x0b0d090e, 0xadc78bf2, 0xb9a8b62d,\
218
+ 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3,\
219
+ 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b,\
220
+ 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342,\
221
+ 0x40229713, 0x2011c684, 0x7d244a85, 0xf83dbbd2, 0x1132f9ae,\
222
+ 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177,\
223
+ 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8,\
224
+ 0x1a3ff0a0, 0xd82c7d56, 0xef903322, 0xc74e4987, 0xc1d138d9,\
225
+ 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da,\
226
+ 0xa4bfad3f, 0xe49d3a2c, 0x0d927850, 0x9bcc5f6a, 0x62467e54,\
227
+ 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, 0xbe805d9f,\
228
+ 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810,\
229
+ 0x6e639ce8, 0x7bbb3bdb, 0x097826cd, 0xf418596e, 0x01b79aec,\
230
+ 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x08cfbc21, 0xe6e815ef,\
231
+ 0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431,\
232
+ 0x31233f2a, 0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc,\
233
+ 0xb0d090e0, 0x15d8a733, 0x4a9804f1, 0xf7daec41, 0x0e50cd7f,\
234
+ 0x2ff69117, 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4,\
235
+ 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, 0x04ea5e9d,\
236
+ 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92,\
237
+ 0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859,\
238
+ 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a,\
239
+ 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753,\
240
+ 0x5baafd5f, 0x146f3ddf, 0x86db4478, 0x81f3afca, 0x3ec468b9,\
241
+ 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0x0c25e2bc, 0x8b493c28,\
242
+ 0x41950dff, 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664,\
243
+ 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0)
244
+
245
+ blockSize = 16
246
+
247
+ #
248
+ # * Constructor.
249
+ # *
250
+ # * @param forSecurity
251
+ # * Used security level.
252
+ # * @param forEncrypt
253
+ # * @param blockCipherKey
254
+ # * @param forAad
255
+ # * @param iv
256
+ # * @param forTag
257
+ #
258
+ def __init__(self, forSecurity, forEncrypt, blockCipherKey, forAad, iv, forTag):
259
+ self.security = forSecurity
260
+ self.tag = forTag
261
+ if not self.tag:
262
+ # Tag size is 12 bytes.
263
+ self.tag = bytearray(12)
264
+ elif len(self.tag) != 12:
265
+ raise ValueError("Invalid tag.")
266
+ self.encrypt = forEncrypt
267
+ self.workingKey = self.generateKey(forEncrypt, blockCipherKey)
268
+ if self.encrypt:
269
+ bufLength = GXDLMSChipperingStream.BLOCK_SIZE
270
+ else:
271
+ bufLength = (GXDLMSChipperingStream.BLOCK_SIZE + GXDLMSChipperingStream.TAG_SIZE)
272
+ self.bufBlock = bytearray(bufLength)
273
+ self.aad = forAad
274
+ self.h = bytearray(GXDLMSChipperingStream.BLOCK_SIZE)
275
+ if iv:
276
+ self.processBlock(self.h, 0, self.h, 0)
277
+ self.mArray = [[None] * 32] * 32
278
+ self.init(self.h)
279
+ self.j0 = bytearray(16)
280
+ self.j0[0:len(iv)] = iv[0:]
281
+ self.j0[15] = 0x01
282
+ if self.aad:
283
+ self.s = self.getGHash(self.aad)
284
+ if iv:
285
+ self.counter = self.clone(self.j0)
286
+ self.bytesRemaining = 0
287
+ self.totalLength = 0
288
+ self.output = GXByteBuffer()
289
+ self.c0 = self.c1 = self.c2 = self.c3 = 0
290
+ self.blockSize = 16
291
+
292
+ @classmethod
293
+ def clone(cls, value):
294
+ """ Clone byte array. """
295
+ tmp = value[0:]
296
+ return tmp
297
+
298
+ #
299
+ # * Convert byte array to Little Endian.
300
+ # *
301
+ # * @param data
302
+ # * @param offset
303
+ # * @return
304
+ #
305
+ @classmethod
306
+ def toUInt32(cls, value, offset):
307
+ tmp = value[offset] & 0xFF
308
+ tmp |= (value[offset + 1] << 8) & 0xFF00
309
+ tmp |= (value[offset + 2] << 16) & 0xFF0000
310
+ tmp |= (value[offset + 3] << 24) & 0xFF000000
311
+ return tmp
312
+
313
+ @classmethod
314
+ def subWord(cls, value):
315
+ tmp = cls.S_BOX[value & 0xFF] & 0xFF
316
+ tmp |= (((cls.S_BOX[(value >> 8) & 0xFF]) & 0xFF) << 8) & 0xFF00
317
+ tmp |= (((cls.S_BOX[(value >> 16) & 0xFF]) & 0xFF) << 16) & 0xFF0000
318
+ tmp |= (((cls.S_BOX[(value >> 24) & 0xFF]) & 0xFF) << 24) & 0xFF000000
319
+ return tmp
320
+
321
+ @classmethod
322
+ def shift(cls, value, shift):
323
+ """
324
+ Shift value.
325
+ """
326
+ return (value >> shift) | (value << (32 - shift)) & 0xFFFFFFFF
327
+
328
+ #
329
+ # * Initialise the key schedule from the user supplied key.
330
+ # *
331
+ # * @return
332
+ #
333
+ @classmethod
334
+ def starX(cls, value):
335
+ m1 = 0x80808080
336
+ m2 = 0x7f7f7f7f
337
+ m3 = 0x0000001b
338
+ return ((value & m2) << 1) ^ (((value & m1) >> 7) * m3)
339
+
340
+ def imixCol(self, x):
341
+ f2 = self.starX(x)
342
+ f4 = self.starX(f2)
343
+ f8 = self.starX(f4)
344
+ f9 = x ^ f8
345
+ return f2 ^ f4 ^ f8 ^ self.shift(f2 ^ f9, 8) ^ self.shift(f4 ^ f9, 16) ^ self.shift(f9, 24)
346
+
347
+ #
348
+ # * Get bytes from UIn32.
349
+ # *
350
+ # * @param value
351
+ # * @param data
352
+ # * @param offset
353
+ #
354
+ @classmethod
355
+ def getUInt32(cls, value, data, offset):
356
+ data[offset] = value & 0xFF
357
+ data[offset + 1] = (value >> 8) & 0xFF
358
+ data[offset + 2] = (value >> 16) & 0xFF
359
+ data[offset + 3] = (value >> 24) & 0xFF
360
+
361
+ def unPackBlock(self, bytes_, offset):
362
+ self.c0 = self.toUInt32(bytes_, offset)
363
+ self.c1 = self.toUInt32(bytes_, offset + 4)
364
+ self.c2 = self.toUInt32(bytes_, offset + 8)
365
+ self.c3 = self.toUInt32(bytes_, offset + 12)
366
+
367
+ def packBlock(self, bytes_, offset):
368
+ self.getUInt32(self.c0, bytes_, offset)
369
+ self.getUInt32(self.c1, bytes_, offset + 4)
370
+ self.getUInt32(self.c2, bytes_, offset + 8)
371
+ self.getUInt32(self.c3, bytes_, offset + 12)
372
+
373
+ #
374
+ # * Encrypt data block.
375
+ # *
376
+ # * @param key
377
+ #
378
+ def encryptBlock(self, key):
379
+ r = 1
380
+ self.c0 ^= key[0][0]
381
+ self.c1 ^= key[0][1]
382
+ self.c2 ^= key[0][2]
383
+ self.c3 ^= key[0][3]
384
+ while r < self.rounds - 1:
385
+ r0 = (self.AES[self.c0 & 0xFF] & 0xFFFFFFFF)
386
+ r0 ^= (self.shift(self.AES[(self.c1 >> 8) & 0xFF], 24) & 0xFFFFFFFF)
387
+ r0 ^= (self.shift(self.AES[(self.c2 >> 16) & 0xFF], 16) & 0xFFFFFFFF)
388
+ r0 ^= (self.shift(self.AES[(self.c3 >> 24) & 0xFF], 8) & 0xFFFFFFFF)
389
+ r0 ^= (key[r][0] & 0xFFFFFFFF)
390
+ r1 = (self.AES[self.c1 & 0xFF] & 0xFFFFFFFF)
391
+ r1 ^= self.shift(self.AES[(self.c2 >> 8) & 0xFF], 24) & 0xFFFFFFFF
392
+ r1 ^= self.shift(self.AES[(self.c3 >> 16) & 0xFF], 16) & 0xFFFFFFFF
393
+ r1 ^= self.shift(self.AES[(self.c0 >> 24) & 0xFF], 8) & 0xFFFFFFFF
394
+ r1 ^= key[r][1] & 0xFFFFFFFF
395
+ r2 = self.AES[self.c2 & 0xFF] & 0xFFFFFFFF
396
+ r2 ^= self.shift(self.AES[(self.c3 >> 8) & 0xFF], 24) & 0xFFFFFFFF
397
+ r2 ^= self.shift(self.AES[(self.c0 >> 16) & 0xFF], 16) & 0xFFFFFFFF
398
+ r2 ^= self.shift(self.AES[(self.c1 >> 24) & 0xFF], 8) & 0xFFFFFFFF
399
+ r2 ^= key[r][2] & 0xFFFFFFFF
400
+ r3 = self.AES[self.c3 & 0xFF] & 0xFFFFFFFF
401
+ r3 ^= self.shift(self.AES[(self.c0 >> 8) & 0xFF], 24) & 0xFFFFFFFF
402
+ r3 ^= self.shift(self.AES[(self.c1 >> 16) & 0xFF], 16) & 0xFFFFFFFF
403
+ r3 ^= self.shift(self.AES[(self.c2 >> 24) & 0xFF], 8) & 0xFFFFFFFF
404
+ r3 ^= key[r][3] & 0xFFFFFFFF
405
+ r = r + 1
406
+ self.c0 = self.AES[r0 & 0xFF] & 0xFFFFFFFF
407
+ self.c0 ^= self.shift(self.AES[(r1 >> 8) & 0xFF], 24) & 0xFFFFFFFF
408
+ self.c0 ^= self.shift(self.AES[(r2 >> 16) & 0xFF], 16) & 0xFFFFFFFF
409
+ self.c0 ^= self.shift(self.AES[(r3 >> 24) & 0xFF], 8) & 0xFFFFFFFF
410
+ self.c0 ^= key[r][0] & 0xFFFFFFFF
411
+ self.c1 = self.AES[r1 & 0xFF] & 0xFFFFFFFF
412
+ self.c1 ^= self.shift(self.AES[(r2 >> 8) & 0xFF], 24) & 0xFFFFFFFF
413
+ self.c1 ^= self.shift(self.AES[(r3 >> 16) & 0xFF], 16) & 0xFFFFFFFF
414
+ self.c1 ^= self.shift(self.AES[(r0 >> 24) & 0xFF], 8) & 0xFFFFFFFF
415
+ self.c1 ^= key[r][1] & 0xFFFFFFFF
416
+ self.c2 = self.AES[r2 & 0xFF] & 0xFFFFFFFF
417
+ self.c2 ^= self.shift(self.AES[(r3 >> 8) & 0xFF], 24) & 0xFFFFFFFF
418
+ self.c2 ^= self.shift(self.AES[(r0 >> 16) & 0xFF], 16) & 0xFFFFFFFF
419
+ self.c2 ^= self.shift(self.AES[(r1 >> 24) & 0xFF], 8) & 0xFFFFFFFF
420
+ self.c2 ^= key[r][2] & 0xFFFFFFFF
421
+ self.c3 = self.AES[r3 & 0xFF] & 0xFFFFFFFF
422
+ self.c3 ^= self.shift(self.AES[(r0 >> 8) & 0xFF], 24) & 0xFFFFFFFF
423
+ self.c3 ^= self.shift(self.AES[(r1 >> 16) & 0xFF], 16) & 0xFFFFFFFF
424
+ self.c3 ^= self.shift(self.AES[(r2 >> 24) & 0xFF], 8) & 0xFFFFFFFF
425
+ self.c3 ^= key[r][3] & 0xFFFFFFFF
426
+ r = r + 1
427
+
428
+ r0 = self.AES[self.c0 & 0xFF] & 0xFFFFFFFF
429
+ r0 ^= self.shift(self.AES[(self.c1 >> 8) & 0xFF], 24) & 0xFFFFFFFF
430
+ r0 ^= self.shift(self.AES[(self.c2 >> 16) & 0xFF], 16) & 0xFFFFFFFF
431
+ r0 ^= self.shift(self.AES[self.c3 >> 24], 8) & 0xFFFFFFFF
432
+ r0 ^= key[r][0] & 0xFFFFFFFF
433
+ r1 = self.AES[self.c1 & 0xFF] & 0xFFFFFFFF
434
+ r1 ^= self.shift(self.AES[(self.c2 >> 8) & 0xFF], 24) & 0xFFFFFFFF
435
+ r1 ^= self.shift(self.AES[(self.c3 >> 16) & 0xFF], 16) & 0xFFFFFFFF
436
+ r1 ^= self.shift(self.AES[self.c0 >> 24], 8) & 0xFFFFFFFF
437
+ r1 ^= key[r][1] & 0xFFFFFFFF
438
+ r2 = self.AES[self.c2 & 0xFF] & 0xFFFFFFFF
439
+ r2 ^= self.shift(self.AES[(self.c3 >> 8) & 0xFF], 24) & 0xFFFFFFFF
440
+ r2 ^= self.shift(self.AES[(self.c0 >> 16) & 0xFF], 16) & 0xFFFFFFFF
441
+ r2 ^= self.shift(self.AES[self.c1 >> 24], 8) & 0xFFFFFFFF
442
+ r2 ^= key[r][2] & 0xFFFFFFFF
443
+ r3 = self.AES[self.c3 & 0xFF] & 0xFFFFFFFF
444
+ r3 ^= self.shift(self.AES[(self.c0 >> 8) & 0xFF], 24) & 0xFFFFFFFF
445
+ r3 ^= self.shift(self.AES[(self.c1 >> 16) & 0xFF], 16) & 0xFFFFFFFF
446
+ r3 ^= self.shift(self.AES[self.c2 >> 24], 8) & 0xFFFFFFFF
447
+ r3 ^= key[r][3] & 0xFFFFFFFF
448
+ r += 1
449
+ self.c0 = (self.S_BOX[r0 & 0xFF] & 0xFF) & 0xFFFFFFFF
450
+ self.c0 ^= ((self.S_BOX[(r1 >> 8) & 0xFF] & 0xFF) << 8) & 0xFFFFFFFF
451
+ self.c0 ^= ((self.S_BOX[(r2 >> 16) & 0xFF] & 0xFF) << 16) & 0xFFFFFFFF
452
+ self.c0 ^= ((self.S_BOX[r3 >> 24] & 0xFF) << 24) & 0xFFFFFFFF
453
+ self.c0 ^= key[r][0] & 0xFFFFFFFF
454
+ self.c1 = (self.S_BOX[r1 & 0xFF] & 0xFF) & 0xFFFFFFFF
455
+ self.c1 ^= ((self.S_BOX[(r2 >> 8) & 0xFF] & 0xFF) << 8) & 0xFFFFFFFF
456
+ self.c1 ^= ((self.S_BOX[(r3 >> 16) & 0xFF] & 0xFF) << 16) & 0xFFFFFFFF
457
+ self.c1 ^= ((self.S_BOX[r0 >> 24] & 0xFF) << 24) & 0xFFFFFFFF
458
+ self.c1 ^= key[r][1] & 0xFFFFFFFF
459
+ self.c2 = (self.S_BOX[r2 & 0xFF] & 0xFF) & 0xFFFFFFFF
460
+ self.c2 ^= ((self.S_BOX[(r3 >> 8) & 0xFF] & 0xFF) << 8) & 0xFFFFFFFF
461
+ self.c2 ^= ((self.S_BOX[(r0 >> 16) & 0xFF] & 0xFF) << 16) & 0xFFFFFFFF
462
+ self.c2 ^= ((self.S_BOX[r1 >> 24] & 0xFF) << 24) & 0xFFFFFFFF
463
+ self.c2 ^= key[r][2] & 0xFFFFFFFF
464
+ self.c3 = (self.S_BOX[r3 & 0xFF] & 0xFF) & 0xFFFFFFFF
465
+ self.c3 ^= ((self.S_BOX[(r0 >> 8) & 0xFF] & 0xFF) << 8) & 0xFFFFFFFF
466
+ self.c3 ^= ((self.S_BOX[(r1 >> 16) & 0xFF] & 0xFF) << 16) & 0xFFFFFFFF
467
+ self.c3 ^= ((self.S_BOX[r2 >> 24] & 0xFF) << 24) & 0xFFFFFFFF
468
+ self.c3 ^= key[r][3] & 0xFFFFFFFF
469
+
470
+ def decryptBlock(self, key):
471
+ t0 = self.c0 ^ key[self.rounds][0]
472
+ t1 = self.c1 ^ key[self.rounds][1]
473
+ t2 = self.c2 ^ key[self.rounds][2]
474
+ r0 = r1 = r2 = 0
475
+ r3 = self.c3 ^ key[self.rounds][3]
476
+ r = self.rounds - 1
477
+ while r > 1:
478
+ r0 = (self.AES1_REVERSED[t0 & 255] & 0xFFFFFFFF) ^ self.shift(self.AES1_REVERSED[(r3 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t2 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t1 >> 24) & 255], 8) ^ key[r][0]
479
+ r1 = self.AES1_REVERSED[t1 & 255] ^ self.shift(self.AES1_REVERSED[(t0 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r3 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t2 >> 24) & 255], 8) ^ key[r][1]
480
+ r2 = self.AES1_REVERSED[t2 & 255] ^ self.shift(self.AES1_REVERSED[(t1 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t0 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r3 >> 24) & 255], 8) ^ key[r][2]
481
+ r3 = self.AES1_REVERSED[r3 & 255] ^ self.shift(self.AES1_REVERSED[(t2 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t1 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t0 >> 24) & 255], 8) ^ key[r][3]
482
+ r -= 1
483
+ t0 = self.AES1_REVERSED[r0 & 255] ^ self.shift(self.AES1_REVERSED[(r3 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r2 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r1 >> 24) & 255], 8) ^ key[r][0]
484
+ t1 = self.AES1_REVERSED[r1 & 255] ^ self.shift(self.AES1_REVERSED[(r0 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r3 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r2 >> 24) & 255], 8) ^ key[r][1]
485
+ t2 = self.AES1_REVERSED[r2 & 255] ^ self.shift(self.AES1_REVERSED[(r1 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r0 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r3 >> 24) & 255], 8) ^ key[r][2]
486
+ r3 = self.AES1_REVERSED[r3 & 255] ^ self.shift(self.AES1_REVERSED[(r2 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r1 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r0 >> 24) & 255], 8) ^ key[r][3]
487
+ r -= 1
488
+ r = 1
489
+ r0 = self.AES1_REVERSED[t0 & 255] ^ self.shift(self.AES1_REVERSED[(r3 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t2 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t1 >> 24) & 255], 8) ^ key[r][0]
490
+ r1 = self.AES1_REVERSED[t1 & 255] ^ self.shift(self.AES1_REVERSED[(t0 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(r3 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t2 >> 24) & 255], 8) ^ key[r][1]
491
+ r2 = self.AES1_REVERSED[t2 & 255] ^ self.shift(self.AES1_REVERSED[(t1 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t0 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(r3 >> 24) & 255], 8) ^ key[r][2]
492
+ r3 = self.AES1_REVERSED[r3 & 255] ^ self.shift(self.AES1_REVERSED[(t2 >> 8) & 255], 24) ^ self.shift(self.AES1_REVERSED[(t1 >> 16) & 255], 16) ^ self.shift(self.AES1_REVERSED[(t0 >> 24) & 255], 8) ^ key[r][3]
493
+ r = 0
494
+ self.c0 = (self.S_BOX_REVERSED[r0 & 255] & 0xFF) ^ ((((self.S_BOX_REVERSED[(r3 >> 8) & 255]) & 0xFF) << 8)) ^ ((((self.S_BOX_REVERSED[(r2 >> 16) & 255]) & 0xFF) << 16)) ^ ((((self.S_BOX_REVERSED[(r1 >> 24) & 255]) & 0xFF) << 24)) ^ key[r][0]
495
+ self.c1 = (self.S_BOX_REVERSED[r1 & 255] & 0xFF) ^ (((self.S_BOX_REVERSED[(r0 >> 8) & 255]) & 0xFF) << 8) ^ (((self.S_BOX_REVERSED[(r3 >> 16) & 255]) & 0xFF) << 16) ^ (((self.S_BOX_REVERSED[(r2 >> 24) & 255]) & 0xFF) << 24) ^ key[r][1]
496
+ self.c2 = (self.S_BOX_REVERSED[r2 & 255] & 0xFF) ^ (((self.S_BOX_REVERSED[(r1 >> 8) & 255]) & 0xFF) << 8) ^ (((self.S_BOX_REVERSED[(r0 >> 16) & 255]) & 0xFF) << 16) ^ (((self.S_BOX_REVERSED[(r3 >> 24) & 255]) & 0xFF) << 24) ^ key[r][2]
497
+ self.c3 = (self.S_BOX_REVERSED[r3 & 255] & 0xFF) ^ (((self.S_BOX_REVERSED[(r2 >> 8) & 255]) & 0xFF) << 8) ^ (((self.S_BOX_REVERSED[(r1 >> 16) & 255]) & 0xFF) << 16) ^ (((self.S_BOX_REVERSED[(r0 >> 24) & 255]) & 0xFF) << 24) ^ key[r][3]
498
+
499
+ def processBlock(self, input_, inOffset, forOutput, outOffset):
500
+ if inOffset + (32 / 2) > len(input_):
501
+ raise ValueError("input buffer too short")
502
+ if outOffset + (32 / 2) > len(forOutput):
503
+ raise ValueError("output buffer too short")
504
+ self.unPackBlock(input_, inOffset)
505
+ if self.encrypt:
506
+ self.encryptBlock(self.workingKey)
507
+ else:
508
+ self.decryptBlock(self.workingKey)
509
+ self.packBlock(forOutput, outOffset)
510
+ return self.BLOCK_SIZE
511
+
512
+ @classmethod
513
+ def bEToUInt32(cls, buff, offset):
514
+ value = (buff[offset] << 24)
515
+ value |= (buff[offset + 1] << 16) & 0xFF0000
516
+ value |= (buff[offset + 2] << 8) & 0xFF00
517
+ value |= buff[offset + 3] & 0xFF
518
+ return value
519
+
520
+ @classmethod
521
+ def shiftRight(cls, block, count):
522
+ bit = 0
523
+ i = 0
524
+ while i < 4:
525
+ b = block[i]
526
+ block[i] = (b >> count) | bit
527
+ bit = (b << (32 - count)) & 0xFFFFFFFF
528
+ i += 1
529
+
530
+ @classmethod
531
+ def multiplyP(cls, x):
532
+ lsb = (x[3] & 1) != 0
533
+ cls.shiftRight(x, 1)
534
+ if lsb:
535
+ x[0] ^= 0xe1000000
536
+
537
+ @classmethod
538
+ def getUint128(cls, buff):
539
+ us = [None] * 4
540
+ us[0] = cls.bEToUInt32(buff, 0)
541
+ us[1] = cls.bEToUInt32(buff, 4)
542
+ us[2] = cls.bEToUInt32(buff, 8)
543
+ us[3] = cls.bEToUInt32(buff, 12)
544
+ return us
545
+
546
+ @classmethod
547
+ def xor(cls, block, value):
548
+ pos = 0
549
+ while pos != 16:
550
+ block[pos] ^= value[pos]
551
+ pos += 1
552
+
553
+ @classmethod
554
+ def xor128(cls, block, value):
555
+ pos = 0
556
+ while pos != 4:
557
+ block[pos] ^= value[pos]
558
+ pos += 1
559
+
560
+ @classmethod
561
+ def multiplyP8(cls, x):
562
+ lsw = x[3]
563
+ cls.shiftRight(x, 8)
564
+ pos = 0
565
+ while pos != 8:
566
+ if (lsw & (1 << pos)) != 0:
567
+ x[0] ^= ((0xe1000000 >> (7 - pos)) & 0xFFFFFFFF)
568
+ pos += 1
569
+
570
+ def getGHash(self, b):
571
+ y = bytearray(16)
572
+ pos = 0
573
+ while pos < len(b):
574
+ x = bytearray(16)
575
+ cnt = min(len(b) - pos, 16)
576
+ x[0:cnt] = b[pos:pos + cnt]
577
+ self.xor(y, x)
578
+ self.multiplyH(y)
579
+ pos += 16
580
+ return y
581
+
582
+ @classmethod
583
+ def uInt32ToBE(cls, value, buff, offset):
584
+ buff[offset] = (value >> 24) & 0xFF
585
+ buff[offset + 1] = (value >> 16) & 0xFF
586
+ buff[offset + 2] = (value >> 8) & 0xFF
587
+ buff[offset + 3] = value & 0xFF
588
+
589
+ def multiplyH(self, value):
590
+ tmp = [0] * 4
591
+ pos = 0
592
+ while pos != 16:
593
+ m = self.mArray[pos + pos][value[pos] & 0x0f]
594
+ tmp[0] ^= m[0]
595
+ tmp[1] ^= m[1]
596
+ tmp[2] ^= m[2]
597
+ tmp[3] ^= m[3]
598
+ m = self.mArray[pos + pos + 1][(value[pos] & 0xf0) >> 4]
599
+ tmp[0] ^= m[0]
600
+ tmp[1] ^= m[1]
601
+ tmp[2] ^= m[2]
602
+ tmp[3] ^= m[3]
603
+ pos += 1
604
+ self.uInt32ToBE(tmp[0], value, 0)
605
+ self.uInt32ToBE(tmp[1], value, 4)
606
+ self.uInt32ToBE(tmp[2], value, 8)
607
+ self.uInt32ToBE(tmp[3], value, 12)
608
+
609
+ def init(self, value):
610
+ self.mArray[0] = [0] * 16
611
+ self.mArray[1] = [0] * 16
612
+ self.mArray[0][0] = [0] * 4
613
+ self.mArray[1][0] = [0] * 4
614
+ self.mArray[1][8] = self.getUint128(value)
615
+ tmp = []
616
+ pos = 4
617
+ while pos >= 1:
618
+ tmp = self.clone(self.mArray[1][pos + pos])
619
+ self.multiplyP(tmp)
620
+ self.mArray[1][pos] = tmp
621
+ pos >>= 1
622
+ tmp = self.clone(self.mArray[1][1])
623
+ self.multiplyP(tmp)
624
+ self.mArray[0][8] = tmp
625
+ pos = 4
626
+ while pos >= 1:
627
+ tmp = self.clone(self.mArray[0][pos + pos])
628
+ self.multiplyP(tmp)
629
+ self.mArray[0][pos] = tmp
630
+ pos >>= 1
631
+ pos1 = 0
632
+ while True:
633
+ pos2 = 2
634
+ while pos2 < 16:
635
+ k = 1
636
+ while k < pos2:
637
+ tmp = self.clone(self.mArray[pos1][pos2])
638
+ self.xor128(tmp, self.mArray[pos1][k])
639
+ self.mArray[pos1][pos2 + k] = tmp
640
+ k += 1
641
+ pos2 += pos2
642
+ pos1 += 1
643
+ if pos1 == 32:
644
+ return
645
+ if pos1 > 1:
646
+ self.mArray[pos1] = [0] * 16
647
+ self.mArray[pos1][0] = [0] * 4
648
+ pos = 8
649
+ while pos > 0:
650
+ tmp = self.clone(self.mArray[pos1 - 2][pos])
651
+ self.multiplyP8(tmp)
652
+ self.mArray[pos1][pos] = tmp
653
+ pos >>= 1
654
+
655
+
656
+ def gCTRBlock(self, buf, bufCount):
657
+ i = 15
658
+ while i >= 12:
659
+ self.counter[i] += 1
660
+ if self.counter[i] != 0:
661
+ break
662
+ i -= 1
663
+ tmp = bytearray(self.BLOCK_SIZE)
664
+ self.processBlock(self.counter, 0, tmp, 0)
665
+ if self.encrypt:
666
+ zeroes = bytearray(self.BLOCK_SIZE)
667
+ tmp[bufCount:self.BLOCK_SIZE] = zeroes[bufCount:self.BLOCK_SIZE]
668
+ hashBytes = tmp
669
+ else:
670
+ hashBytes = buf
671
+ pos = 0
672
+ while pos != bufCount:
673
+ tmp[pos] ^= buf[pos]
674
+ self.output.setUInt8(tmp[pos])
675
+ pos += 1
676
+ self.xor(self.s, hashBytes)
677
+ self.multiplyH(self.s)
678
+ self.totalLength += bufCount
679
+
680
+ @classmethod
681
+ def setPackLength(cls, length, buff, offset):
682
+ cls.uInt32ToBE(int((length >> 32)), buff, offset)
683
+ cls.uInt32ToBE(int(length), buff, offset + 4)
684
+
685
+ def reset(self):
686
+ self.s = self.getGHash(self.aad)
687
+ self.counter = self.clone(self.j0)
688
+ self.bytesRemaining = 0
689
+ self.totalLength = 0
690
+
691
+ @classmethod
692
+ def tagsEquals(cls, tag1, tag2):
693
+ pos = 0
694
+ while pos != 12:
695
+ if tag1[pos] != tag2[pos]:
696
+ return False
697
+ pos += 1
698
+ return True
699
+
700
+ def write(self, input_):
701
+ for it in input_:
702
+ self.bufBlock[self.bytesRemaining] = it
703
+ self.bytesRemaining += 1
704
+ if self.bytesRemaining == self.BLOCK_SIZE:
705
+ self.gCTRBlock(self.bufBlock, self.BLOCK_SIZE)
706
+ if not self.encrypt:
707
+ #System.arraycopy(self.bufBlock, self.BLOCK_SIZE,
708
+ #self.bufBlock, 0,)
709
+ self.bufBlock[0:len(self.tag)] = self.bufBlock[self.blockSize:self.blockSize + len(self.tag)]
710
+ self.bytesRemaining = 0
711
+
712
+ def flushFinalBlock(self):
713
+ if self.bytesRemaining > 0:
714
+ tmp = self.bufBlock[0:self.bytesRemaining]
715
+ self.gCTRBlock(tmp, self.bytesRemaining)
716
+ if self.security == Security.ENCRYPTION:
717
+ self.reset()
718
+ return self.output.array()
719
+ x = bytearray(16)
720
+ self.setPackLength(8 * len(self.aad), x, 0)
721
+ self.setPackLength(self.totalLength * 8, x, 8)
722
+ self.xor(self.s, x)
723
+ self.multiplyH(self.s)
724
+ generatedTag = bytearray(self.BLOCK_SIZE)
725
+ self.processBlock(self.j0, 0, generatedTag, 0)
726
+ self.xor(generatedTag, self.s)
727
+ if not self.encrypt:
728
+ if not self.tagsEquals(self.tag, generatedTag):
729
+ print(GXByteBuffer.hex(self.tag, False) + "-" + GXByteBuffer.hex(generatedTag, False))
730
+ raise ValueError("Decrypt failed. Invalid tag.")
731
+ else:
732
+ #Tag size is 12 bytes.
733
+ self.tag = generatedTag[0:12]
734
+ self.reset()
735
+ return self.output.array()
736
+
737
+ def generateKey(self, isEncrypt, key):
738
+ #Key length in words.
739
+ keyLen = int(len(key) / 4)
740
+ self.rounds = keyLen + 6
741
+ w = [[0 for x in range(4)] for y in range(self.rounds + 1)]
742
+ t = 0
743
+ i = 0
744
+ while i < len(key):
745
+ w[t >> 2][t & 3] = self.toUInt32(key, i)
746
+ i += 4
747
+ t += 1
748
+ k = (self.rounds + 1) << 2
749
+ i = keyLen
750
+ while i < k:
751
+ temp = w[(i - 1) >> 2][(i - 1) & 3]
752
+ if (i % keyLen) == 0:
753
+ temp = self.subWord(self.shift(temp, 8)) ^ (self.R_CON[int(i / keyLen) - 1] & 0xFF)
754
+ elif (keyLen > 6) and ((i % keyLen) == 4):
755
+ temp = self.subWord(temp)
756
+ w[i >> 2][i & 3] = w[(i - keyLen) >> 2][(i - keyLen) & 3] ^ temp
757
+ i += 1
758
+ if not isEncrypt:
759
+ j = 1
760
+ while j < self.rounds:
761
+ i = 0
762
+ while i < 4:
763
+ w[j][i] = self.imixCol(w[j][i])
764
+ i += 1
765
+ j += 1
766
+ return w
767
+
768
+ @classmethod
769
+ def galoisMultiply(cls, value):
770
+ if value >> 7 != 0:
771
+ value = value << 1
772
+ return (value ^ 0x1b) & 0xFF
773
+
774
+ return (value << 1) & 0xFF
775
+ # temp = (value >> 7) & 0xFF
776
+ # temp = temp & 0x1b
777
+ # return ((value << 1) ^ temp) & 0xFF
778
+
779
+ @classmethod
780
+ def aes1Encrypt(cls, data: bytearray, offset: int, secret: bytearray):
781
+ round_ = 0
782
+ i = 0
783
+ key = secret.copy()
784
+ while round_ < 10:
785
+ i = 0
786
+ while i < 16:
787
+ data[i + offset] = cls.S_BOX[(data[i + offset] ^ key[i]) & 0xFF]
788
+ i += 1
789
+ buf1 = data[1 + offset]
790
+ data[1 + offset] = data[5 + offset]
791
+ data[5 + offset] = data[9 + offset]
792
+ data[9 + offset] = data[13 + offset]
793
+ data[13 + offset] = buf1
794
+ buf1 = data[2 + offset]
795
+ buf2 = data[6 + offset]
796
+ data[2 + offset] = data[10 + offset]
797
+ data[6 + offset] = data[14 + offset]
798
+ data[10 + offset] = buf1
799
+ data[14 + offset] = buf2
800
+ buf1 = data[15 + offset]
801
+ data[15 + offset] = data[11 + offset]
802
+ data[11 + offset] = data[7 + offset]
803
+ data[7 + offset] = data[3 + offset]
804
+ data[3 + offset] = buf1
805
+ if round_ < 9:
806
+ i = 0
807
+ while i < 4:
808
+ buf4 = (i << 2) & 0xFF
809
+ buf1 = (data[buf4 + offset] ^ data[buf4 + 1 + offset] ^ data[buf4 + 2 + offset] ^ data[buf4 + 3 + offset]) & 0xFF
810
+ buf2 = data[buf4 + offset] & 0xFF
811
+ buf3 = (data[buf4 + offset] ^ data[buf4 + 1 + offset]) & 0xFF
812
+ buf3 = cls.galoisMultiply(buf3) & 0xFF
813
+ data[buf4 + offset] = (data[buf4 + offset] ^ buf3 ^ buf1) & 0xFF
814
+ buf3 = (data[buf4 + 1 + offset] ^ data[buf4 + 2 + offset]) & 0xFF
815
+ buf3 = cls.galoisMultiply(buf3) & 0xFF
816
+ data[buf4 + 1 + offset] = (data[buf4 + 1 + offset] ^ buf3 ^ buf1) & 0xFF
817
+ buf3 = (data[buf4 + 2 + offset] ^ data[buf4 + 3 + offset]) & 0xFF
818
+ buf3 = cls.galoisMultiply(buf3) & 0xFF
819
+ data[buf4 + 2 + offset] = (data[buf4 + 2 + offset] ^ buf3 ^ buf1) & 0xFF
820
+ buf3 = (data[buf4 + 3 + offset] ^ buf2) & 0xFF
821
+ buf3 = cls.galoisMultiply(buf3) & 0xFF
822
+ data[buf4 + 3 + offset] = (data[buf4 + 3 + offset] ^ buf3 ^ buf1) & 0xFF
823
+ i += 1
824
+ key[0] = (cls.S_BOX[key[13] & 0xFF] ^ key[0] ^ cls.R_CON[round_]) & 0xFF
825
+ key[1] = (cls.S_BOX[key[14] & 0xFF] ^ key[1]) & 0xFF
826
+ key[2] = (cls.S_BOX[key[15] & 0xFF] ^ key[2]) & 0xFF
827
+ key[3] = (cls.S_BOX[key[12] & 0xFF] ^ key[3]) & 0xFF
828
+ i = 4
829
+ while i < 16:
830
+ key[i] = (key[i] ^ key[i - 4]) & 0xFF
831
+ i += 1
832
+ round_ += 1
833
+ i = 0
834
+ while i < 16:
835
+ data[i + offset] = (data[i + offset] ^ key[i])
836
+ i += 1
837
+
838
+ def encryptAes(self, data):
839
+ n = len(data) / 8
840
+ if (n * 8) != len(data):
841
+ raise ValueError("Invalid data.")
842
+ iv = bytearray([0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6])
843
+ block = bytearray(len(data) + len(iv))
844
+ buf = bytearray(8 + len(iv))
845
+ block[0:len(self.IV)] = self.IV[0:len(self.IV)]
846
+ block[len(self.IV):len(self.IV) + len(data)] = data[0:len(data)]
847
+ j = 0
848
+ while j != 6:
849
+ i = 1
850
+ while i <= n:
851
+ buf[0:len(self.IV)] = block[0: len(self.IV)]
852
+ buf[len(self.IV):8 + len(self.IV)] = block[8 * i:8 * i + 8]
853
+ self.processBlock(buf, 0, buf, 0)
854
+ t = int(n * j + i)
855
+ k = 1
856
+ while t != 0:
857
+ v = int(t)
858
+ buf[len(self.IV) - k] ^= v
859
+ t = int(t >> 8)
860
+ k += 1
861
+ block[0:8] = buf[0:8]
862
+ block[8 * i:8 * i + 8] = buf[8:16]
863
+ i += 1
864
+ j += 1
865
+ return block
866
+
867
+ def decryptAes(self, input_):
868
+ n = len(input_) / 8
869
+ if (n * 8) != len(input_):
870
+ raise ValueError("Invalid data.")
871
+ iv = bytearray([0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6])
872
+ if len(input_) > len(iv):
873
+ block = bytearray(len(input_) - len(iv))
874
+ else:
875
+ block = bytearray(len(iv))
876
+ a = bytearray(len(iv))
877
+ buf = bytearray(8 + len(iv))
878
+ a[0:] = input_[0:len(iv)]
879
+ block[0:] = input_[len(iv):len(input_)]
880
+ n = n - 1
881
+ if n == 0:
882
+ n = 1
883
+ j = 5
884
+ while j >= 0:
885
+ i = n
886
+ while i >= 1:
887
+ buf[0:len(iv)] = a[0:len(iv)]
888
+ buf[len(iv):8 + len(iv)] = block[8 * int(i - 1):8 * int(i)]
889
+ t = n * j + i
890
+ k = 1
891
+ while t != 0:
892
+ v = int(t)
893
+ buf[len(self.IV)] ^= v
894
+ t = int((int(t) >> 8))
895
+ k += 1
896
+ self.processBlock(buf, 0, buf, 0)
897
+ a[0:] = buf[0:8]
898
+ block[8:16] = buf[8 * (i - 1):8*i]
899
+ i -= 1
900
+ j -= 1
901
+ if a != self.IV:
902
+ raise ValueError("Invalid data")
903
+ return block
904
+
905
+ @classmethod
906
+ def aes1Decrypt(cls, data, secret):
907
+ buf1 = 0
908
+ buf2 = 0
909
+ buf3 = 0
910
+ round_ = 0
911
+ i = 0
912
+ buf4 = 0
913
+ key = secret[0:]
914
+ while round_ < 10:
915
+ key[0] = int((cls.S_BOX[key[13] & 0xFF] ^ key[0] ^ cls.R_CON[round_]))
916
+ key[1] = int((cls.S_BOX[key[14] & 0xFF] ^ key[1]))
917
+ key[2] = int((cls.S_BOX[key[15] & 0xFF] ^ key[2]))
918
+ key[3] = int((cls.S_BOX[key[12] & 0xFF] ^ key[3]))
919
+ while i < 16:
920
+ key[i] = int((key[i] ^ key[i - 4]))
921
+ i += 1
922
+ round_ += 1
923
+ while i < 16:
924
+ data[i] = int((data[i] ^ key[i]))
925
+ i += 1
926
+ while round_ < 10:
927
+ while i > 3:
928
+ key[i] = int((key[i] ^ key[i - 4]))
929
+ i -= 1
930
+ key[0] = int((cls.S_BOX[key[13] & 0xFF] ^ key[0] ^ cls.R_CON[9 - round_]))
931
+ key[1] = int((cls.S_BOX[key[14] & 0xFF] ^ key[1]))
932
+ key[2] = int((cls.S_BOX[key[15] & 0xFF] ^ key[2]))
933
+ key[3] = int((cls.S_BOX[key[12] & 0xFF] ^ key[3]))
934
+ if round_ > 0:
935
+ while i < 4:
936
+ buf4 = (i << 2) & 0xFF
937
+ buf1 = cls.galoisMultiply(cls.galoisMultiply(data[buf4] ^ data[buf4 + 2]))
938
+ buf2 = cls.galoisMultiply(cls.galoisMultiply(data[buf4 + 1] ^ data[buf4 + 3]))
939
+ data[buf4] ^= buf1
940
+ data[buf4 + 1] ^= buf2
941
+ data[buf4 + 2] ^= buf1
942
+ data[buf4 + 3] ^= buf2
943
+ buf1 = int((data[buf4] ^ data[buf4 + 1] ^ data[buf4 + 2] ^ data[buf4 + 3]))
944
+ buf2 = data[buf4]
945
+ buf3 = int((data[buf4] ^ data[buf4 + 1]))
946
+ buf3 = cls.galoisMultiply(buf3)
947
+ data[buf4] = int((data[buf4] ^ buf3 ^ buf1))
948
+ buf3 = int((data[buf4 + 1] ^ data[buf4 + 2]))
949
+ buf3 = cls.galoisMultiply(buf3)
950
+ data[buf4 + 1] = int((data[buf4 + 1] ^ buf3 ^ buf1))
951
+ buf3 = int((data[buf4 + 2] ^ data[buf4 + 3]))
952
+ buf3 = cls.galoisMultiply(buf3)
953
+ data[buf4 + 2] = int((data[buf4 + 2] ^ buf3 ^ buf1))
954
+ buf3 = int((data[buf4 + 3] ^ buf2))
955
+ buf3 = cls.galoisMultiply(buf3)
956
+ data[buf4 + 3] = int((data[buf4 + 3] ^ buf3 ^ buf1))
957
+ i += 1
958
+ buf1 = data[13]
959
+ data[13] = data[9]
960
+ data[9] = data[5]
961
+ data[5] = data[1]
962
+ data[1] = buf1
963
+ buf1 = data[10]
964
+ buf2 = data[14]
965
+ data[10] = data[2]
966
+ data[14] = data[6]
967
+ data[2] = buf1
968
+ data[6] = buf2
969
+ buf1 = data[3]
970
+ data[3] = data[7]
971
+ data[7] = data[11]
972
+ data[11] = data[15]
973
+ data[15] = buf1
974
+ while i < 16:
975
+ data[i] = int((cls.S_BOX_REVERSED[data[i] & 0xFF] ^ key[i]))
976
+ i += 1
977
+ round_ += 1