--- tags: CS 2022 Fall, 程式安全 --- # [0x03] Crypto III slide: https://drive.google.com/drive/folders/1odb_qi-nW0tpKfEDXpmCCox6zxVCEGMD?usp=sharing lecture: https://drive.google.com/file/d/1cthYF5PcZYoGC0uRhlf8Ba-NbtSAvviX/view ### [HW] AES 首先來看看題目給的數據 ![](https://i.imgur.com/WklijJ8.png) 可以看出有 $10$ round (下方突起) 我今天要取的是第一次 `AddRoundKey` 以及 `SubBytes` 的範圍 所以我們只需要橘色的部分 #### 取第一次 `AddRoundKey` `SubBytes` 的原因 我們知道第一次 `AddRoundKey` 的 `key` 就是輸入 `AES` 的 `key` 而且第一次 `AddRoundKey` `SubBytes` 不會把不同的 `bytes` 混在一起 再加上 `SubBytes` 又是非線性的 #### Power Model 所取的中間值 $state$ 如下 $$ state = SubByte(AddRoundKey(PT, K)) $$ 將使用的為 `Hamming Weight Model` > ### Why is the Hamming Weight model suitable? > 1. In software case, the intermediate value may be moved between register and memory several times > 2. Bus may be precharged before moving data > > [name=講師簡報] 計算 $state[i]$ 的 `Hamming Weight` 來當成那點的功率消耗 共會有 $D$ 條 $traces$ 所以得到 `D x KEY_BYTE_SPACE` 的矩陣 `powerMatrix` ##### `AES/exp2.ipynb` ```python # return Power Matrix (D * KEY_BYTE_SPACE) def getPowerMatrix (key: bytearray, byte_index: int): global PT powerMatrix = [] # for i in range(D): for pt in PT: pt = bytearray(pt) powerVector = [] # for k in KEY_SPACE for k in range(K): key[byte_index] = k if not k in key_byte_space: key[byte_index] = 0 intermediateState = CipherFirstAddKeyAndSubBytes(pt, key) HW = getHammingWeight(intermediateState[byte_index]) powerVector.append(HW) powerMatrix.append(powerVector) return powerMatrix ``` 接著將 `powerMatrix (D x K)` 與 `PM (D x T)` 的 `column` 進行計算 `correlation` 此步驟為比較我們猜的 `key_byte` 所模擬出來的功率消耗曲線與實際情況的相關性 ##### `AES/exp2.ipynb` ```python # return correlation matrix of i th byte (K x T) def getCorrBetweenPowerMatrixAndTraces2 (byte_index: int) -> list[list[int]]: # PM (D x T) global PM PM_NP_T = np.array(PM).transpose() # Power Matrix (D x KEY_BYTE_SPACE) powerMatrix = getPowerMatrix(bytearray(b'0000000000000000'), byte_index) powerMatrix_NP_T = np.array(powerMatrix).transpose() # K * T corrMatrix = [ ] for k in range(K): corrVector = [] for t in range(T): corrVector.append(corr_calc(powerMatrix_NP_T[k], PM_NP_T[t])) corrMatrix.append(corrVector) assert(np.array(corrMatrix).shape == (K, T)) return np.array(corrMatrix) ``` 接著我們只要取相關性最大的 `key_byte` 就會是答案 ##### `AES/exp2.ipynb` ```python def getKeyByte2 (byte_index: int) -> int: corrMatrix = getCorrBetweenPowerMatrixAndTraces2(byte_index) # get max index of corrMatrix maxIndex = np.argmax(corrMatrix) I = maxIndex // T J = maxIndex % T return I ``` 對於每個 `key_byte` 都作一次就有完整的 `key` 了 **`AES/exp2.ipynb`** ```python def getKey2 () -> bytearray: key = bytearray(b'0000000000000000') for i in range(16): key[i] = getKeyByte2(i) return key # output: bytearray(b'18MbH9oEnbXHyHTR') ```