---
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')
```