-
Notifications
You must be signed in to change notification settings - Fork 56
/
04-acquisition-setup-example.py
77 lines (57 loc) · 2.59 KB
/
04-acquisition-setup-example.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
# In this tutorial we will show how to set up an `AbstractContainer` dedicated
# to emulate a simple (dummy) side-channel acquisition setup. The context here
# is the use of lascar for the acquisition phase.
#
# Say we are targeting a device running an AES, that we can drive through a
# python class `Dut` (for Device Under Test). This class has a method that
# commands the device to run the targeted operation, and returns the
# plaintext/ciphertext.
import numpy as np
class Dut:
def go(self):
# Dummy AES, returns the plaintext and the ciphertext, concatenated.
plaintext = np.random.randint(0, 256, (16,)) # 16 random bytes
ciphertext = np.random.randint(
0, 256, (16,)
) # 16 random bytes for the ciphertext
return np.append(plaintext, ciphertext)
# Beside, we have an `Oscilloscope` class, which returns the power measurement
# of the device through the method `get_trace`:
class Oscilloscope:
def get_trace(self):
# Return the side-channel leakage: here a vector of 100 floats
return np.random.rand(100)
# We create an `AcquisitionSetup` class, inheriting from `AbstractContainer`, and
# override the `generate_trace` method which will request both device and
# oscilloscope.
from lascar import AbstractContainer, Trace
class AcquisitionSetup(AbstractContainer):
def __init__(self, number_of_traces: int):
"""
:param number_of_traces: Number of traces in the container
"""
super().__init__(self, number_of_traces)
self.dut = Dut()
self.oscilloscope = Oscilloscope()
def generate_trace(self, index: int):
"""
Method required by `AcquisitionSetup` to work properly.
:param index: index of trace, not used here.
:return: Trace with leakage from oscilloscope, and value from the dut
plaintext/ciphertext.
"""
# The container logger can be used!
self.logger.debug("Generate trace %d", index)
value = self.dut.go()
leakage = self.oscilloscope.get_trace()
return Trace(leakage, value)
# Now everything is ready to create our `AcquisitionSetup`:
acquisition = AcquisitionSetup(100)
# This container is Abstract. Its 100 traces are stored nowhere, yet they can be
# accessed:
print("trace 0:", acquisition_container[0])
print("trace 10:", acquisition_container[10])
# More importantly, this container can be converted to a Hdf5Container, so the
# traces get saved to the disk. The export method takes here all its sense.
from lascar import Hdf5Container
hdf5 = Hdf5Container.export(acquisition, "tmp.h5")