今天來把 How AES Works系列題目結束掉!
只解一題
網址 : https://cryptohack.org/courses/symmetric/aes6/
這題要我們完成AES的解密,他的python檔案裡面有部分程式碼
參考題目右邊這張圖
我們打開題目給python檔,會發現拿到的是Ciphertext,所以我們要做的是從下面跑到上面,得到Plaintext
而過程大概是
一開始先
AddRoundKey
之後正式進入Round 1
InvShiftRows -> InvSubBytes -> AddRoundKey -> InvMixColums
到最後一回合的時候變成
InvShiftRows -> InvSubBytes -> AddRoundKey
少了InvMixColums
便可得到Plaintext
題外話 inv為"逆"的意思完整為 : inverse
複習
剛剛看了過程,484覺得那些名詞很熟悉,沒錯拉,都是之前題目寫過或看過的,所以只要稍微借來用就ok拉
matrix : 矩陣
def bytes2matrix(text):
""" Converts a 16-byte array into a 4x4 matrix. """
return [list(text[i:i+4]) for i in range(0, len(text), 4)]
def matrix2bytes(matrix):
""" Converts a 4x4 matrix into a 16-byte array. """
byte_output_arr = [bytes([i]) for row in matrix for i in row]
byte_output = b"".join(byte_output_arr)
return byte_output
def add_round_key(s, k):
for i in range(4):
for j in range(4):
s[i][j] = s[i][j] ^ k[i][j]
#s = state, k = round_keys
def inv_shift_rows(s):
s[1][1], s[2][1], s[3][1], s[0][1] = s[0][1], s[1][1], s[2][1], s[3][1]
s[2][2], s[3][2], s[0][2], s[1][2] = s[0][2], s[1][2], s[2][2], s[3][2]
s[3][3], s[0][3], s[1][3], s[2][3] = s[0][3], s[1][3], s[2][3], s[3][3]
#s = state
#省略inv_s_box內容,太長了w
def inv_subbytes(s, inv_s_box):
for i in range(4):
for j in range(4):
s[i][j] = inv_s_box[s[i][j]]
#s = state
xtime = lambda a: (((a << 1) ^ 0x1B) & 0xFF) if (a & 0x80) else (a << 1)
def mix_single_column(a):
t = a[0] ^ a[1] ^ a[2] ^ a[3]
u = a[0]
a[0] ^= t ^ xtime(a[0] ^ a[1])
a[1] ^= t ^ xtime(a[1] ^ a[2])
a[2] ^= t ^ xtime(a[2] ^ a[3])
a[3] ^= t ^ xtime(a[3] ^ u)
def mix_columns(s):
for i in range(4):
mix_single_column(s[i])
def inv_mix_columns(s):
for i in range(4):
u = xtime(xtime(s[i][0] ^ s[i][2]))
v = xtime(xtime(s[i][1] ^ s[i][3]))
s[i][0] ^= u
s[i][1] ^= v
s[i][2] ^= u
s[i][3] ^= v
mix_columns(s)
#s = state
有了以上副函式就可以完成我們的AES解密拉~
其實還有一個是生成RoundKey的,但是這個題目有給,所以我就沒放了,只放了題目沒給的
還有會不會有人想說,InvSubBytes裡的inv_s_box為甚麼可以直接拿之前的來用?我是有想過拉XD後來發現s箱其實都是固定的!所以inv_s_box其實也是固定的,就都長一樣,所以是通用的
因為我們是要解密,所以要逆著來,代表roundkey的使用也要從最後一個開始
round_keys[-1]為最後一個元素
round_keys[0]為第一個元素
N_ROUNDS = 10
key = b'\xc3,\\xa6\xb5\x80^\x0c\xdb\x8d\xa5z*\xb6\xfe\'
ciphertext = b'\xd1O\x14j\xa4+O\xb6\xa1\xc4\x08B)\x8f\x12\xdd'
def decrypt(key, ciphertext):
round_keys = expand_key(key) #生成roundKey
# 把ciphertext轉為矩陣
state = bytes2matrix(ciphertext)
# 最一開始先做一次AddRoundKey
add_round_key(state, round_keys[-1])
#進入round(持續9回合)
for i in range(N_ROUNDS - 1, 0, -1):
inv_shift_rows(state)
inv_subbytes(state, inv_s_box)
add_round_key(state, round_keys[i])
inv_mix_columns(state)
#結束round,進行最後一回合(第10回合)(忽略InvMixColums)
inv_shift_rows(state)
inv_subbytes(state, inv_s_box)
add_round_key(state, round_keys[0])
# 把state 矩陣轉為bytes
plaintext = matrix2bytes(state)
return plaintext.decode()
print(decrypt(key, ciphertext))
完整code有點太長惹,我把它放在github,有興趣的可以去看!
flag : crypto{MYAES128}
今天為AES的實作!應用昨天學到的過程
也結束了How AES Works系列的題目
明天進入Symmetric Starter的部分