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
|
from configparser import ConfigParser
from itertools import zip_longest
from os.path import exists, isfile, join, basename, dirname
from pathlib import Path
from typing import Union, BinaryIO
import numpy as np
from public import public
from pyecsca.sca.trace_set.base import TraceSet
from pyecsca.sca.trace import Trace
@public
class ChipWhispererTraceSet(TraceSet):
"""ChipWhisperer trace set (native) format."""
@classmethod
def read(
cls, input: Union[str, Path, bytes, BinaryIO], **kwargs
) -> "ChipWhispererTraceSet":
if isinstance(input, (str, Path)):
traces, kws = ChipWhispererTraceSet.__read(input)
return ChipWhispererTraceSet(*traces, **kws)
else:
raise ValueError
@classmethod
def inplace(
cls, input: Union[str, Path, bytes, BinaryIO], **kwargs
) -> "ChipWhispererTraceSet":
raise NotImplementedError
def write(self, output: Union[str, Path, BinaryIO]):
raise NotImplementedError
@classmethod
def __read(cls, full_path):
file_name = basename(full_path)
if not file_name.startswith("config_") or not file_name.endswith(".cfg"):
raise ValueError
path = dirname(full_path)
name = file_name[7:-4]
data = ChipWhispererTraceSet.__read_data(path, name)
traces = []
for samples, key, textin, textout in zip_longest(
data["traces"], data["keylist"], data["textin"], data["textout"]
):
traces.append(
Trace(samples, {"key": key, "textin": textin, "textout": textout})
)
del data["traces"]
del data["keylist"]
del data["textin"]
del data["textout"]
config = ChipWhispererTraceSet.__read_config(path, name)
return traces, {**data, **config}
@classmethod
def __read_data(cls, path, name):
types = {
"keylist": None,
"knownkey": None,
"textin": None,
"textout": None,
"traces": None,
}
for type in types:
type_path = join(path, name + type + ".npy")
if exists(type_path) and isfile(type_path):
types[type] = np.load(type_path, allow_pickle=True)
return types
@classmethod
def __read_config(cls, path, name):
config_path = join(path, "config_" + name + ".cfg")
if exists(config_path) and isfile(config_path):
config = ConfigParser()
config.read(config_path)
return config["Trace Config"]
else:
return {}
def __repr__(self):
return "ChipWhispererTraceSet()"
|