1"""Pure-Python AES implementation."""
2
3from cryptomath import *
4
5from AES import *
6from rijndael import rijndael
7
8def new(key, mode, IV):
9    return Python_AES(key, mode, IV)
10
11class Python_AES(AES):
12    def __init__(self, key, mode, IV):
13        AES.__init__(self, key, mode, IV, "python")
14        self.rijndael = rijndael(key, 16)
15        self.IV = IV
16
17    def encrypt(self, plaintext):
18        AES.encrypt(self, plaintext)
19
20        plaintextBytes = stringToBytes(plaintext)
21        chainBytes = stringToBytes(self.IV)
22
23        #CBC Mode: For each block...
24        for x in range(len(plaintextBytes)/16):
25
26            #XOR with the chaining block
27            blockBytes = plaintextBytes[x*16 : (x*16)+16]
28            for y in range(16):
29                blockBytes[y] ^= chainBytes[y]
30            blockString = bytesToString(blockBytes)
31
32            #Encrypt it
33            encryptedBytes = stringToBytes(self.rijndael.encrypt(blockString))
34
35            #Overwrite the input with the output
36            for y in range(16):
37                plaintextBytes[(x*16)+y] = encryptedBytes[y]
38
39            #Set the next chaining block
40            chainBytes = encryptedBytes
41
42        self.IV = bytesToString(chainBytes)
43        return bytesToString(plaintextBytes)
44
45    def decrypt(self, ciphertext):
46        AES.decrypt(self, ciphertext)
47
48        ciphertextBytes = stringToBytes(ciphertext)
49        chainBytes = stringToBytes(self.IV)
50
51        #CBC Mode: For each block...
52        for x in range(len(ciphertextBytes)/16):
53
54            #Decrypt it
55            blockBytes = ciphertextBytes[x*16 : (x*16)+16]
56            blockString = bytesToString(blockBytes)
57            decryptedBytes = stringToBytes(self.rijndael.decrypt(blockString))
58
59            #XOR with the chaining block and overwrite the input with output
60            for y in range(16):
61                decryptedBytes[y] ^= chainBytes[y]
62                ciphertextBytes[(x*16)+y] = decryptedBytes[y]
63
64            #Set the next chaining block
65            chainBytes = blockBytes
66
67        self.IV = bytesToString(chainBytes)
68        return bytesToString(ciphertextBytes)
69