Utilities/crypto/py3AES.py

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

eric ide

mercurial