1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
| from Crypto.Util.number import *
class AES:
MIX_C = [[0x2, 0x3, 0x1, 0x1], [0x1, 0x2, 0x3, 0x1], [0x1, 0x1, 0x2, 0x3], [0x3, 0x1, 0x1, 0x2]] I_MIXC = [[0xe, 0xb, 0xd, 0x9], [0x9, 0xe, 0xb, 0xd], [0xd, 0x9, 0xe, 0xb], [0xb, 0xd, 0x9, 0xe]] RCon = [0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000]
S_BOX = [[99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118], [202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192], [183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21], [4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117], [9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132], [83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207], [208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168], [81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210], [205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115], [96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219], [224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121], [231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8], [186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138], [112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158], [225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223], [140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22]]
I_SBOX = [[82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251], [124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203], [84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78], [8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37], [114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146], [108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132], [144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6], [208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107], [58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115], [150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110], [71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27], [252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244], [31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95], [96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239], [160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97], [23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125]]
def SubBytes(self, State): return [self.S_BOX[i][j]^0xA1 for i, j in [(_ >> 4, _ & 0xF) for _ in State]]
def SubBytes_Inv(self, State): State = [i^0xA1 for i in State] return [self.I_SBOX[i][j] for i, j in [(_ >> 4, _ & 0xF) for _ in State]]
def ShiftRows(self, S): return [S[ 0], S[ 5], S[10], S[15], S[ 4], S[ 9], S[14], S[ 3], S[ 8], S[13], S[ 2], S[ 7], S[12], S[ 1], S[ 6], S[11]]
def ShiftRows_Inv(self, S): return [S[ 0], S[13], S[10], S[ 7], S[ 4], S[ 1], S[14], S[11], S[ 8], S[ 5], S[ 2], S[15], S[12], S[ 9], S[ 6], S[ 3]]
def MixColumns(self, State): return self.Matrix_Mul(self.MIX_C, State)
def MixColumns_Inv(self, State): return self.Matrix_Mul(self.I_MIXC, State)
def RotWord(self, _4byte_block): return ((_4byte_block & 0xffffff) << 8) + (_4byte_block >> 24)
def SubWord(self, _4byte_block): result = 0 for position in range(4): i = _4byte_block >> position * 8 + 4 & 0xf j = _4byte_block >> position * 8 & 0xf result ^= self.S_BOX[i][j] << position * 8 return result
def mod(self, poly, mod = 0b100011011): while poly.bit_length() > 8: poly ^= mod << poly.bit_length() - 9 return poly
def mul(self, poly1, poly2): result = 0 for index in range(poly2.bit_length()): if poly2 & 1 << index: result ^= poly1 << index return result
def Matrix_Mul(self, M1, M2): M = [0] * 16 for row in range(4): for col in range(4): for Round in range(4): M[row + col*4] ^= self.mul(M1[row][Round], M2[Round+col*4]) M[row + col*4] = self.mod(M[row + col*4]) M[row + col*4] ^= 0x54 return M
def round_key_generator(self, _16bytes_key): w = [_16bytes_key >> 96, _16bytes_key >> 64 & 0xFFFFFFFF, _16bytes_key >> 32 & 0xFFFFFFFF, _16bytes_key & 0xFFFFFFFF] + [0]*40 for i in range(4, 44): temp = w[i-1] if not i % 4: temp = self.SubWord(self.RotWord(temp)) ^ self.RCon[i//4-1] w[i] = w[i-4] ^ temp return [self.num_2_16bytes( sum([w[4 * i] << 96, w[4*i+1] << 64, w[4*i+2] << 32, w[4*i+3]]) ) for i in range(11)]
def AddRoundKey(self, State, RoundKeys, index): return self._16bytes_xor(State, RoundKeys[index])
def _16bytes_xor(self, _16bytes_1, _16bytes_2): return [_16bytes_1[i] ^ _16bytes_2[i] for i in range(16)]
def _16bytes2num(cls, _16bytes): return int.from_bytes(_16bytes, byteorder = 'big')
def num_2_16bytes(cls, num): return num.to_bytes(16, byteorder = 'big')
def aes_encrypt(self, plaintext_list, RoundKeys): State = plaintext_list State = self.AddRoundKey(State, RoundKeys, 0) xor_key=[0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x03, 0x02, 0x02, 0x03, 0x00, 0x01, 0x03, 0x02, 0x01, 0x00] State = [State[i]^xor_key[i] for i in range(len(xor_key))] for Round in range(1, 10): State = self.SubBytes(State) State = self.ShiftRows(State) State = self.MixColumns(State) State = self.AddRoundKey(State, RoundKeys, Round) State = [State[i]^xor_key[i] for i in range(len(xor_key))] State = self.SubBytes(State) State = self.ShiftRows(State) State = self.AddRoundKey(State, RoundKeys, 10) State = [State[i]^xor_key[i] for i in range(len(xor_key))] return State
def aes_decrypt(self, ciphertext_list, RoundKeys): State = ciphertext_list xor_key=[0x00, 0x01, 0x02, 0x03, 0x01, 0x00, 0x03, 0x02, 0x02, 0x03, 0x00, 0x01, 0x03, 0x02, 0x01, 0x00] State = [State[i]^xor_key[i] for i in range(len(xor_key))] State = self.AddRoundKey(State, RoundKeys, 10) for Round in range(1, 10): State = self.ShiftRows_Inv(State) State = self.SubBytes_Inv(State) State = [State[i]^xor_key[i] for i in range(len(xor_key))] State = self.AddRoundKey(State, RoundKeys, 10-Round) State = self.MixColumns_Inv(State) State = self.ShiftRows_Inv(State) State = self.SubBytes_Inv(State) State = self.AddRoundKey(State, RoundKeys, 0) return State
if __name__ == '__main__':
aes = AES() key = bytes_to_long(b'gah43jJKgfjGMeAR') RoundKeys = aes.round_key_generator(key)
plaintext = bytes_to_long(b'fmcdzRf]3ws^e2o}') plaintext = aes.num_2_16bytes(plaintext) ciphertext = aes.aes_encrypt(plaintext, RoundKeys) print('ciphertext = ' + hex(aes._16bytes2num(ciphertext)))
ciphertext = bytes_to_long(bytes(ciphertext)) ciphertext = aes.num_2_16bytes(ciphertext) plaintext = aes.aes_decrypt(ciphertext, RoundKeys) print(bytes(plaintext))
|