# Simple Crypto 0x13(2023 HW - Power Analysis) ## Background [ [edu-ctf 2023] week04 - crypto3 [1:30:36]](https://www.youtube.com/live/Q-gaGLJpJHc?si=DZgJm62AnoPHWiZF&t=5433) ## Source code json file recorded by TA ## Recon 這一題全部都是刻出來的,也包含算correlation coefficient,後面才知道numpy有這東西,但反正根據老師上課的作法一步一步跟著做是絕對沒有問題的,包含以下步驟: 1. Preprocessing 也就是把pt, ct, pm都按照簡報上的方式排列(各個trace的第一個byte都蒐集在一起,第二個byte都蒐集再一起...) 2. 計算和sbox key XOR的結果 3. 查表sbox 4. 計算hamming weight model 5. 計算和trace的correlation coefficient 6. 看哪一個結果的數值最大,並把index結果記錄下來算它的ascii 7. repeat以上操作後共可得16 bytes的flag * 加速的方法: 可以把整個trace的圖片plot出來看看,會發現題目給的json file是把整段加密的過程記錄下來,所以我們可以只取前一兩百個point就可以完成key的還原 ## Exploit ```python= import json from tqdm import trange import numpy as np import copy from string import ascii_letters, digits from numpy import corrcoef jsonFile = open('./Crypto/HW3/traces.json', 'r') j = json.load(jsonFile) 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] ] def data_preprocess(json_data): pt_col = [] ct_col = [] trace_col = [] for bytes in range(16): tmp_pt_col = [] tmp_ct_col = [] for trace_idx in range(len(json_data)): tmp_pt_col.append(json_data[trace_idx]['pt'][bytes]) tmp_ct_col.append(json_data[trace_idx]['ct'][bytes]) pt_col.append(tmp_pt_col) ct_col.append(tmp_ct_col) for point in range(len(json_data[0]['pm'])): tmp_trace_col = [] for trace_idx in range(len(json_data)): tmp_trace_col.append(json_data[trace_idx]['pm'][point]) trace_col.append(tmp_trace_col) return pt_col, ct_col, trace_col def sbox_preprocess(pt_col): sbox_result_tmp = [] for sbox_key in range(256): # 總共有256個sbox key tmp = [] for trace in range(len(pt_col)): # 有50個trace tmp.append(pt_col[trace] ^ sbox_key) sbox_result_tmp.append(tmp) return sbox_result_tmp def choose_sbox(sbox_result_tmp): sbox_result = copy.deepcopy(sbox_result_tmp) for sbox_key in range(256): for trace in range(50): hex_value = '{0:0>2x}'.format(sbox_result_tmp[sbox_key][trace]) x, y = hex_value[0], hex_value[1] sbox_result[sbox_key][trace] = s_box[int(x, 16)][int(y, 16)] return sbox_result def cal_hamming_weight(sbox_result_col): hw_model = copy.deepcopy(sbox_result_col) for i in range(len(sbox_result_col)): # 256 for j in range(len(sbox_result_col[i])): # 50 hw_model[i][j] = bin(sbox_result_col[i][j]).count('1') return hw_model def cal_correlation(hw_model_col_result, trace_col): correlation_result = [] for i in (ascii_letters + digits).encode():#trange(len(hw_model_col_result)): <- 加速的部分 for j in range(biggest_length): correlation_result.append(corrcoef(hw_model_col_result[i], trace_col[j])[0, -1]) return correlation_result def run_pearson_correlation(x, y): mean_x = np.mean(x) mean_y = np.mean(y) covariance = np.sum((x - mean_x) * (y - mean_y)) std_dev_x = np.sqrt(np.sum((x - mean_x)**2)) std_dev_y = np.sqrt(np.sum((y - mean_y)**2)) correlation = covariance / (std_dev_x * std_dev_y) return correlation def display_pt(offset:int, data_offset = (0, len(j[0]["pm"]))): plt.plot(range(data_offset[0], data_offset[1]), j[offset]["pm"][data_offset[0]:data_offset[1]]) plt.savefig(fname="pt_" + str(offset) + ".jpg") plt.clf() # display_pt(0, (0, 95)) # display_pt(0) pt_col, ct_col, trace_col = data_preprocess(j) flag = '' biggest_length = 95# len(trace_col) for idx in trange(16): sbox_preprocess_result = sbox_preprocess(pt_col[idx]) choose_sbox_result = choose_sbox(sbox_preprocess_result) hw_model_col_result = cal_hamming_weight(choose_sbox_result) correlation_result = cal_correlation(hw_model_col_result, trace_col) key_idx = correlation_result.index(max(correlation_result)) flag += (ascii_letters + digits)[key_idx // biggest_length] # from Crypto.Util.number import long_to_bytes # flag += long_to_bytes(key_idx // biggest_length).decode("cp437") print('The key of AES is: FLAG{' + flag + '}') ``` 有嘗試過只選擇常見可使用的字元也就是`abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`,以及trace只選擇前95個data,也可以正常解析出AES key並且算的更快(大約快77倍左右) Flag: `FLAG{W0ckAwocKaWoCka1}` ## Reference [NTU Computer Security HW1 - AES](https://hackmd.io/@asef18766/NTU-CS-2022-hw1#AES)