1 from __future__
import unicode_literals
16 if compat_pycrypto_AES
:
17 def aes_cbc_decrypt_bytes(data
, key
, iv
):
18 """ Decrypt bytes with AES-CBC using pycryptodome """
19 return compat_pycrypto_AES
.new(key
, compat_pycrypto_AES
.MODE_CBC
, iv
).decrypt(data
)
21 def aes_gcm_decrypt_and_verify_bytes(data
, key
, tag
, nonce
):
22 """ Decrypt bytes with AES-GCM using pycryptodome """
23 return compat_pycrypto_AES
.new(key
, compat_pycrypto_AES
.MODE_GCM
, nonce
).decrypt_and_verify(data
, tag
)
26 def aes_cbc_decrypt_bytes(data
, key
, iv
):
27 """ Decrypt bytes with AES-CBC using native implementation since pycryptodome is unavailable """
28 return intlist_to_bytes(aes_cbc_decrypt(*map(bytes_to_intlist
, (data
, key
, iv
))))
30 def aes_gcm_decrypt_and_verify_bytes(data
, key
, tag
, nonce
):
31 """ Decrypt bytes with AES-GCM using native implementation since pycryptodome is unavailable """
32 return intlist_to_bytes(aes_gcm_decrypt_and_verify(*map(bytes_to_intlist
, (data
, key
, tag
, nonce
))))
35 def unpad_pkcs7(data
):
36 return data
[:-compat_ord(data
[-1])]
42 def aes_ecb_encrypt(data
, key
, iv
=None):
44 Encrypt with aes in ECB mode
46 @param {int[]} data cleartext
47 @param {int[]} key 16/24/32-Byte cipher key
48 @param {int[]} iv Unused for this mode
49 @returns {int[]} encrypted data
51 expanded_key
= key_expansion(key
)
52 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
55 for i
in range(block_count
):
56 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
57 encrypted_data
+= aes_encrypt(block
, expanded_key
)
58 encrypted_data
= encrypted_data
[:len(data
)]
63 def aes_ecb_decrypt(data
, key
, iv
=None):
65 Decrypt with aes in ECB mode
67 @param {int[]} data cleartext
68 @param {int[]} key 16/24/32-Byte cipher key
69 @param {int[]} iv Unused for this mode
70 @returns {int[]} decrypted data
72 expanded_key
= key_expansion(key
)
73 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
76 for i
in range(block_count
):
77 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
78 encrypted_data
+= aes_decrypt(block
, expanded_key
)
79 encrypted_data
= encrypted_data
[:len(data
)]
84 def aes_ctr_decrypt(data
, key
, iv
):
86 Decrypt with aes in counter mode
88 @param {int[]} data cipher
89 @param {int[]} key 16/24/32-Byte cipher key
90 @param {int[]} iv 16-Byte initialization vector
91 @returns {int[]} decrypted data
93 return aes_ctr_encrypt(data
, key
, iv
)
96 def aes_ctr_encrypt(data
, key
, iv
):
98 Encrypt with aes in counter mode
100 @param {int[]} data cleartext
101 @param {int[]} key 16/24/32-Byte cipher key
102 @param {int[]} iv 16-Byte initialization vector
103 @returns {int[]} encrypted data
105 expanded_key
= key_expansion(key
)
106 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
107 counter
= iter_vector(iv
)
110 for i
in range(block_count
):
111 counter_block
= next(counter
)
112 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
113 block
+= [0] * (BLOCK_SIZE_BYTES
- len(block
))
115 cipher_counter_block
= aes_encrypt(counter_block
, expanded_key
)
116 encrypted_data
+= xor(block
, cipher_counter_block
)
117 encrypted_data
= encrypted_data
[:len(data
)]
119 return encrypted_data
122 def aes_cbc_decrypt(data
, key
, iv
):
124 Decrypt with aes in CBC mode
126 @param {int[]} data cipher
127 @param {int[]} key 16/24/32-Byte cipher key
128 @param {int[]} iv 16-Byte IV
129 @returns {int[]} decrypted data
131 expanded_key
= key_expansion(key
)
132 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
135 previous_cipher_block
= iv
136 for i
in range(block_count
):
137 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
138 block
+= [0] * (BLOCK_SIZE_BYTES
- len(block
))
140 decrypted_block
= aes_decrypt(block
, expanded_key
)
141 decrypted_data
+= xor(decrypted_block
, previous_cipher_block
)
142 previous_cipher_block
= block
143 decrypted_data
= decrypted_data
[:len(data
)]
145 return decrypted_data
148 def aes_cbc_encrypt(data
, key
, iv
):
150 Encrypt with aes in CBC mode. Using PKCS#7 padding
152 @param {int[]} data cleartext
153 @param {int[]} key 16/24/32-Byte cipher key
154 @param {int[]} iv 16-Byte IV
155 @returns {int[]} encrypted data
157 expanded_key
= key_expansion(key
)
158 block_count
= int(ceil(float(len(data
)) / BLOCK_SIZE_BYTES
))
161 previous_cipher_block
= iv
162 for i
in range(block_count
):
163 block
= data
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
]
164 remaining_length
= BLOCK_SIZE_BYTES
- len(block
)
165 block
+= [remaining_length
] * remaining_length
166 mixed_block
= xor(block
, previous_cipher_block
)
168 encrypted_block
= aes_encrypt(mixed_block
, expanded_key
)
169 encrypted_data
+= encrypted_block
171 previous_cipher_block
= encrypted_block
173 return encrypted_data
176 def aes_gcm_decrypt_and_verify(data
, key
, tag
, nonce
):
178 Decrypt with aes in GBM mode and checks authenticity using tag
180 @param {int[]} data cipher
181 @param {int[]} key 16-Byte cipher key
182 @param {int[]} tag authentication tag
183 @param {int[]} nonce IV (recommended 12-Byte)
184 @returns {int[]} decrypted data
187 # XXX: check aes, gcm param
189 hash_subkey
= aes_encrypt([0] * BLOCK_SIZE_BYTES
, key_expansion(key
))
192 j0
= nonce
+ [0, 0, 0, 1]
194 fill
= (BLOCK_SIZE_BYTES
- (len(nonce
) % BLOCK_SIZE_BYTES
)) % BLOCK_SIZE_BYTES
+ 8
195 ghash_in
= nonce
+ [0] * fill
+ bytes_to_intlist((8 * len(nonce
)).to_bytes(8, 'big'))
196 j0
= ghash(hash_subkey
, ghash_in
)
198 # TODO: add nonce support to aes_ctr_decrypt
200 # nonce_ctr = j0[:12]
203 decrypted_data
= aes_ctr_decrypt(data
, key
, iv_ctr
+ [0] * (BLOCK_SIZE_BYTES
- len(iv_ctr
)))
204 pad_len
= len(data
) // 16 * 16
208 + [0] * (BLOCK_SIZE_BYTES
- len(data
) + pad_len
) # pad
209 + bytes_to_intlist((0 * 8).to_bytes(8, 'big') # length of associated data
210 + ((len(data
) * 8).to_bytes(8, 'big'))) # length of data
213 if tag
!= aes_ctr_encrypt(s_tag
, key
, j0
):
214 raise ValueError("Mismatching authentication tag")
216 return decrypted_data
219 def aes_encrypt(data
, expanded_key
):
221 Encrypt one block with aes
223 @param {int[]} data 16-Byte state
224 @param {int[]} expanded_key 176/208/240-Byte expanded key
225 @returns {int[]} 16-Byte cipher
227 rounds
= len(expanded_key
) // BLOCK_SIZE_BYTES
- 1
229 data
= xor(data
, expanded_key
[:BLOCK_SIZE_BYTES
])
230 for i
in range(1, rounds
+ 1):
231 data
= sub_bytes(data
)
232 data
= shift_rows(data
)
234 data
= list(iter_mix_columns(data
, MIX_COLUMN_MATRIX
))
235 data
= xor(data
, expanded_key
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
])
240 def aes_decrypt(data
, expanded_key
):
242 Decrypt one block with aes
244 @param {int[]} data 16-Byte cipher
245 @param {int[]} expanded_key 176/208/240-Byte expanded key
246 @returns {int[]} 16-Byte state
248 rounds
= len(expanded_key
) // BLOCK_SIZE_BYTES
- 1
250 for i
in range(rounds
, 0, -1):
251 data
= xor(data
, expanded_key
[i
* BLOCK_SIZE_BYTES
: (i
+ 1) * BLOCK_SIZE_BYTES
])
253 data
= list(iter_mix_columns(data
, MIX_COLUMN_MATRIX_INV
))
254 data
= shift_rows_inv(data
)
255 data
= sub_bytes_inv(data
)
256 data
= xor(data
, expanded_key
[:BLOCK_SIZE_BYTES
])
261 def aes_decrypt_text(data
, password
, key_size_bytes
):
264 - The first 8 Bytes of decoded 'data' are the 8 high Bytes of the counter
265 - The cipher key is retrieved by encrypting the first 16 Byte of 'password'
266 with the first 'key_size_bytes' Bytes from 'password' (if necessary filled with 0's)
267 - Mode of operation is 'counter'
269 @param {str} data Base64 encoded string
270 @param {str,unicode} password Password (will be encoded with utf-8)
271 @param {int} key_size_bytes Possible values: 16 for 128-Bit, 24 for 192-Bit or 32 for 256-Bit
272 @returns {str} Decrypted data
274 NONCE_LENGTH_BYTES
= 8
276 data
= bytes_to_intlist(compat_b64decode(data
))
277 password
= bytes_to_intlist(password
.encode('utf-8'))
279 key
= password
[:key_size_bytes
] + [0] * (key_size_bytes
- len(password
))
280 key
= aes_encrypt(key
[:BLOCK_SIZE_BYTES
], key_expansion(key
)) * (key_size_bytes
// BLOCK_SIZE_BYTES
)
282 nonce
= data
[:NONCE_LENGTH_BYTES
]
283 cipher
= data
[NONCE_LENGTH_BYTES
:]
285 decrypted_data
= aes_ctr_decrypt(cipher
, key
, nonce
+ [0] * (BLOCK_SIZE_BYTES
- NONCE_LENGTH_BYTES
))
286 plaintext
= intlist_to_bytes(decrypted_data
)
291 RCON
= (0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36)
292 SBOX
= (0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
293 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
294 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
295 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
296 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
297 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
298 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
299 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
300 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
301 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
302 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
303 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
304 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
305 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
306 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
307 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16)
308 SBOX_INV
= (0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
309 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
310 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
311 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
312 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
313 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
314 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
315 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
316 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
317 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
318 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
319 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
320 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
321 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
322 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
323 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d)
324 MIX_COLUMN_MATRIX
= ((0x2, 0x3, 0x1, 0x1),
325 (0x1, 0x2, 0x3, 0x1),
326 (0x1, 0x1, 0x2, 0x3),
327 (0x3, 0x1, 0x1, 0x2))
328 MIX_COLUMN_MATRIX_INV
= ((0xE, 0xB, 0xD, 0x9),
329 (0x9, 0xE, 0xB, 0xD),
330 (0xD, 0x9, 0xE, 0xB),
331 (0xB, 0xD, 0x9, 0xE))
332 RIJNDAEL_EXP_TABLE
= (0x01, 0x03, 0x05, 0x0F, 0x11, 0x33, 0x55, 0xFF, 0x1A, 0x2E, 0x72, 0x96, 0xA1, 0xF8, 0x13, 0x35,
333 0x5F, 0xE1, 0x38, 0x48, 0xD8, 0x73, 0x95, 0xA4, 0xF7, 0x02, 0x06, 0x0A, 0x1E, 0x22, 0x66, 0xAA,
334 0xE5, 0x34, 0x5C, 0xE4, 0x37, 0x59, 0xEB, 0x26, 0x6A, 0xBE, 0xD9, 0x70, 0x90, 0xAB, 0xE6, 0x31,
335 0x53, 0xF5, 0x04, 0x0C, 0x14, 0x3C, 0x44, 0xCC, 0x4F, 0xD1, 0x68, 0xB8, 0xD3, 0x6E, 0xB2, 0xCD,
336 0x4C, 0xD4, 0x67, 0xA9, 0xE0, 0x3B, 0x4D, 0xD7, 0x62, 0xA6, 0xF1, 0x08, 0x18, 0x28, 0x78, 0x88,
337 0x83, 0x9E, 0xB9, 0xD0, 0x6B, 0xBD, 0xDC, 0x7F, 0x81, 0x98, 0xB3, 0xCE, 0x49, 0xDB, 0x76, 0x9A,
338 0xB5, 0xC4, 0x57, 0xF9, 0x10, 0x30, 0x50, 0xF0, 0x0B, 0x1D, 0x27, 0x69, 0xBB, 0xD6, 0x61, 0xA3,
339 0xFE, 0x19, 0x2B, 0x7D, 0x87, 0x92, 0xAD, 0xEC, 0x2F, 0x71, 0x93, 0xAE, 0xE9, 0x20, 0x60, 0xA0,
340 0xFB, 0x16, 0x3A, 0x4E, 0xD2, 0x6D, 0xB7, 0xC2, 0x5D, 0xE7, 0x32, 0x56, 0xFA, 0x15, 0x3F, 0x41,
341 0xC3, 0x5E, 0xE2, 0x3D, 0x47, 0xC9, 0x40, 0xC0, 0x5B, 0xED, 0x2C, 0x74, 0x9C, 0xBF, 0xDA, 0x75,
342 0x9F, 0xBA, 0xD5, 0x64, 0xAC, 0xEF, 0x2A, 0x7E, 0x82, 0x9D, 0xBC, 0xDF, 0x7A, 0x8E, 0x89, 0x80,
343 0x9B, 0xB6, 0xC1, 0x58, 0xE8, 0x23, 0x65, 0xAF, 0xEA, 0x25, 0x6F, 0xB1, 0xC8, 0x43, 0xC5, 0x54,
344 0xFC, 0x1F, 0x21, 0x63, 0xA5, 0xF4, 0x07, 0x09, 0x1B, 0x2D, 0x77, 0x99, 0xB0, 0xCB, 0x46, 0xCA,
345 0x45, 0xCF, 0x4A, 0xDE, 0x79, 0x8B, 0x86, 0x91, 0xA8, 0xE3, 0x3E, 0x42, 0xC6, 0x51, 0xF3, 0x0E,
346 0x12, 0x36, 0x5A, 0xEE, 0x29, 0x7B, 0x8D, 0x8C, 0x8F, 0x8A, 0x85, 0x94, 0xA7, 0xF2, 0x0D, 0x17,
347 0x39, 0x4B, 0xDD, 0x7C, 0x84, 0x97, 0xA2, 0xFD, 0x1C, 0x24, 0x6C, 0xB4, 0xC7, 0x52, 0xF6, 0x01)
348 RIJNDAEL_LOG_TABLE
= (0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6, 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
349 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef, 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
350 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a, 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
351 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24, 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
352 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94, 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
353 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62, 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
354 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42, 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
355 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca, 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
356 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74, 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
357 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5, 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
358 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec, 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
359 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86, 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
360 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc, 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
361 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47, 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
362 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89, 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
363 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18, 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07)
366 def key_expansion(data
):
368 Generate key schedule
370 @param {int[]} data 16/24/32-Byte cipher key
371 @returns {int[]} 176/208/240-Byte expanded key
373 data
= data
[:] # copy
375 key_size_bytes
= len(data
)
376 expanded_key_size_bytes
= (key_size_bytes
// 4 + 7) * BLOCK_SIZE_BYTES
378 while len(data
) < expanded_key_size_bytes
:
380 temp
= key_schedule_core(temp
, rcon_iteration
)
382 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
386 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
388 if key_size_bytes
== 32:
390 temp
= sub_bytes(temp
)
391 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
393 for _
in range(3 if key_size_bytes
== 32 else 2 if key_size_bytes
== 24 else 0):
395 data
+= xor(temp
, data
[-key_size_bytes
: 4 - key_size_bytes
])
396 data
= data
[:expanded_key_size_bytes
]
408 return [SBOX
[x
] for x
in data
]
411 def sub_bytes_inv(data
):
412 return [SBOX_INV
[x
] for x
in data
]
416 return data
[1:] + [data
[0]]
419 def key_schedule_core(data
, rcon_iteration
):
421 data
= sub_bytes(data
)
422 data
[0] = data
[0] ^ RCON
[rcon_iteration
]
427 def xor(data1
, data2
):
428 return [x ^ y
for x
, y
in zip(data1
, data2
)]
431 def iter_mix_columns(data
, matrix
):
432 for i
in (0, 4, 8, 12):
437 mixed ^
= (0 if data
[i
:i
+ 4][j
] == 0 or row
[j
] == 0 else
438 RIJNDAEL_EXP_TABLE
[(RIJNDAEL_LOG_TABLE
[data
[i
+ j
]] + RIJNDAEL_LOG_TABLE
[row
[j
]]) % 0xFF])
442 def shift_rows(data
):
443 return [data
[((column
+ row
) & 0b11) * 4 + row
] for column
in range(4) for row
in range(4)]
446 def shift_rows_inv(data
):
447 return [data
[((column
- row
) & 0b11) * 4 + row
] for column
in range(4) for row
in range(4)]
450 def shift_block(data
):
459 data_shifted
.append(n
)
465 data
= data
[:] # copy
466 for i
in range(len(data
) - 1, -1, -1):
470 data
[i
] = data
[i
] + 1
475 def block_product(block_x
, block_y
):
476 # NIST SP 800-38D, Algorithm 1
478 if len(block_x
) != BLOCK_SIZE_BYTES
or len(block_y
) != BLOCK_SIZE_BYTES
:
479 raise ValueError("Length of blocks need to be %d bytes" % BLOCK_SIZE_BYTES
)
481 block_r
= [0xE1] + [0] * (BLOCK_SIZE_BYTES
- 1)
483 block_z
= [0] * BLOCK_SIZE_BYTES
486 for bit
in range(7, -1, -1):
488 block_z
= xor(block_z
, block_v
)
490 do_xor
= block_v
[-1] & 1
491 block_v
= shift_block(block_v
)
493 block_v
= xor(block_v
, block_r
)
498 def ghash(subkey
, data
):
499 # NIST SP 800-38D, Algorithm 2
501 if len(data
) % BLOCK_SIZE_BYTES
:
502 raise ValueError("Length of data should be %d bytes" % BLOCK_SIZE_BYTES
)
504 last_y
= [0] * BLOCK_SIZE_BYTES
505 for i
in range(0, len(data
), BLOCK_SIZE_BYTES
):
506 block
= data
[i
: i
+ BLOCK_SIZE_BYTES
] # noqa: E203
507 last_y
= block_product(xor(last_y
, block
), subkey
)
515 'aes_cbc_decrypt_bytes',
518 'aes_gcm_decrypt_and_verify',
519 'aes_gcm_decrypt_and_verify_bytes',