forked from bxt/Ludus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAES.py
148 lines (136 loc) · 5.9 KB
/
AES.py
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
# Die in SubByte verwendete Bijektion F256 -> F256 ist durch folgende Liste gegeben.
# Dabei ist SubByteTable[x] der Funktionswert von x.
global SubByteTable
SubByteTable=[
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16]
# Eingabe ist der AES-Schluessel K (4x4 Matrix ueber F256)
# Ausgabe ist eine Liste L, die die 11 Schluessel L[0], ..., L[10] enthaelt (4x4 Matrizen ueber F256)
def KeyExpansion(K):
R = [0,0x1000000,0x2000000,0x4000000,0x8000000,0x10000000,0x20000000,0x40000000,
0x80000000,0x1b000000,0x36000000]
w = [0]*44
w[0] = K[0][0]*0x1000000 + K[1][0]*0x10000 + K[2][0]*0x100 + K[3][0]
w[1] = K[0][1]*0x1000000 + K[1][1]*0x10000 + K[2][1]*0x100 + K[3][1]
w[2] = K[0][2]*0x1000000 + K[1][2]*0x10000 + K[2][2]*0x100 + K[3][2]
w[3] = K[0][3]*0x1000000 + K[1][3]*0x10000 + K[2][3]*0x100 + K[3][3]
i = 4
while i < 44:
t = w[i-1]
if (i%4) == 0:
t = ((SubByteTable[(t>>16)&0xff]<<24)|(SubByteTable[(t>>8)&0xff]<<16)|
(SubByteTable[(t>>0)&0xff]<<8)|(SubByteTable[(t>>24)&0xff]<<0)) ^ R[i//4]
w[i] = w[i-4] ^ t
i = i + 1
L = []
for r in range(0,11):
K = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
for i in range(0,4):
for j in range(0,4):
K[i][j]=(w[4*r+j]>>(8*(3-i))) & 0xff
L = L + [K]
return L
# Addition in F256
def F256Add(x,y):
return x ^ y
# Multiplikation in F256
def F256Mul(x,y):
z = 0 # zuerst Produkt der Polynome bilden
for i in range(8):
z ^= (1 & y>>i) * (x<<i)
f = 0b100011011 # jetzt modulo f(x)=x^8+x^4+x^3+x+1 rechnen
for i in reversed(range(8,16)):
z ^= (1 & z>>i) * (f << i-8)
return z
def SubByte(A):
B = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
for i in range(0,4):
for j in range(0,4):
B[i][j] = SubByteTable[A[i][j]]
return B
def ShiftRow(A):
B = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
for i in range(4):
B[i] = A[i][i:] + A[i][:i]
return B
def MixCol(A):
B = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
T = [[2,3,1,1],[1,2,3,1],[1,1,2,3],[3,1,1,2]]
for i in range(4):
for k in range(4):
result = 0
for j in range(4):
result = F256Add(result, F256Mul(T[i][j],A[j][k]))
B[i][k] = result
return B
# addiert den Schluessel K zu den Daten A
def AddKey(A,K):
# A = zu verschluesselnde Daten (4x4 Matrix ueber F256)
# K = Schluessel (4x4 Matrix ueber F256)
B = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]
for i in range(4):
for k in range(4):
B[i][k] = F256Add(A[i][k], K[i][k])
return B
# eine AES-Runde bestehend aus SubByte, ShiftRow, MixCol und AddKey
def AESRound(A,K):
# A = zu verschluesselnde Daten (4x4 Matrix ueber F256)
# K = Schluessel (4x4 Matrix ueber F256)
return AddKey(MixCol(ShiftRow(SubByte(A))),K)
# gesamtes AES bestehend aus 11 Runden
def AES(P,K):
# P = zu verschluesselnde Daten (4x4 Matrix ueber F256)
# K = Schluessel (4x4 Matrix ueber F256)
K = KeyExpansion(K)
# K[0], ..., K[10] sind die Schluessel fuer die Runden 0-10 (4x4 Matrizen ueber F256)
C = AddKey(P,K[0]) # round 0
for i in range(1, 10): # round 1 to 9
C = AESRound(C,K[i])
C = AddKey(ShiftRow(SubByte(C)),K[10]) # round 10
return C
# es folgen einige Tests fuer die obigen Funktionen
def AESTests():
if F256Add(123,45)!=86: print("Fehler in F256Add")
#
if F256Mul(123,45)!=128: print("Fehler in F256Mul")
#
A = [[0xe1,0x19,0xb3,0xf7],[0x6c,0x8e,0x56,0xb2],[0x13,0x7f,0x9a,0x1b],[0xe3,0x41,0xe1,0xad]]
B = [[0x9d,0x85,0xfc,0x8e],[0xef,0xde,0x4b,0x08],[0x95,0xaa,0xf2,0x9f],[0x9a,0x58,0xdb,0xea]]
if MixCol(A)!=B: print("Fehler in MixCol")
#
A = [[0x76,0xbd,0xec,0xed],[0x27,0xe5,0xb0,0x20],[0x20,0xa5,0xe6,0x35],[0x87,0xb7,0xe7,0x9e]]
B = [[0x38,0x7a,0xce,0x55],[0xcc,0xd9,0xe7,0xb7],[0xb7,0x06,0x8e,0x96],[0x17,0xa9,0x94,0x0b]]
if SubByte(A)!=B: print("Fehler in SubByte")
#
A = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
B = [[1,2,3,4],[6,7,8,5],[11,12,9,10],[16,13,14,15]]
if ShiftRow(A)!=B: print("Fehler in ShiftRow")
#
A = [[0x76,0xbd,0xec,0xed],[0x27,0xe5,0xb0,0x20],[0x20,0xa5,0xe6,0x35],[0x87,0xb7,0xe7,0x9e]]
K = [[0xe6,0x04,0x51,0x24],[0xdc,0xfd,0x58,0xc3],[0x49,0xe6,0x59,0x79],[0x51,0xcd,0x99,0x2a]]
B = [[0x63,0x43,0x0a,0x53],[0xcf,0xe4,0x88,0x8b],[0xb2,0x75,0xb5,0x4b],[0x58,0x1c,0x99,0x2c]]
if AESRound(A,K)!=B: print("Fehler in AESRound")
#
P = [[0x32,0x88,0x31,0xe0],[0x43,0x5a,0x31,0x37],[0xf6,0x30,0x98,0x07],[0xa8,0x8d,0xa2,0x34]]
K = [[0x2b,0x28,0xab,0x09],[0x7e,0xae,0xf7,0xcf],[0x15,0xd2,0x15,0x4f],[0x16,0xa6,0x88,0x3c]]
C = [[0x39,0x02,0xdc,0x19],[0x25,0xdc,0x11,0x6a],[0x84,0x09,0x85,0x0b],[0x1d,0xfb,0x97,0x32]]
if AES(P,K)!=C: print("Fehler in AES")
return
if __name__ == '__main__':
#import doctest
#doctest.testmod()
AESTests()