1010
1111# Precomputed S-Box for byte substitution
1212S_BOX = (
13- 0x63 , 0x7C , 0x77 , 0x7B , 0xF2 , 0x6B , 0x6F , 0xC5 , 0x30 , 0x01 , 0x67 , 0x2B , 0xFE , 0xD7 , 0xAB , 0x76 ,
14- 0xCA , 0x82 , 0xC9 , 0x7D , 0xFA , 0x59 , 0x47 , 0xF0 , 0xAD , 0xD4 , 0xA2 , 0xAF , 0x9C , 0xA4 , 0x72 , 0xC0 ,
15- 0xB7 , 0xFD , 0x93 , 0x26 , 0x36 , 0x3F , 0xF7 , 0xCC , 0x34 , 0xA5 , 0xE5 , 0xF1 , 0x71 , 0xD8 , 0x31 , 0x15 ,
16- 0x04 , 0xC7 , 0x23 , 0xC3 , 0x18 , 0x96 , 0x05 , 0x9A , 0x07 , 0x12 , 0x80 , 0xE2 , 0xEB , 0x27 , 0xB2 , 0x75 ,
17- 0x09 , 0x83 , 0x2C , 0x1A , 0x1B , 0x6E , 0x5A , 0xA0 , 0x52 , 0x3B , 0xD6 , 0xB3 , 0x29 , 0xE3 , 0x2F , 0x84 ,
18- 0x53 , 0xD1 , 0x00 , 0xED , 0x20 , 0xFC , 0xB1 , 0x5B , 0x6A , 0xCB , 0xBE , 0x39 , 0x4A , 0x4C , 0x58 , 0xCF ,
19- 0xD0 , 0xEF , 0xAA , 0xFB , 0x43 , 0x4D , 0x33 , 0x85 , 0x45 , 0xF9 , 0x02 , 0x7F , 0x50 , 0x3C , 0x9F , 0xA8 ,
20- 0x51 , 0xA3 , 0x40 , 0x8F , 0x92 , 0x9D , 0x38 , 0xF5 , 0xBC , 0xB6 , 0xDA , 0x21 , 0x10 , 0xFF , 0xF3 , 0xD2 ,
21- 0xCD , 0x0C , 0x13 , 0xEC , 0x5F , 0x97 , 0x44 , 0x17 , 0xC4 , 0xA7 , 0x7E , 0x3D , 0x64 , 0x5D , 0x19 , 0x73 ,
22- 0x60 , 0x81 , 0x4F , 0xDC , 0x22 , 0x2A , 0x90 , 0x88 , 0x46 , 0xEE , 0xB8 , 0x14 , 0xDE , 0x5E , 0x0B , 0xDB ,
23- 0xE0 , 0x32 , 0x3A , 0x0A , 0x49 , 0x06 , 0x24 , 0x5C , 0xC2 , 0xD3 , 0xAC , 0x62 , 0x91 , 0x95 , 0xE4 , 0x79 ,
24- 0xE7 , 0xC8 , 0x37 , 0x6D , 0x8D , 0xD5 , 0x4E , 0xA9 , 0x6C , 0x56 , 0xF4 , 0xEA , 0x65 , 0x7A , 0xAE , 0x08 ,
25- 0xBA , 0x78 , 0x25 , 0x2E , 0x1C , 0xA6 , 0xB4 , 0xC6 , 0xE8 , 0xDD , 0x74 , 0x1F , 0x4B , 0xBD , 0x8B , 0x8A ,
26- 0x70 , 0x3E , 0xB5 , 0x66 , 0x48 , 0x03 , 0xF6 , 0x0E , 0x61 , 0x35 , 0x57 , 0xB9 , 0x86 , 0xC1 , 0x1D , 0x9E ,
27- 0xE1 , 0xF8 , 0x98 , 0x11 , 0x69 , 0xD9 , 0x8E , 0x94 , 0x9B , 0x1E , 0x87 , 0xE9 , 0xCE , 0x55 , 0x28 , 0xDF ,
28- 0x8C , 0xA1 , 0x89 , 0x0D , 0xBF , 0xE6 , 0x42 , 0x68 , 0x41 , 0x99 , 0x2D , 0x0F , 0xB0 , 0x54 , 0xBB , 0x16 ,
13+ 0x63 ,
14+ 0x7C ,
15+ 0x77 ,
16+ 0x7B ,
17+ 0xF2 ,
18+ 0x6B ,
19+ 0x6F ,
20+ 0xC5 ,
21+ 0x30 ,
22+ 0x01 ,
23+ 0x67 ,
24+ 0x2B ,
25+ 0xFE ,
26+ 0xD7 ,
27+ 0xAB ,
28+ 0x76 ,
29+ 0xCA ,
30+ 0x82 ,
31+ 0xC9 ,
32+ 0x7D ,
33+ 0xFA ,
34+ 0x59 ,
35+ 0x47 ,
36+ 0xF0 ,
37+ 0xAD ,
38+ 0xD4 ,
39+ 0xA2 ,
40+ 0xAF ,
41+ 0x9C ,
42+ 0xA4 ,
43+ 0x72 ,
44+ 0xC0 ,
45+ 0xB7 ,
46+ 0xFD ,
47+ 0x93 ,
48+ 0x26 ,
49+ 0x36 ,
50+ 0x3F ,
51+ 0xF7 ,
52+ 0xCC ,
53+ 0x34 ,
54+ 0xA5 ,
55+ 0xE5 ,
56+ 0xF1 ,
57+ 0x71 ,
58+ 0xD8 ,
59+ 0x31 ,
60+ 0x15 ,
61+ 0x04 ,
62+ 0xC7 ,
63+ 0x23 ,
64+ 0xC3 ,
65+ 0x18 ,
66+ 0x96 ,
67+ 0x05 ,
68+ 0x9A ,
69+ 0x07 ,
70+ 0x12 ,
71+ 0x80 ,
72+ 0xE2 ,
73+ 0xEB ,
74+ 0x27 ,
75+ 0xB2 ,
76+ 0x75 ,
77+ 0x09 ,
78+ 0x83 ,
79+ 0x2C ,
80+ 0x1A ,
81+ 0x1B ,
82+ 0x6E ,
83+ 0x5A ,
84+ 0xA0 ,
85+ 0x52 ,
86+ 0x3B ,
87+ 0xD6 ,
88+ 0xB3 ,
89+ 0x29 ,
90+ 0xE3 ,
91+ 0x2F ,
92+ 0x84 ,
93+ 0x53 ,
94+ 0xD1 ,
95+ 0x00 ,
96+ 0xED ,
97+ 0x20 ,
98+ 0xFC ,
99+ 0xB1 ,
100+ 0x5B ,
101+ 0x6A ,
102+ 0xCB ,
103+ 0xBE ,
104+ 0x39 ,
105+ 0x4A ,
106+ 0x4C ,
107+ 0x58 ,
108+ 0xCF ,
109+ 0xD0 ,
110+ 0xEF ,
111+ 0xAA ,
112+ 0xFB ,
113+ 0x43 ,
114+ 0x4D ,
115+ 0x33 ,
116+ 0x85 ,
117+ 0x45 ,
118+ 0xF9 ,
119+ 0x02 ,
120+ 0x7F ,
121+ 0x50 ,
122+ 0x3C ,
123+ 0x9F ,
124+ 0xA8 ,
125+ 0x51 ,
126+ 0xA3 ,
127+ 0x40 ,
128+ 0x8F ,
129+ 0x92 ,
130+ 0x9D ,
131+ 0x38 ,
132+ 0xF5 ,
133+ 0xBC ,
134+ 0xB6 ,
135+ 0xDA ,
136+ 0x21 ,
137+ 0x10 ,
138+ 0xFF ,
139+ 0xF3 ,
140+ 0xD2 ,
141+ 0xCD ,
142+ 0x0C ,
143+ 0x13 ,
144+ 0xEC ,
145+ 0x5F ,
146+ 0x97 ,
147+ 0x44 ,
148+ 0x17 ,
149+ 0xC4 ,
150+ 0xA7 ,
151+ 0x7E ,
152+ 0x3D ,
153+ 0x64 ,
154+ 0x5D ,
155+ 0x19 ,
156+ 0x73 ,
157+ 0x60 ,
158+ 0x81 ,
159+ 0x4F ,
160+ 0xDC ,
161+ 0x22 ,
162+ 0x2A ,
163+ 0x90 ,
164+ 0x88 ,
165+ 0x46 ,
166+ 0xEE ,
167+ 0xB8 ,
168+ 0x14 ,
169+ 0xDE ,
170+ 0x5E ,
171+ 0x0B ,
172+ 0xDB ,
173+ 0xE0 ,
174+ 0x32 ,
175+ 0x3A ,
176+ 0x0A ,
177+ 0x49 ,
178+ 0x06 ,
179+ 0x24 ,
180+ 0x5C ,
181+ 0xC2 ,
182+ 0xD3 ,
183+ 0xAC ,
184+ 0x62 ,
185+ 0x91 ,
186+ 0x95 ,
187+ 0xE4 ,
188+ 0x79 ,
189+ 0xE7 ,
190+ 0xC8 ,
191+ 0x37 ,
192+ 0x6D ,
193+ 0x8D ,
194+ 0xD5 ,
195+ 0x4E ,
196+ 0xA9 ,
197+ 0x6C ,
198+ 0x56 ,
199+ 0xF4 ,
200+ 0xEA ,
201+ 0x65 ,
202+ 0x7A ,
203+ 0xAE ,
204+ 0x08 ,
205+ 0xBA ,
206+ 0x78 ,
207+ 0x25 ,
208+ 0x2E ,
209+ 0x1C ,
210+ 0xA6 ,
211+ 0xB4 ,
212+ 0xC6 ,
213+ 0xE8 ,
214+ 0xDD ,
215+ 0x74 ,
216+ 0x1F ,
217+ 0x4B ,
218+ 0xBD ,
219+ 0x8B ,
220+ 0x8A ,
221+ 0x70 ,
222+ 0x3E ,
223+ 0xB5 ,
224+ 0x66 ,
225+ 0x48 ,
226+ 0x03 ,
227+ 0xF6 ,
228+ 0x0E ,
229+ 0x61 ,
230+ 0x35 ,
231+ 0x57 ,
232+ 0xB9 ,
233+ 0x86 ,
234+ 0xC1 ,
235+ 0x1D ,
236+ 0x9E ,
237+ 0xE1 ,
238+ 0xF8 ,
239+ 0x98 ,
240+ 0x11 ,
241+ 0x69 ,
242+ 0xD9 ,
243+ 0x8E ,
244+ 0x94 ,
245+ 0x9B ,
246+ 0x1E ,
247+ 0x87 ,
248+ 0xE9 ,
249+ 0xCE ,
250+ 0x55 ,
251+ 0x28 ,
252+ 0xDF ,
253+ 0x8C ,
254+ 0xA1 ,
255+ 0x89 ,
256+ 0x0D ,
257+ 0xBF ,
258+ 0xE6 ,
259+ 0x42 ,
260+ 0x68 ,
261+ 0x41 ,
262+ 0x99 ,
263+ 0x2D ,
264+ 0x0F ,
265+ 0xB0 ,
266+ 0x54 ,
267+ 0xBB ,
268+ 0x16 ,
29269)
30270
31271# Round constants used for key expansion
32- RCON = (
33- 0x00 , 0x01 , 0x02 , 0x04 , 0x08 , 0x10 , 0x20 , 0x40 , 0x80 , 0x1B , 0x36
34- )
272+ RCON = (0x00 , 0x01 , 0x02 , 0x04 , 0x08 , 0x10 , 0x20 , 0x40 , 0x80 , 0x1B , 0x36 )
273+
35274
36275def sub_bytes (state : list [int ]) -> None :
37276 """
@@ -40,6 +279,7 @@ def sub_bytes(state: list[int]) -> None:
40279 for i in range (16 ):
41280 state [i ] = S_BOX [state [i ]]
42281
282+
43283def shift_rows (state : list [int ]) -> None :
44284 """
45285 Shifts the rows of the 4x4 state matrix.
@@ -52,6 +292,7 @@ def shift_rows(state: list[int]) -> None:
52292 # Row 3: shifted left by 3
53293 state [3 ], state [7 ], state [11 ], state [15 ] = state [15 ], state [3 ], state [7 ], state [11 ]
54294
295+
55296def galois_multiply (a : int , b : int ) -> int :
56297 """
57298 Multiplies two numbers in the GF(2^8) Galois field.
@@ -67,6 +308,7 @@ def galois_multiply(a: int, b: int) -> int:
67308 b >>= 1
68309 return p % 256
69310
311+
70312def mix_columns (state : list [int ]) -> None :
71313 """
72314 Mixes the columns of the state matrix to provide diffusion.
@@ -86,13 +328,15 @@ def mix_columns(state: list[int]) -> None:
86328 galois_multiply (col [0 ], 3 ) ^ col [1 ] ^ col [2 ] ^ galois_multiply (col [3 ], 2 )
87329 )
88330
331+
89332def add_round_key (state : list [int ], round_key : list [int ]) -> None :
90333 """
91334 XORs the state matrix with the current round key.
92335 """
93336 for i in range (16 ):
94337 state [i ] ^= round_key [i ]
95338
339+
96340def key_expansion (key : bytes ) -> list [int ]:
97341 """
98342 Expands a 16-byte key into 11 round keys (176 bytes total).
@@ -107,23 +351,24 @@ def key_expansion(key: bytes) -> list[int]:
107351 word = [S_BOX [b ] for b in word ]
108352 # XOR RCON
109353 word [0 ] ^= RCON [i // 4 ]
110-
354+
111355 for j in range (4 ):
112356 key_schedule .append (key_schedule [(i - 4 ) * 4 + j ] ^ word [j ])
113-
357+
114358 return key_schedule
115359
360+
116361def aes_128_encrypt_block (plaintext : bytes , key : bytes ) -> bytes :
117362 """
118363 Encrypts a single 16-byte block of plaintext using AES-128.
119-
364+
120365 Args:
121366 plaintext: Exactly 16 bytes of data.
122367 key: Exactly 16 bytes of encryption key.
123-
368+
124369 Returns:
125370 16 bytes of encrypted ciphertext.
126-
371+
127372 Raises:
128373 ValueError: If plaintext or key are not exactly 16 bytes.
129374
@@ -137,7 +382,7 @@ def aes_128_encrypt_block(plaintext: bytes, key: bytes) -> bytes:
137382 """
138383 if len (plaintext ) != 16 or len (key ) != 16 :
139384 raise ValueError ("Plaintext and Key must be exactly 16 bytes long." )
140-
385+
141386 state = list (plaintext )
142387 expanded_key = key_expansion (key )
143388
@@ -158,7 +403,8 @@ def aes_128_encrypt_block(plaintext: bytes, key: bytes) -> bytes:
158403
159404 return bytes (state )
160405
406+
161407if __name__ == "__main__" :
162408 import doctest
163409
164- doctest .testmod ()
410+ doctest .testmod ()
0 commit comments