From c497a57896f522296e68ce543212c3d0cb0a2637 Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 19 Jun 2026 16:47:07 +0000 Subject: [PATCH 1/6] Implemented AES-128 cipher algorithm --- ciphers/aes_128.py | 164 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 ciphers/aes_128.py diff --git a/ciphers/aes_128.py b/ciphers/aes_128.py new file mode 100644 index 000000000000..b9040da35268 --- /dev/null +++ b/ciphers/aes_128.py @@ -0,0 +1,164 @@ +""" +Advanced Encryption Standard (AES) - 128 bit + +AES is a symmetric block cipher chosen by the U.S. government to protect classified information. +AES is implemented in software and hardware throughout the world to encrypt sensitive data. +This implementation provides the core AES-128 block encryption algorithm (operating on 16-byte blocks). + +Reference: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard +""" + +# Precomputed S-Box for byte substitution +S_BOX = ( + 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, +) + +# Round constants used for key expansion +RCON = ( + 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 +) + +def sub_bytes(state: list[int]) -> None: + """ + Applies the AES S-Box substitution to each byte in the state. + """ + for i in range(16): + state[i] = S_BOX[state[i]] + +def shift_rows(state: list[int]) -> None: + """ + Shifts the rows of the 4x4 state matrix. + """ + # Row 0: unchanged + # Row 1: shifted left by 1 + state[1], state[5], state[9], state[13] = state[5], state[9], state[13], state[1] + # Row 2: shifted left by 2 + state[2], state[6], state[10], state[14] = state[10], state[14], state[2], state[6] + # Row 3: shifted left by 3 + state[3], state[7], state[11], state[15] = state[15], state[3], state[7], state[11] + +def galois_multiply(a: int, b: int) -> int: + """ + Multiplies two numbers in the GF(2^8) Galois field. + """ + p = 0 + for _ in range(8): + if b & 1: + p ^= a + hi_bit_set = a & 0x80 + a <<= 1 + if hi_bit_set: + a ^= 0x11B # x^8 + x^4 + x^3 + x + 1 + b >>= 1 + return p % 256 + +def mix_columns(state: list[int]) -> None: + """ + Mixes the columns of the state matrix to provide diffusion. + """ + for i in range(4): + col = state[i * 4 : (i + 1) * 4] + state[i * 4] = ( + galois_multiply(col[0], 2) ^ galois_multiply(col[1], 3) ^ col[2] ^ col[3] + ) + state[i * 4 + 1] = ( + col[0] ^ galois_multiply(col[1], 2) ^ galois_multiply(col[2], 3) ^ col[3] + ) + state[i * 4 + 2] = ( + col[0] ^ col[1] ^ galois_multiply(col[2], 2) ^ galois_multiply(col[3], 3) + ) + state[i * 4 + 3] = ( + galois_multiply(col[0], 3) ^ col[1] ^ col[2] ^ galois_multiply(col[3], 2) + ) + +def add_round_key(state: list[int], round_key: list[int]) -> None: + """ + XORs the state matrix with the current round key. + """ + for i in range(16): + state[i] ^= round_key[i] + +def key_expansion(key: bytes) -> list[int]: + """ + Expands a 16-byte key into 11 round keys (176 bytes total). + """ + key_schedule = list(key) + for i in range(4, 44): + word = key_schedule[(i - 1) * 4 : i * 4] + if i % 4 == 0: + # Shift row + word = word[1:] + word[:1] + # Sub bytes + word = [S_BOX[b] for b in word] + # XOR RCON + word[0] ^= RCON[i // 4] + + for j in range(4): + key_schedule.append(key_schedule[(i - 4) * 4 + j] ^ word[j]) + + return key_schedule + +def aes_128_encrypt_block(plaintext: bytes, key: bytes) -> bytes: + """ + Encrypts a single 16-byte block of plaintext using AES-128. + + Args: + plaintext: Exactly 16 bytes of data. + key: Exactly 16 bytes of encryption key. + + Returns: + 16 bytes of encrypted ciphertext. + + Raises: + ValueError: If plaintext or key are not exactly 16 bytes. + + Examples: + + >>> key = bytes.fromhex('2b7e151628aed2a6abf7158809cf4f3c') + >>> plaintext = bytes.fromhex('3243f6a8885a308d313198a2e0370734') + >>> ciphertext = aes_128_encrypt_block(plaintext, key) + >>> ciphertext.hex() + '3925841d02dc09fbdc118597196a0b32' + """ + if len(plaintext) != 16 or len(key) != 16: + raise ValueError("Plaintext and Key must be exactly 16 bytes long.") + + state = list(plaintext) + expanded_key = key_expansion(key) + + # Initial Round + add_round_key(state, expanded_key[0:16]) + + # 9 Main Rounds + for round_num in range(1, 10): + sub_bytes(state) + shift_rows(state) + mix_columns(state) + add_round_key(state, expanded_key[round_num * 16 : (round_num + 1) * 16]) + + # Final Round (No MixColumns) + sub_bytes(state) + shift_rows(state) + add_round_key(state, expanded_key[160:176]) + + return bytes(state) + +if __name__ == "__main__": + import doctest + + doctest.testmod() \ No newline at end of file From 2222207cad707d5d5823ce746c39b220fa587c90 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jun 2026 17:04:44 +0000 Subject: [PATCH 2/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ciphers/aes_128.py | 298 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 272 insertions(+), 26 deletions(-) diff --git a/ciphers/aes_128.py b/ciphers/aes_128.py index b9040da35268..ebf777611d0e 100644 --- a/ciphers/aes_128.py +++ b/ciphers/aes_128.py @@ -10,28 +10,267 @@ # Precomputed S-Box for byte substitution S_BOX = ( - 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, + 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, ) # Round constants used for key expansion -RCON = ( - 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 -) +RCON = (0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36) + def sub_bytes(state: list[int]) -> None: """ @@ -40,6 +279,7 @@ def sub_bytes(state: list[int]) -> None: for i in range(16): state[i] = S_BOX[state[i]] + def shift_rows(state: list[int]) -> None: """ Shifts the rows of the 4x4 state matrix. @@ -52,6 +292,7 @@ def shift_rows(state: list[int]) -> None: # Row 3: shifted left by 3 state[3], state[7], state[11], state[15] = state[15], state[3], state[7], state[11] + def galois_multiply(a: int, b: int) -> int: """ Multiplies two numbers in the GF(2^8) Galois field. @@ -67,6 +308,7 @@ def galois_multiply(a: int, b: int) -> int: b >>= 1 return p % 256 + def mix_columns(state: list[int]) -> None: """ Mixes the columns of the state matrix to provide diffusion. @@ -86,6 +328,7 @@ def mix_columns(state: list[int]) -> None: galois_multiply(col[0], 3) ^ col[1] ^ col[2] ^ galois_multiply(col[3], 2) ) + def add_round_key(state: list[int], round_key: list[int]) -> None: """ XORs the state matrix with the current round key. @@ -93,6 +336,7 @@ def add_round_key(state: list[int], round_key: list[int]) -> None: for i in range(16): state[i] ^= round_key[i] + def key_expansion(key: bytes) -> list[int]: """ Expands a 16-byte key into 11 round keys (176 bytes total). @@ -107,23 +351,24 @@ def key_expansion(key: bytes) -> list[int]: word = [S_BOX[b] for b in word] # XOR RCON word[0] ^= RCON[i // 4] - + for j in range(4): key_schedule.append(key_schedule[(i - 4) * 4 + j] ^ word[j]) - + return key_schedule + def aes_128_encrypt_block(plaintext: bytes, key: bytes) -> bytes: """ Encrypts a single 16-byte block of plaintext using AES-128. - + Args: plaintext: Exactly 16 bytes of data. key: Exactly 16 bytes of encryption key. - + Returns: 16 bytes of encrypted ciphertext. - + Raises: ValueError: If plaintext or key are not exactly 16 bytes. @@ -137,7 +382,7 @@ def aes_128_encrypt_block(plaintext: bytes, key: bytes) -> bytes: """ if len(plaintext) != 16 or len(key) != 16: raise ValueError("Plaintext and Key must be exactly 16 bytes long.") - + state = list(plaintext) expanded_key = key_expansion(key) @@ -158,7 +403,8 @@ def aes_128_encrypt_block(plaintext: bytes, key: bytes) -> bytes: return bytes(state) + if __name__ == "__main__": import doctest - doctest.testmod() \ No newline at end of file + doctest.testmod() From 70238943fd2963755cfa29cf4bf4f3f4781522dd Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 19 Jun 2026 17:20:36 +0000 Subject: [PATCH 3/6] Fix line length formatting issues for ruff --- ciphers/aes_128.py | 54 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/ciphers/aes_128.py b/ciphers/aes_128.py index ebf777611d0e..d81212883136 100644 --- a/ciphers/aes_128.py +++ b/ciphers/aes_128.py @@ -1,9 +1,11 @@ """ Advanced Encryption Standard (AES) - 128 bit -AES is a symmetric block cipher chosen by the U.S. government to protect classified information. -AES is implemented in software and hardware throughout the world to encrypt sensitive data. -This implementation provides the core AES-128 block encryption algorithm (operating on 16-byte blocks). +AES is a symmetric block cipher chosen by the U.S. government to +protect classified information. AES is implemented in software +and hardware throughout the world to encrypt sensitive data. +This implementation provides the core AES-128 block encryption +algorithm (operating on 16-byte blocks). Reference: https://en.wikipedia.org/wiki/Advanced_Encryption_Standard """ @@ -275,6 +277,11 @@ def sub_bytes(state: list[int]) -> None: """ Applies the AES S-Box substitution to each byte in the state. + + >>> state = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + >>> sub_bytes(state) + >>> state[:4] + [99, 124, 119, 123] """ for i in range(16): state[i] = S_BOX[state[i]] @@ -283,6 +290,11 @@ def sub_bytes(state: list[int]) -> None: def shift_rows(state: list[int]) -> None: """ Shifts the rows of the 4x4 state matrix. + + >>> state = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + >>> shift_rows(state) + >>> state + [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11] """ # Row 0: unchanged # Row 1: shifted left by 1 @@ -293,25 +305,39 @@ def shift_rows(state: list[int]) -> None: state[3], state[7], state[11], state[15] = state[15], state[3], state[7], state[11] +<<<<<<< HEAD def galois_multiply(a: int, b: int) -> int: +======= +def galois_multiply(multiplicand: int, multiplier: int) -> int: +>>>>>>> b42bd6a1 (Fix line length formatting issues for ruff) """ Multiplies two numbers in the GF(2^8) Galois field. + + >>> galois_multiply(2, 3) + 6 + >>> galois_multiply(87, 19) + 254 """ p = 0 for _ in range(8): - if b & 1: - p ^= a - hi_bit_set = a & 0x80 - a <<= 1 + if multiplier & 1: + p ^= multiplicand + hi_bit_set = multiplicand & 0x80 + multiplicand <<= 1 if hi_bit_set: - a ^= 0x11B # x^8 + x^4 + x^3 + x + 1 - b >>= 1 + multiplicand ^= 0x11B # x^8 + x^4 + x^3 + x + 1 + multiplier >>= 1 return p % 256 def mix_columns(state: list[int]) -> None: """ Mixes the columns of the state matrix to provide diffusion. + + >>> state = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + >>> mix_columns(state) + >>> state + [2, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] """ for i in range(4): col = state[i * 4 : (i + 1) * 4] @@ -332,6 +358,12 @@ def mix_columns(state: list[int]) -> None: def add_round_key(state: list[int], round_key: list[int]) -> None: """ XORs the state matrix with the current round key. + + >>> state = [0] * 16 + >>> round_key = [1] * 16 + >>> add_round_key(state, round_key) + >>> state + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ for i in range(16): state[i] ^= round_key[i] @@ -340,6 +372,10 @@ def add_round_key(state: list[int], round_key: list[int]) -> None: def key_expansion(key: bytes) -> list[int]: """ Expands a 16-byte key into 11 round keys (176 bytes total). + + >>> key = bytes([0] * 16) + >>> len(key_expansion(key)) + 176 """ key_schedule = list(key) for i in range(4, 44): From e79741cb4a40b595bc7d9b556aaab3f410da9120 Mon Sep 17 00:00:00 2001 From: = <=> Date: Fri, 19 Jun 2026 17:14:38 +0000 Subject: [PATCH 4/6] Fix line length formatting issues for ruff --- ciphers/aes_128.py | 288 +++------------------------------------------ 1 file changed, 19 insertions(+), 269 deletions(-) diff --git a/ciphers/aes_128.py b/ciphers/aes_128.py index d81212883136..4cc7e3538054 100644 --- a/ciphers/aes_128.py +++ b/ciphers/aes_128.py @@ -12,267 +12,28 @@ # Precomputed S-Box for byte substitution S_BOX = ( - 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, + 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, ) # Round constants used for key expansion -RCON = (0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36) - +RCON = ( + 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 +) def sub_bytes(state: list[int]) -> None: """ @@ -286,7 +47,6 @@ def sub_bytes(state: list[int]) -> None: for i in range(16): state[i] = S_BOX[state[i]] - def shift_rows(state: list[int]) -> None: """ Shifts the rows of the 4x4 state matrix. @@ -304,12 +64,7 @@ def shift_rows(state: list[int]) -> None: # Row 3: shifted left by 3 state[3], state[7], state[11], state[15] = state[15], state[3], state[7], state[11] - -<<<<<<< HEAD -def galois_multiply(a: int, b: int) -> int: -======= def galois_multiply(multiplicand: int, multiplier: int) -> int: ->>>>>>> b42bd6a1 (Fix line length formatting issues for ruff) """ Multiplies two numbers in the GF(2^8) Galois field. @@ -329,7 +84,6 @@ def galois_multiply(multiplicand: int, multiplier: int) -> int: multiplier >>= 1 return p % 256 - def mix_columns(state: list[int]) -> None: """ Mixes the columns of the state matrix to provide diffusion. @@ -354,7 +108,6 @@ def mix_columns(state: list[int]) -> None: galois_multiply(col[0], 3) ^ col[1] ^ col[2] ^ galois_multiply(col[3], 2) ) - def add_round_key(state: list[int], round_key: list[int]) -> None: """ XORs the state matrix with the current round key. @@ -368,7 +121,6 @@ def add_round_key(state: list[int], round_key: list[int]) -> None: for i in range(16): state[i] ^= round_key[i] - def key_expansion(key: bytes) -> list[int]: """ Expands a 16-byte key into 11 round keys (176 bytes total). @@ -393,7 +145,6 @@ def key_expansion(key: bytes) -> list[int]: return key_schedule - def aes_128_encrypt_block(plaintext: bytes, key: bytes) -> bytes: """ Encrypts a single 16-byte block of plaintext using AES-128. @@ -439,7 +190,6 @@ def aes_128_encrypt_block(plaintext: bytes, key: bytes) -> bytes: return bytes(state) - if __name__ == "__main__": import doctest From b52fe0646d145d4a20f697787a4761e2c610ffba Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 19 Jun 2026 17:28:20 +0000 Subject: [PATCH 5/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- ciphers/aes_128.py | 284 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 265 insertions(+), 19 deletions(-) diff --git a/ciphers/aes_128.py b/ciphers/aes_128.py index 4cc7e3538054..dd7cbacbd7a8 100644 --- a/ciphers/aes_128.py +++ b/ciphers/aes_128.py @@ -12,28 +12,267 @@ # Precomputed S-Box for byte substitution S_BOX = ( - 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, + 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, ) # Round constants used for key expansion -RCON = ( - 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 -) +RCON = (0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36) + def sub_bytes(state: list[int]) -> None: """ @@ -47,6 +286,7 @@ def sub_bytes(state: list[int]) -> None: for i in range(16): state[i] = S_BOX[state[i]] + def shift_rows(state: list[int]) -> None: """ Shifts the rows of the 4x4 state matrix. @@ -64,6 +304,7 @@ def shift_rows(state: list[int]) -> None: # Row 3: shifted left by 3 state[3], state[7], state[11], state[15] = state[15], state[3], state[7], state[11] + def galois_multiply(multiplicand: int, multiplier: int) -> int: """ Multiplies two numbers in the GF(2^8) Galois field. @@ -84,6 +325,7 @@ def galois_multiply(multiplicand: int, multiplier: int) -> int: multiplier >>= 1 return p % 256 + def mix_columns(state: list[int]) -> None: """ Mixes the columns of the state matrix to provide diffusion. @@ -108,6 +350,7 @@ def mix_columns(state: list[int]) -> None: galois_multiply(col[0], 3) ^ col[1] ^ col[2] ^ galois_multiply(col[3], 2) ) + def add_round_key(state: list[int], round_key: list[int]) -> None: """ XORs the state matrix with the current round key. @@ -121,6 +364,7 @@ def add_round_key(state: list[int], round_key: list[int]) -> None: for i in range(16): state[i] ^= round_key[i] + def key_expansion(key: bytes) -> list[int]: """ Expands a 16-byte key into 11 round keys (176 bytes total). @@ -145,6 +389,7 @@ def key_expansion(key: bytes) -> list[int]: return key_schedule + def aes_128_encrypt_block(plaintext: bytes, key: bytes) -> bytes: """ Encrypts a single 16-byte block of plaintext using AES-128. @@ -190,6 +435,7 @@ def aes_128_encrypt_block(plaintext: bytes, key: bytes) -> bytes: return bytes(state) + if __name__ == "__main__": import doctest From eae7939f99907f8d950a0738eadd5a4dd70190e2 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 20 Jun 2026 09:33:43 +0000 Subject: [PATCH 6/6] style: standardize docstrings to match aes_128_encrypt_block format --- ciphers/aes_128.py | 81 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/ciphers/aes_128.py b/ciphers/aes_128.py index dd7cbacbd7a8..68c63231d326 100644 --- a/ciphers/aes_128.py +++ b/ciphers/aes_128.py @@ -278,11 +278,16 @@ def sub_bytes(state: list[int]) -> None: """ Applies the AES S-Box substitution to each byte in the state. - >>> state = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] - >>> sub_bytes(state) - >>> state[:4] - [99, 124, 119, 123] + Args: + state: A list of 16 integers representing the state matrix. + + Examples: + >>> state = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + >>> sub_bytes(state) + >>> state[:4] + [99, 124, 119, 123] """ + for i in range(16): state[i] = S_BOX[state[i]] @@ -291,10 +296,14 @@ def shift_rows(state: list[int]) -> None: """ Shifts the rows of the 4x4 state matrix. - >>> state = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] - >>> shift_rows(state) - >>> state - [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11] + Args: + state: A list of 16 integers representing the state matrix. + + Examples: + >>> state = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + >>> shift_rows(state) + >>> state + [0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11] """ # Row 0: unchanged # Row 1: shifted left by 1 @@ -309,10 +318,18 @@ def galois_multiply(multiplicand: int, multiplier: int) -> int: """ Multiplies two numbers in the GF(2^8) Galois field. - >>> galois_multiply(2, 3) - 6 - >>> galois_multiply(87, 19) - 254 + Args: + multiplicand: The first integer to multiply. + multiplier: The second integer to multiply. + + Returns: + The product of the two numbers in the Galois field. + + Examples: + >>> galois_multiply(2, 3) + 6 + >>> galois_multiply(87, 19) + 254 """ p = 0 for _ in range(8): @@ -330,10 +347,14 @@ def mix_columns(state: list[int]) -> None: """ Mixes the columns of the state matrix to provide diffusion. - >>> state = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] - >>> mix_columns(state) - >>> state - [2, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + Args: + state: A list of 16 integers representing the state matrix. + + Examples: + >>> state = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + >>> mix_columns(state) + >>> state + [2, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] """ for i in range(4): col = state[i * 4 : (i + 1) * 4] @@ -355,11 +376,16 @@ def add_round_key(state: list[int], round_key: list[int]) -> None: """ XORs the state matrix with the current round key. - >>> state = [0] * 16 - >>> round_key = [1] * 16 - >>> add_round_key(state, round_key) - >>> state - [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + Args: + state: A list of 16 integers representing the state matrix. + round_key: A list of 16 integers representing the round key. + + Examples: + >>> state = [0] * 16 + >>> round_key = [1] * 16 + >>> add_round_key(state, round_key) + >>> state + [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ for i in range(16): state[i] ^= round_key[i] @@ -369,9 +395,16 @@ def key_expansion(key: bytes) -> list[int]: """ Expands a 16-byte key into 11 round keys (176 bytes total). - >>> key = bytes([0] * 16) - >>> len(key_expansion(key)) - 176 + Args: + key: Exactly 16 bytes of encryption key. + + Returns: + A list of 176 integers representing the expanded key schedule. + + Examples: + >>> key = bytes([0] * 16) + >>> len(key_expansion(key)) + 176 """ key_schedule = list(key) for i in range(4, 44):