| 140 |
Kevin |
1 |
# S-box lookup table calculated from the field F_{2^8} = Z_2[x]/x^8+x^4+x^3+x+1
|
|
|
2 |
# 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
|
3 |
s_box = [[0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76],#0
|
|
|
4 |
[0XCA,0X82,0XC9,0X7D,0XFA,0X59,0X47,0XF0,0XAD,0XD4,0XA2,0XAF,0X9C,0XA4,0X72,0XC0],#1
|
|
|
5 |
[0XB7,0XFD,0X93,0X26,0X36,0X3F,0XF7,0XCC,0X34,0XA5,0XE5,0XF1,0X71,0XD8,0X31,0X15],#1
|
|
|
6 |
[0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75],#3
|
|
|
7 |
[0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84],#4
|
|
|
8 |
[0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF],#5
|
|
|
9 |
[0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8],#6
|
|
|
10 |
[0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2],#7
|
|
|
11 |
[0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73],#8
|
|
|
12 |
[0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB],#9
|
|
|
13 |
[0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79],#A
|
|
|
14 |
[0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08],#B
|
|
|
15 |
[0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A],#C
|
|
|
16 |
[0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E],#D
|
|
|
17 |
[0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF],#E
|
|
|
18 |
[0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16]]#F
|
|
|
19 |
|
|
|
20 |
# Key expansion lookup table
|
|
|
21 |
RCon = [[0x01,0x00,0x00,0x00],[0x02,0x00,0x00,0x00],[0x04,0x00,0x00,0x00],[0x08,0x00,0x00,0x00],
|
|
|
22 |
[0x10,0x00,0x00,0x00],[0x20,0x00,0x00,0x00],[0x40,0x00,0x00,0x00],[0x80,0x00,0x00,0x00],
|
|
|
23 |
[0x1B,0x00,0x00,0x00],[0x36,0x00,0x00,0x00]]
|
|
|
24 |
|
|
|
25 |
# Encryption key
|
|
|
26 |
encryption_key = [0x2B,0x7E,0x15,0x16,0x28,0xAE,0xD2,0xA6,0xAB,0xF7,0x15,0x88,0x09,0xCF,0x4F,0x3C]
|
|
|
27 |
|
|
|
28 |
# Input plaintext
|
|
|
29 |
plaintext = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]
|
|
|
30 |
|
|
|
31 |
def RotWord(byte_array):
|
|
|
32 |
'''Takes a list of bytes and cyclic left shifts it by one.'''
|
|
|
33 |
byte_array.append(byte_array.pop(0))
|
|
|
34 |
return byte_array
|
|
|
35 |
|
|
|
36 |
def SubBytes(byte_array):
|
|
|
37 |
'''Substitutes each byte in the given list with the value in the s-box.'''
|
|
|
38 |
for i in range(len(byte_array)):
|
|
|
39 |
byte_array[i] = s_box[(byte_array[i]&0xF0)>>4][byte_array[i]&0xF]
|
|
|
40 |
return byte_array
|
|
|
41 |
|
|
|
42 |
def XorBytes(byte_array,input):
|
|
|
43 |
'''XORs two byte arrays and returns the result.'''
|
|
|
44 |
for i in range(len(byte_array)):
|
|
|
45 |
byte_array[i] ^= input[i]
|
|
|
46 |
return byte_array
|
|
|
47 |
|
|
|
48 |
def ShiftRows(byte_array):
|
|
|
49 |
'''Shifts the second row left by one, the third row by two, and the fourth row by three.'''
|
|
|
50 |
# Shift second row
|
|
|
51 |
temp = byte_array[1]
|
|
|
52 |
byte_array[1] = byte_array[5]
|
|
|
53 |
byte_array[5] = byte_array[9]
|
|
|
54 |
byte_array[9] = byte_array[13]
|
|
|
55 |
byte_array[13] = temp
|
|
|
56 |
# Shift third row
|
|
|
57 |
temp = byte_array[2]
|
|
|
58 |
byte_array[2] = byte_array[10]
|
|
|
59 |
byte_array[10] = temp
|
|
|
60 |
temp = byte_array[6]
|
|
|
61 |
byte_array[6] = byte_array[14]
|
|
|
62 |
byte_array[14] = temp
|
|
|
63 |
# Shift fourth row
|
|
|
64 |
temp = byte_array[3]
|
|
|
65 |
byte_array[3] = byte_array[15]
|
|
|
66 |
byte_array[15] = byte_array[11]
|
|
|
67 |
byte_array[11] = byte_array[7]
|
|
|
68 |
byte_array[7] = temp
|
|
|
69 |
return byte_array
|
|
|
70 |
|
|
|
71 |
def MC_Mul(byte,mul):
|
|
|
72 |
'''Helper function for MixColumns'''
|
|
|
73 |
if mul == 2:
|
|
|
74 |
byte <<= 1
|
|
|
75 |
if byte > 0xFF:
|
|
|
76 |
byte ^= 0x11B
|
|
|
77 |
elif mul == 3:
|
|
|
78 |
byte = (byte<<1)^byte
|
|
|
79 |
if byte > 0xFF:
|
|
|
80 |
byte ^= 0x11B
|
|
|
81 |
return byte
|
|
|
82 |
|
|
|
83 |
def MixColumns(byte_array):
|
|
|
84 |
'''Mixes each column by multiplying it with a certain matrix of elements of the field F_{2^8}.'''
|
|
|
85 |
ret = []
|
|
|
86 |
for i in [0,4,8,12]:
|
|
|
87 |
ret.append((MC_Mul(byte_array[i],2) ^ MC_Mul(byte_array[i+1],3) ^ byte_array[i+2] ^ byte_array[i+3])&0xFF)
|
|
|
88 |
ret.append((byte_array[i] ^ MC_Mul(byte_array[i+1],2) ^ MC_Mul(byte_array[i+2],3) ^ byte_array[i+3])&0xFF)
|
|
|
89 |
ret.append((byte_array[i] ^ byte_array[i+1] ^ MC_Mul(byte_array[i+2],2) ^ MC_Mul(byte_array[i+3],3))&0xFF)
|
|
|
90 |
ret.append((MC_Mul(byte_array[i],3) ^ byte_array[i+1] ^ byte_array[i+2] ^ MC_Mul(byte_array[i+3],2))&0xFF)
|
|
|
91 |
return ret
|
|
|
92 |
|
|
|
93 |
def KeyExpansion(key):
|
|
|
94 |
'''Computes and returns the expansion key for a given encryption key.'''
|
|
|
95 |
expanded_key = []
|
|
|
96 |
for i in range(4):
|
|
|
97 |
expanded_key.append([key[4*i],key[4*i+1],key[4*i+2],key[4*i+3]])
|
|
|
98 |
for i in range(4,44):
|
|
|
99 |
temp = list(expanded_key[i-1])
|
|
|
100 |
if i % 4 == 0:
|
|
|
101 |
temp = XorBytes(SubBytes(RotWord(temp)),RCon[(i/4)-1])
|
|
|
102 |
expanded_key.append(XorBytes(list(expanded_key[i-4]),temp))
|
|
|
103 |
return expanded_key
|
|
|
104 |
|
|
|
105 |
def RoundKey(expansion_key,round):
|
|
|
106 |
'''Computes and returns the round key given the expansion key.'''
|
|
|
107 |
round_key = []
|
|
|
108 |
for i in range(4):
|
|
|
109 |
for j in range(4):
|
|
|
110 |
round_key.append(expansion_key[4*round+i][j])
|
|
|
111 |
return round_key
|
|
|
112 |
|
|
|
113 |
if __name__ == '__main__':
|
|
|
114 |
# Calculate and print out the round keys
|
|
|
115 |
expansion_key = KeyExpansion(encryption_key)
|
|
|
116 |
for i in range(11):
|
|
|
117 |
round_key = RoundKey(expansion_key, i)
|
|
|
118 |
print "Round Key %d:" % i,
|
|
|
119 |
for j in range(16):
|
|
|
120 |
print "%02X" % round_key[j],
|
|
|
121 |
print
|
|
|
122 |
print
|
|
|
123 |
|
|
|
124 |
# Print out round 0 info
|
|
|
125 |
state = list(plaintext)
|
|
|
126 |
print "Initial state = plaintext:\t",
|
|
|
127 |
for i in range(16):
|
|
|
128 |
print "%02X" % state[i],
|
|
|
129 |
print
|
|
|
130 |
|
|
|
131 |
print "Round 0 (Add Round Key 0):\t",
|
|
|
132 |
state = XorBytes(state, RoundKey(expansion_key, 0))
|
|
|
133 |
for i in range(16):
|
|
|
134 |
print "%02X" % state[i],
|
|
|
135 |
print "\n"
|
|
|
136 |
|
|
|
137 |
# Print out the results of each round
|
|
|
138 |
for i in range(1,10):
|
|
|
139 |
print "Round %d (SubBytes):\t\t\t" % i,
|
|
|
140 |
state = SubBytes(state)
|
|
|
141 |
for j in range(16):
|
|
|
142 |
print "%02X" % state[j],
|
|
|
143 |
print
|
|
|
144 |
|
|
|
145 |
print "Round %d (ShiftRows):\t\t" % i,
|
|
|
146 |
state = ShiftRows(state)
|
|
|
147 |
for j in range(16):
|
|
|
148 |
print "%02X" % state[j],
|
|
|
149 |
print
|
|
|
150 |
|
|
|
151 |
print "Round %d (MixColumns):\t\t" % i,
|
|
|
152 |
state = MixColumns(state)
|
|
|
153 |
for j in range(16):
|
|
|
154 |
print "%02X" % state[j],
|
|
|
155 |
print
|
|
|
156 |
|
|
|
157 |
print "Round %d (Add Round Key %d):\t" % (i,i),
|
|
|
158 |
state = XorBytes(state, RoundKey(expansion_key, i))
|
|
|
159 |
for j in range(16):
|
|
|
160 |
print "%02X" % state[j],
|
|
|
161 |
print "\n"
|
|
|
162 |
|
|
|
163 |
# Print out the results for the final round
|
|
|
164 |
print "Round 10 (SubBytes):\t\t",
|
|
|
165 |
state = SubBytes(state)
|
|
|
166 |
for j in range(16):
|
|
|
167 |
print "%02X" % state[j],
|
|
|
168 |
print
|
|
|
169 |
|
|
|
170 |
print "Round 10 (ShiftRows):\t\t",
|
|
|
171 |
state = ShiftRows(state)
|
|
|
172 |
for j in range(16):
|
|
|
173 |
print "%02X" % state[j],
|
|
|
174 |
print
|
|
|
175 |
|
|
|
176 |
print "Round 10 (Add Round Key 10):",
|
|
|
177 |
state = XorBytes(state, RoundKey(expansion_key, 10))
|
|
|
178 |
for j in range(16):
|
|
|
179 |
print "%02X" % state[j],
|
|
|
180 |
print "\n"
|
|
|
181 |
|
|
|
182 |
# Print the ciphertext
|
|
|
183 |
print "Ciphertext:\t\t\t",
|
|
|
184 |
for j in range(16):
|
|
|
185 |
print "%02X" % state[j],
|
|
|
186 |
print
|