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