-
Notifications
You must be signed in to change notification settings - Fork 56
/
Copy pathprofiled-attack.py
145 lines (107 loc) · 4.65 KB
/
profiled-attack.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
"""
This script demonstrates how to use sklearn classifiers and keras model within lascar to perform profiled SCA.
Profiled SCA means that the attacker has access to an sample of the Device Under Test with known guess.
He can hence learn how the DUT behave, and build a classifier which will after be applied on a device with unknown guess
In this example, QuadraticDiscriminantAnalysis is performed on simulated AES traces.
Two steps:
1 - Use ProfileEngine to learn on traces with known guess
2 - Use of MatchEngine to apply the classifier on traces with unknown guess.
This can be used with all classifier provided by sklearn
(see http://scikit-learn.org/stable/auto_examples/classification/plot_classifier_comparison.html for a list of classifiers)
And with all keras Neural Network inherating from keras.Model
The ProfileEngine is actually a PartitionerEngine (such as SnrEngine, NicvEngine, TTestEngine...)
Specifically it needs:
- a sklearn Classifier instantiated (such as QuadraticDiscriminantAnalysis) or a keras neural network compiled
- a partition function, which will separate leakages into classes
- a "number_of_partitions" to indicate the number of possible classes for the partition_function
The MatchEngine is actually a GuessEngine (such as CpaHypothesisEngine)
Specifically it needs:
- a classifier which has been already trained (with ProfileEngine)
- a selection function (under guess hypothesis) on the sensitive value (here the output of the sbox at first round)
- a "guess_range" which will define what are the guess possible values
"""
import matplotlib.pyplot as plt
import numpy as np
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis
from lascar import *
from lascar.tools.aes import *
byte = 3 # key byte to be attacked. In BasicAesSimulationContainer, k_3 = 3
"""
# Part 1: Profiling Phase: Building the classifier from simulated traces with kown keys inside partition function
"""
container_profile = BasicAesSimulationContainer(5000, 0.5) # 5000 traces for profiling
container_profile.leakage_section = [
byte
] # POI selection: trivial here since on BasicAesSimulationContainer, the 3rd byte leaks on the third sample
solution = container_profile[0].value["key"][byte]
# partition_function must take 1 argument: the value returned by the container at each trace
def partition_function(value):
return sbox[
value["plaintext"][3] ^ value["key"][3]
] # here we partition on the output of the 3rd sbox
number_of_partitions = (
256 # number of possible classes (~values) for the partition_function
)
classifier_qda = QuadraticDiscriminantAnalysis()
from lascar.tools.keras_neural_networks import mlp_best
classifier_keras = mlp_best(
container_profile._leakage_abstract.shape,
number_of_classes=number_of_partitions,
nodes=[100, 50],
dropout=0.2,
)
classifier_profile_engine_qda = ProfileEngine(
classifier_qda, partition_function, number_of_partitions, name="profile qda"
)
classifier_profile_engine_keras = ProfileEngine(
classifier_keras,
partition_function,
number_of_partitions,
epochs=20,
name="profile keras",
)
session = Session(
container_profile,
engines=[classifier_profile_engine_qda, classifier_profile_engine_keras],
).run()
save_classifier(
classifier_qda, "classifier_qda.save"
) # The classifier can be saved for further usage
save_classifier(classifier_keras, "classifier_keras.save")
"""
# Part 2: Attack Phase: Apply the prebuilt-classifier on traces with unknown key
"""
# The sensitive value with guess hypothesis
def sensitive_value_with_guess(data, guess):
return sbox[data["plaintext"][byte] ^ guess]
guess_range = range(256) # what are the hypothesis for the guess
container_attack = BasicAesSimulationContainer(
50, 1, seed=12
) # 200 traces for attack (different seed used for having different traces)
container_attack.leakage_section = [byte] # Same POI-selection than for profiling phase
classifier_qda = load_classifier(
"classifier_qda.save"
) # the classifier is imported from a file
classifier_keras = load_classifier("classifier_keras.save")
classifier_match_engine_qda = MatchEngine(
classifier_qda,
sensitive_value_with_guess,
guess_range,
name="match qda",
solution=container_attack.key[byte],
)
classifier_match_engine_keras = MatchEngine(
classifier_keras,
sensitive_value_with_guess,
guess_range,
name="match keras",
solution=container_attack.key[byte],
)
engines = [classifier_match_engine_qda, classifier_match_engine_keras]
session = Session(
container_attack,
engines=engines,
output_method=ScoreProgressionOutputMethod(*engines),
output_steps=range(0, 50, 5),
)
session.run()