1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch# Author: Trevor Perrin 2a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch# See the LICENSE file for legal information regarding use of this file. 3a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Pure-Python AES implementation.""" 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom .cryptomath import * 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom .aes import * 9a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochfrom .rijndael import rijndael 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def new(key, mode, IV): 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Python_AES(key, mode, IV) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Python_AES(AES): 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, key, mode, IV): 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AES.__init__(self, key, mode, IV, "python") 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.rijndael = rijndael(key, 16) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.IV = IV 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def encrypt(self, plaintext): 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AES.encrypt(self, plaintext) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch plaintextBytes = plaintext[:] 24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch chainBytes = self.IV[:] 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #CBC Mode: For each block... 27a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for x in range(len(plaintextBytes)//16): 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #XOR with the chaining block 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blockBytes = plaintextBytes[x*16 : (x*16)+16] 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for y in range(16): 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blockBytes[y] ^= chainBytes[y] 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #Encrypt it 35a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch encryptedBytes = self.rijndael.encrypt(blockBytes) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #Overwrite the input with the output 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for y in range(16): 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) plaintextBytes[(x*16)+y] = encryptedBytes[y] 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #Set the next chaining block 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chainBytes = encryptedBytes 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 44a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch self.IV = chainBytes[:] 45a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return plaintextBytes 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def decrypt(self, ciphertext): 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AES.decrypt(self, ciphertext) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ciphertextBytes = ciphertext[:] 51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch chainBytes = self.IV[:] 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #CBC Mode: For each block... 54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch for x in range(len(ciphertextBytes)//16): 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #Decrypt it 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) blockBytes = ciphertextBytes[x*16 : (x*16)+16] 58a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch decryptedBytes = self.rijndael.decrypt(blockBytes) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #XOR with the chaining block and overwrite the input with output 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for y in range(16): 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decryptedBytes[y] ^= chainBytes[y] 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ciphertextBytes[(x*16)+y] = decryptedBytes[y] 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) #Set the next chaining block 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chainBytes = blockBytes 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 68a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch self.IV = chainBytes[:] 69a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return ciphertextBytes 70