Commit 68fab27f authored by Stefan Hackenberg's avatar Stefan Hackenberg
Browse files

Add exercise for lecture_6

parent 567e7eb4
%% Cell type:markdown id: tags:
# Lecture 5: Template attack on AES SBOX
%% Cell type:markdown id: tags:
Template attacks are a powerful type of side-channel attack. These attacks are a subset of profiling attacks, where an attacker creates a "profile" of a sensitive device and applies this profile to quickly find a victim's secret key.
There are four steps to a template attack:
1. Using a copy of the protected device, record a large number of power traces using many different inputs (plaintexts and keys). Ensure that enough traces are recorded to give us information about each subkey value.
2. Create a template of the device's operation. This template notes a few "points of interest" in the power traces and a multivariate distribution of the power traces at each point.
3. On the victim device, record a small number of power traces. Use multiple plaintexts. (We have no control over the secret key, which is fixed.)
4. Apply the template to the attack traces. For each subkey, track which value is most likely to be the correct subkey. Continue until the key has been recovered.
https://wiki.newae.com/Template_Attacks
%% Cell type:code id: tags:
``` python
import sys
sys.path.append('..')
```
%% Cell type:code id: tags:
``` python
import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models import CrosshairTool
from bokeh.io import output_notebook
output_notebook()
```
%% Cell type:code id: tags:
``` python
import numpy as np
SBOX = [
# 0 1 2 3 4 5 6 7 8 9 a b c d e f
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, # 0
0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, # 1
0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, # 2
0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, # 3
0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, # 4
0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, # 5
0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, # 6
0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, # 7
0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, # 8
0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, # 9
0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, # a
0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, # b
0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, # c
0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, # d
0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, # e
0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16 # f
]
def sbox(data):
return SBOX[data]
sbox_vec = np.vectorize(sbox)
```
%% Cell type:code id: tags:
``` python
import numpy as np
HW = [bin(n).count("1") for n in range(0, 256)]
def hw(n):
if isinstance(n, str):
return HW[ord(n)]
return HW[n]
hw_vec = np.vectorize(hw)
def cov(x, y):
return np.cov(x, y)[0][1]
```
%% Cell type:code id: tags:
``` python
import securec
from securec import util
scope, target = util.init()
```
%% Cell type:code id: tags:
``` python
securec.util.compile_and_flash('./6_sbox.c')
```
%% Cell type:markdown id: tags:
## Profiling Phase
%% Cell type:markdown id: tags:
### Record templates
Record traces with random keys and random inputs.
%% Cell type:code id: tags:
``` python
import random
import tqdm
import tqdm.notebook
scope.default_setup()
def capture_random_key_input(num_traces=1000, num_samples=500):
scope.adc.samples = num_samples
data = []
for _ in tqdm.notebook.tqdm(range(num_traces)):
scope.arm()
key = random.choices(range(0, 256), k=16)
input = random.choices(range(0, 256), k=16)
target.simpleserial_write(0x01, key + input)
data.append((key, input, np.array(util.capture())))
return data
```
%% Cell type:code id: tags:
``` python
data_template = capture_random_key_input(num_traces=20000)
```
%% Cell type:markdown id: tags:
### Find Points of Interest
%% Cell type:code id: tags:
``` python
# Group traces by different hamming weights
traces_per_hw = [[] for _ in range(9)]
for key, input, trace in data_template:
traces_per_hw[hw(sbox(key[0] ^ input[0]))].append(trace)
traces_per_hw = list(map(np.array, traces_per_hw))
means_per_hw = [np.average(trace, 0) for trace in traces_per_hw]
# Calculate sum of absolute differences
diffs = np.zeros(means_per_hw[0].shape[0])
for mean_i in means_per_hw:
for mean_j in means_per_hw:
diffs += np.abs(mean_i - mean_j)
# Take highest peaks as pois
pois = np.argsort(diffs)[-5:]
# Plot
p = figure(height=300, sizing_mode='stretch_width')
p.add_tools(CrosshairTool())
p.line(range(len(diffs)), diffs, color='blue', legend_label='Sum of diffs')
p.circle(pois, [diffs[poi] for poi in pois], size=10)
show(p)
```
%% Cell type:markdown id: tags:
### Calculate template
%% Cell type:code id: tags:
``` python
template_mean = np.zeros((9, len(pois)))
template_cov = np.zeros((9, len(pois), len(pois)))
for ham in range(template_mean.shape[0]):
for i in range(len(pois)):
template_mean[ham, i] = means_per_hw[ham][pois[i]]
for j in range(len(pois)):
template_cov[ham, i, j] = cov(
traces_per_hw[ham][:, pois[i]],
traces_per_hw[ham][:, pois[j]],
)
print('template_mean', template_mean.shape, '=\n', template_mean)
print('template_cov', template_cov.shape, '=\n', template_cov)
```
%% Cell type:markdown id: tags:
## Attacking phase
%% Cell type:markdown id: tags:
### Capture
%% Cell type:markdown id: tags:
Capture with random input but unknown fixed key.
%% Cell type:code id: tags:
``` python
import random
import tqdm
import tqdm.notebook
secret_key = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,]
scope.default_setup()
def capture_random_input(num_traces=10, num_samples=500):
scope.adc.samples = num_samples
data = []
for _ in tqdm.notebook.tqdm(range(num_traces)):
scope.arm()
input = random.choices(range(0, 256), k=16)
target.simpleserial_write(0x01, secret_key + input)
data.append((input, np.array(util.capture())))
return data
```
%% Cell type:code id: tags:
``` python
data_attack = capture_random_input(10)
```
%% Cell type:markdown id: tags:
### Apply template
%% Cell type:code id: tags:
``` python
from scipy.stats import multivariate_normal
# 2: Attack
# Running total of log P_k
P_k = np.zeros(256)
for j in range(len(data_attack)):
# Grab key points and put them in a small matrix
a = [data_attack[j][1][poi] for poi in pois]
# Test each key
for k in range(256):
# Find HW coming out of sbox
guess_hw = hw(sbox(data_attack[j][0][0] ^ k))
# Find p_{k,j}
rv = multivariate_normal(template_mean[guess_hw], template_cov[guess_hw])
p_kj = rv.logpdf(a)
# Add it to running total
P_k[k] += p_kj
# Print our top results so far
# Best match on the right
print(j, P_k.argsort()[-3:])
guess = P_k.argsort()[-1]
print(guess)
```
%% Cell type:markdown id: tags:
<div style="background: #f0ffe0; padding: 15px; border: 1px solid slategray;">
<div class="h2" style="font-variant: small-caps;">Exercise 1</div>
1. The above version of a template attack focuses on the _hamming weight_. A template attack can also target values directly. <br>
So, create and apply templates on the basis of `sbox(input ^ key)`.
</div>
%% Cell type:code id: tags:
``` python
#util.exit()
```
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment