Utilities/crypto/py3AES.py

branch
Py2 comp.
changeset 3057
10516539f238
parent 2525
8b507a9a2d40
parent 2997
7f0ef975da9e
child 3058
0a02c433f52d
equal deleted inserted replaced
3056:9986ec0e559a 3057:10516539f238
4 # from the SlowAES project, http://code.google.com/p/slowaes/ 4 # from the SlowAES project, http://code.google.com/p/slowaes/
5 # 5 #
6 # Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ), 6 # Copyright (c) 2008 Josh Davis ( http://www.josh-davis.org ),
7 # Alex Martelli ( http://www.aleax.it ) 7 # Alex Martelli ( http://www.aleax.it )
8 # 8 #
9 # Ported from C code written by Laurent Haan ( http://www.progressive-coding.com ) 9 # Ported from C code written by Laurent Haan
10 # ( http://www.progressive-coding.com )
10 # 11 #
11 # Licensed under the Apache License, Version 2.0 12 # Licensed under the Apache License, Version 2.0
12 # http://www.apache.org/licenses/ 13 # http://www.apache.org/licenses/
13 # 14 #
14 15
46 47
47 @param b data to be stripped (bytes) 48 @param b data to be stripped (bytes)
48 @return stripped data (bytes) 49 @return stripped data (bytes)
49 """ 50 """
50 if len(b) % 16 or not b: 51 if len(b) % 16 or not b:
51 raise ValueError("Data of len {0} can't be PCKS7-padded".format(len(b))) 52 raise ValueError(
53 "Data of len {0} can't be PCKS7-padded".format(len(b)))
52 numpads = b[-1] 54 numpads = b[-1]
53 if numpads > 16: 55 if numpads > 16:
54 raise ValueError("Data ending with {0} can't be PCKS7-padded".format(b[-1])) 56 raise ValueError(
57 "Data ending with {0} can't be PCKS7-padded".format(b[-1]))
55 return b[:-numpads] 58 return b[:-numpads]
56 59
57 60
58 class AES(object): 61 class AES(object):
59 """ 62 """
164 167
165 def __rotate(self, data): 168 def __rotate(self, data):
166 """ 169 """
167 Private method performing Rijndael's key schedule rotate operation. 170 Private method performing Rijndael's key schedule rotate operation.
168 171
169 Rotate the data word eight bits to the left: eg, rotate(1d2c3a4f) == 2c3a4f1d. 172 Rotate the data word eight bits to the left: eg,
173 rotate(1d2c3a4f) == 2c3a4f1d.
170 174
171 @param data data of size 4 (bytearray) 175 @param data data of size 4 (bytearray)
172 """ 176 """
173 return data[1:] + data[:1] 177 return data[1:] + data[:1]
174 178
228 # and increment rconIteration afterwards 232 # and increment rconIteration afterwards
229 if currentSize % size == 0: 233 if currentSize % size == 0:
230 t = self.__core(t, rconIteration) 234 t = self.__core(t, rconIteration)
231 rconIteration += 1 235 rconIteration += 1
232 # For 256-bit keys, we add an extra sbox to the calculation 236 # For 256-bit keys, we add an extra sbox to the calculation
233 if size == self.KeySize["SIZE_256"] and ((currentSize % size) == 16): 237 if size == self.KeySize["SIZE_256"] and \
238 ((currentSize % size) == 16):
234 for l in range(4): 239 for l in range(4):
235 t[l] = self.__getSBoxValue(t[l]) 240 t[l] = self.__getSBoxValue(t[l])
236 241
237 # We XOR t with the four-byte block 16, 24, 32 bytes before the new 242 # We XOR t with the four-byte block 16, 24, 32 bytes before the new
238 # expanded key. This becomes the next four bytes in the expanded key. 243 # expanded key. This becomes the next four bytes in the expanded
244 # key.
239 for m in range(4): 245 for m in range(4):
240 expandedKey[currentSize] = \ 246 expandedKey[currentSize] = \
241 expandedKey[currentSize - size] ^ t[m] 247 expandedKey[currentSize - size] ^ t[m]
242 currentSize += 1 248 currentSize += 1
243 249
270 roundKey[j * 4 + i] = expandedKey[roundKeyPointer + i * 4 + j] 276 roundKey[j * 4 + i] = expandedKey[roundKeyPointer + i * 4 + j]
271 return roundKey 277 return roundKey
272 278
273 def __galois_multiplication(self, a, b): 279 def __galois_multiplication(self, a, b):
274 """ 280 """
275 Private method to perform a Galois multiplication of 8 bit characters a and b. 281 Private method to perform a Galois multiplication of 8 bit characters
282 a and b.
276 283
277 @param a first factor (byte) 284 @param a first factor (byte)
278 @param b second factor (byte) 285 @param b second factor (byte)
279 @return result (byte) 286 @return result (byte)
280 """ 287 """
291 b >>= 1 298 b >>= 1
292 return p 299 return p
293 300
294 def __subBytes(self, state, isInv): 301 def __subBytes(self, state, isInv):
295 """ 302 """
296 Private method to substitute all the values from the state with the value in 303 Private method to substitute all the values from the state with the
297 the SBox using the state value as index for the SBox. 304 value in the SBox using the state value as index for the SBox.
298 305
299 @param state state to be worked on (bytearray) 306 @param state state to be worked on (bytearray)
300 @param isInv flag indicating an inverse operation (boolean) 307 @param isInv flag indicating an inverse operation (boolean)
301 @return modified state (bytearray) 308 @return modified state (bytearray)
302 """ 309 """
366 return state 373 return state
367 374
368 # galois multiplication of 1 column of the 4x4 matrix 375 # galois multiplication of 1 column of the 4x4 matrix
369 def __mixColumn(self, column, isInv): 376 def __mixColumn(self, column, isInv):
370 """ 377 """
371 Private method to perform a galois multiplication of 1 column the 4x4 matrix. 378 Private method to perform a galois multiplication of 1 column the
379 4x4 matrix.
372 380
373 @param column column to be worked on (bytearray) 381 @param column column to be worked on (bytearray)
374 @param isInv flag indicating an inverse operation (boolean) 382 @param isInv flag indicating an inverse operation (boolean)
375 @return modified column (bytearray) 383 @return modified column (bytearray)
376 """ 384 """
392 g(cpy[1], mult[2]) ^ g(cpy[0], mult[3]) 400 g(cpy[1], mult[2]) ^ g(cpy[0], mult[3])
393 return column 401 return column
394 402
395 def __aes_round(self, state, roundKey): 403 def __aes_round(self, state, roundKey):
396 """ 404 """
397 Private method to apply the 4 operations of the forward round in sequence. 405 Private method to apply the 4 operations of the forward round in
406 sequence.
398 407
399 @param state state to be worked on (bytearray) 408 @param state state to be worked on (bytearray)
400 @param roundKey round key to be used (bytearray) 409 @param roundKey round key to be used (bytearray)
401 @return modified state (bytearray) 410 @return modified state (bytearray)
402 """ 411 """
406 state = self.__addRoundKey(state, roundKey) 415 state = self.__addRoundKey(state, roundKey)
407 return state 416 return state
408 417
409 def __aes_invRound(self, state, roundKey): 418 def __aes_invRound(self, state, roundKey):
410 """ 419 """
411 Private method to apply the 4 operations of the inverse round in sequence. 420 Private method to apply the 4 operations of the inverse round in
421 sequence.
412 422
413 @param state state to be worked on (bytearray) 423 @param state state to be worked on (bytearray)
414 @param roundKey round key to be used (bytearray) 424 @param roundKey round key to be used (bytearray)
415 @return modified state (bytearray) 425 @return modified state (bytearray)
416 """ 426 """
420 state = self.__mixColumns(state, True) 430 state = self.__mixColumns(state, True)
421 return state 431 return state
422 432
423 def __aes_main(self, state, expandedKey, nbrRounds): 433 def __aes_main(self, state, expandedKey, nbrRounds):
424 """ 434 """
425 Private method to perform the initial operations, the standard round, and the 435 Private method to do the AES encryption for one round.
426 final operations of the forward AES, creating a round key for each round. 436
437 Perform the initial operations, the standard round, and the
438 final operations of the forward AES, creating a round key for
439 each round.
427 440
428 @param state state to be worked on (bytearray) 441 @param state state to be worked on (bytearray)
429 @param expandedKey expanded key to be used (bytearray) 442 @param expandedKey expanded key to be used (bytearray)
430 @param nbrRounds number of rounds to be done (integer) 443 @param nbrRounds number of rounds to be done (integer)
431 @return modified state (bytearray) 444 @return modified state (bytearray)
432 """ 445 """
433 state = self.__addRoundKey(state, self.__createRoundKey(expandedKey, 0)) 446 state = self.__addRoundKey(
447 state, self.__createRoundKey(expandedKey, 0))
434 i = 1 448 i = 1
435 while i < nbrRounds: 449 while i < nbrRounds:
436 state = self.__aes_round( 450 state = self.__aes_round(
437 state, self.__createRoundKey(expandedKey, 16 * i)) 451 state, self.__createRoundKey(expandedKey, 16 * i))
438 i += 1 452 i += 1
442 state, self.__createRoundKey(expandedKey, 16 * nbrRounds)) 456 state, self.__createRoundKey(expandedKey, 16 * nbrRounds))
443 return state 457 return state
444 458
445 def __aes_invMain(self, state, expandedKey, nbrRounds): 459 def __aes_invMain(self, state, expandedKey, nbrRounds):
446 """ 460 """
447 Private method to perform the initial operations, the standard round, and the 461 Private method to do the inverse AES encryption for one round.
448 final operations of the inverse AES, creating a round key for each round. 462
463 Perform the initial operations, the standard round, and the
464 final operations of the inverse AES, creating a round key for
465 each round.
449 466
450 @param state state to be worked on (bytearray) 467 @param state state to be worked on (bytearray)
451 @param expandedKey expanded key to be used (bytearray) 468 @param expandedKey expanded key to be used (bytearray)
452 @param nbrRounds number of rounds to be done (integer) 469 @param nbrRounds number of rounds to be done (integer)
453 @return modified state (bytearray) 470 @return modified state (bytearray)
459 state = self.__aes_invRound( 476 state = self.__aes_invRound(
460 state, self.__createRoundKey(expandedKey, 16 * i)) 477 state, self.__createRoundKey(expandedKey, 16 * i))
461 i -= 1 478 i -= 1
462 state = self.__shiftRows(state, True) 479 state = self.__shiftRows(state, True)
463 state = self.__subBytes(state, True) 480 state = self.__subBytes(state, True)
464 state = self.__addRoundKey(state, self.__createRoundKey(expandedKey, 0)) 481 state = self.__addRoundKey(
482 state, self.__createRoundKey(expandedKey, 0))
465 return state 483 return state
466 484
467 def encrypt(self, iput, key, size): 485 def encrypt(self, iput, key, size):
468 """ 486 """
469 Public method to encrypt a 128 bit input block against the given key of size 487 Public method to encrypt a 128 bit input block against the given key
470 specified. 488 of size specified.
471 489
472 @param iput input data (bytearray) 490 @param iput input data (bytearray)
473 @param key key to be used (bytes or bytearray) 491 @param key key to be used (bytes or bytearray)
474 @param size key size (16, 24 or 32) 492 @param size key size (16, 24 or 32)
475 @return encrypted data (bytes) 493 @return encrypted data (bytes)
520 return bytes(output) 538 return bytes(output)
521 539
522 # decrypts a 128 bit input block against the given key of size specified 540 # decrypts a 128 bit input block against the given key of size specified
523 def decrypt(self, iput, key, size): 541 def decrypt(self, iput, key, size):
524 """ 542 """
525 Public method to decrypt a 128 bit input block against the given key of size 543 Public method to decrypt a 128 bit input block against the given key
526 specified. 544 of size specified.
527 545
528 @param iput input data (bytearray) 546 @param iput input data (bytearray)
529 @param key key to be used (bytes or bytearray) 547 @param key key to be used (bytes or bytearray)
530 @param size key size (16, 24 or 32) 548 @param size key size (16, 24 or 32)
531 @return decrypted data (bytes) 549 @return decrypted data (bytes)
801 """ 819 """
802 key = bytearray(key) 820 key = bytearray(key)
803 if mode == AESModeOfOperation.ModeOfOperation["CBC"]: 821 if mode == AESModeOfOperation.ModeOfOperation["CBC"]:
804 data = append_PKCS7_padding(data) 822 data = append_PKCS7_padding(data)
805 keysize = len(key) 823 keysize = len(key)
806 assert keysize in AES.KeySize.values(), 'invalid key size: {0}'.format(keysize) 824 assert keysize in AES.KeySize.values(), \
825 'invalid key size: {0}'.format(keysize)
807 # create a new iv using random data 826 # create a new iv using random data
808 iv = bytearray([i for i in os.urandom(16)]) 827 iv = bytearray([i for i in os.urandom(16)])
809 moo = AESModeOfOperation() 828 moo = AESModeOfOperation()
810 mode, length, ciph = moo.encrypt(data, mode, key, keysize, iv) 829 mode, length, ciph = moo.encrypt(data, mode, key, keysize, iv)
811 # With padding, the original length does not need to be known. It's a bad 830 # With padding, the original length does not need to be known. It's a bad
817 def decryptData(key, data, mode=AESModeOfOperation.ModeOfOperation["CBC"]): 836 def decryptData(key, data, mode=AESModeOfOperation.ModeOfOperation["CBC"]):
818 """ 837 """
819 Module function to decrypt the given data with the given key. 838 Module function to decrypt the given data with the given key.
820 839
821 @param key key to be used for decryption (bytes) 840 @param key key to be used for decryption (bytes)
822 @param data data to be decrypted (with initialization vector prepended) (bytes) 841 @param data data to be decrypted (with initialization vector prepended)
842 (bytes)
823 @param mode mode of operations (0, 1 or 2) 843 @param mode mode of operations (0, 1 or 2)
824 @return decrypted data (bytes) 844 @return decrypted data (bytes)
825 @exception ValueError key size is invalid or decrypted data is invalid 845 @exception ValueError key size is invalid or decrypted data is invalid
826 """ 846 """
827 key = bytearray(key) 847 key = bytearray(key)

eric ide

mercurial