CrackNuts 0.0.1.dev2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cracknuts/__init__.py +5 -0
- cracknuts/__main__.py +33 -0
- cracknuts/acquisition/__init__.py +3 -0
- cracknuts/acquisition/acquisition.py +554 -0
- cracknuts/cracker/__init__.py +0 -0
- cracknuts/cracker/basic_cracker.py +334 -0
- cracknuts/cracker/cracker.py +548 -0
- cracknuts/cracker/mock_cracker.py +163 -0
- cracknuts/cracker/protocol.py +83 -0
- cracknuts/cracker/stateful_cracker.py +214 -0
- cracknuts/logger.py +88 -0
- cracknuts/solver/__init__.py +0 -0
- cracknuts/solver/trace.py +524 -0
- cracknuts/utils/__init__.py +0 -0
- cracknuts/utils/hex_util.py +38 -0
- cracknuts-0.0.1.dev2.dist-info/LICENSE +21 -0
- cracknuts-0.0.1.dev2.dist-info/METADATA +63 -0
- cracknuts-0.0.1.dev2.dist-info/RECORD +21 -0
- cracknuts-0.0.1.dev2.dist-info/WHEEL +5 -0
- cracknuts-0.0.1.dev2.dist-info/entry_points.txt +2 -0
- cracknuts-0.0.1.dev2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
import json
|
|
3
|
+
import os.path
|
|
4
|
+
import time
|
|
5
|
+
import typing
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
import zarr
|
|
9
|
+
|
|
10
|
+
from cracknuts import logger
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TraceDatasetData:
|
|
14
|
+
def __init__(self, level: int = 0, index: tuple = None, get_trace_data: typing.Callable[[any, any], tuple] = None):
|
|
15
|
+
self._level: int = level
|
|
16
|
+
self._index: tuple = index
|
|
17
|
+
self._get_trace_data = get_trace_data
|
|
18
|
+
|
|
19
|
+
def __getitem__(self, index):
|
|
20
|
+
if not isinstance(index, tuple):
|
|
21
|
+
index = (index,)
|
|
22
|
+
|
|
23
|
+
level = len(index) + self._level
|
|
24
|
+
index = index if self._index is None else (*self._index, *index)
|
|
25
|
+
if level < 2:
|
|
26
|
+
return TraceDatasetData(level, index, self._get_trace_data)
|
|
27
|
+
else:
|
|
28
|
+
return self._get_trace_data(*index)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class TraceDataset(abc.ABC):
|
|
32
|
+
_channel_count: int
|
|
33
|
+
_trace_count: int
|
|
34
|
+
_sample_count: int
|
|
35
|
+
_data_length: int
|
|
36
|
+
_create_time: int
|
|
37
|
+
_version: str
|
|
38
|
+
|
|
39
|
+
@abc.abstractmethod
|
|
40
|
+
def get_origin_data(self): ...
|
|
41
|
+
|
|
42
|
+
@classmethod
|
|
43
|
+
@abc.abstractmethod
|
|
44
|
+
def load(cls, path: str, **kwargs) -> "TraceDataset": ...
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
@abc.abstractmethod
|
|
48
|
+
def new(
|
|
49
|
+
cls, path: str, channel_count: int, trace_count: int, sample_count: int, data_length: int, version, **kwargs
|
|
50
|
+
) -> "TraceDataset": ...
|
|
51
|
+
|
|
52
|
+
@abc.abstractmethod
|
|
53
|
+
def dump(self, path: str = None, **kwargs): ...
|
|
54
|
+
|
|
55
|
+
@abc.abstractmethod
|
|
56
|
+
def set_trace(self, channel_index: int, trace_index: int, trace: np.ndarray, data: np.ndarray | None): ...
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def data(self) -> TraceDatasetData:
|
|
60
|
+
return TraceDatasetData(get_trace_data=self._get_trace_data)
|
|
61
|
+
|
|
62
|
+
@abc.abstractmethod
|
|
63
|
+
def _get_trace_data(self, channel_slice, trace_slice) -> tuple[list, list, np.ndarray, np.ndarray]: ...
|
|
64
|
+
|
|
65
|
+
def _parse_slice(self, channel_slice, trace_slice) -> tuple[list, list]:
|
|
66
|
+
if isinstance(channel_slice, slice):
|
|
67
|
+
start, stop, step = channel_slice.indices(self._channel_count)
|
|
68
|
+
channel_indexes = [i for i in range(start, stop, step)]
|
|
69
|
+
elif isinstance(channel_slice, int):
|
|
70
|
+
channel_indexes = [channel_slice]
|
|
71
|
+
elif isinstance(channel_slice, list):
|
|
72
|
+
channel_indexes = channel_slice
|
|
73
|
+
else:
|
|
74
|
+
channel_indexes = None
|
|
75
|
+
|
|
76
|
+
if isinstance(trace_slice, slice):
|
|
77
|
+
start, stop, step = trace_slice.indices(self._trace_count)
|
|
78
|
+
trace_indexes = [i for i in range(start, stop, step)]
|
|
79
|
+
elif isinstance(trace_slice, int):
|
|
80
|
+
trace_indexes = [trace_slice]
|
|
81
|
+
elif isinstance(trace_slice, list):
|
|
82
|
+
trace_indexes = trace_slice
|
|
83
|
+
else:
|
|
84
|
+
trace_indexes = None
|
|
85
|
+
|
|
86
|
+
return channel_indexes, trace_indexes
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def channel_count(self):
|
|
90
|
+
return self._channel_count
|
|
91
|
+
|
|
92
|
+
@property
|
|
93
|
+
def trace_count(self):
|
|
94
|
+
return self._trace_count
|
|
95
|
+
|
|
96
|
+
@property
|
|
97
|
+
def sample_count(self):
|
|
98
|
+
return self._sample_count
|
|
99
|
+
|
|
100
|
+
@property
|
|
101
|
+
def data_length(self):
|
|
102
|
+
return self._data_length
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def create_time(self):
|
|
106
|
+
return self._create_time
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class ScarrTraceDataset(TraceDataset):
|
|
110
|
+
_ATTR_METADATA_KEY = "metadata"
|
|
111
|
+
_GROUP_ROOT_PATH = "0"
|
|
112
|
+
_ARRAY_TRACES_PATH = "traces"
|
|
113
|
+
_ARRAY_DATA_PATH = "plaintext"
|
|
114
|
+
|
|
115
|
+
def __init__(
|
|
116
|
+
self,
|
|
117
|
+
zarr_path: str,
|
|
118
|
+
create_empty: bool = False,
|
|
119
|
+
channel_count: int = None,
|
|
120
|
+
trace_count: int = None,
|
|
121
|
+
sample_count: int = None,
|
|
122
|
+
data_length: int = None,
|
|
123
|
+
zarr_kwargs: dict = None,
|
|
124
|
+
zarr_trace_group_kwargs: dict = None,
|
|
125
|
+
zarr_data_group_kwargs: dict = None,
|
|
126
|
+
create_time: int = None,
|
|
127
|
+
version: str = None,
|
|
128
|
+
):
|
|
129
|
+
if create_empty:
|
|
130
|
+
if channel_count is None or trace_count is None or sample_count is None or data_length is None:
|
|
131
|
+
raise ValueError(
|
|
132
|
+
"channel_count and trace_count and sample_count and data_length "
|
|
133
|
+
"must be specified when in write mode."
|
|
134
|
+
)
|
|
135
|
+
else:
|
|
136
|
+
if zarr_path is None:
|
|
137
|
+
raise ValueError("The zarr_path must be specified when in non-write mode.")
|
|
138
|
+
|
|
139
|
+
self._zarr_path: str = zarr_path
|
|
140
|
+
self._channel_count: int = channel_count
|
|
141
|
+
self._trace_count: int = trace_count
|
|
142
|
+
self._sample_count: int = sample_count
|
|
143
|
+
self._data_length: int = data_length
|
|
144
|
+
self._create_time: int = create_time
|
|
145
|
+
self._version: str = version
|
|
146
|
+
|
|
147
|
+
if zarr_kwargs is None:
|
|
148
|
+
zarr_kwargs = {}
|
|
149
|
+
if zarr_trace_group_kwargs is None:
|
|
150
|
+
zarr_trace_group_kwargs = {}
|
|
151
|
+
if zarr_data_group_kwargs is None:
|
|
152
|
+
zarr_data_group_kwargs = {}
|
|
153
|
+
|
|
154
|
+
mode = zarr_kwargs.pop("mode", "w" if create_empty else "r")
|
|
155
|
+
self._zarr_data = zarr.open(zarr_path, mode=mode, **zarr_kwargs)
|
|
156
|
+
|
|
157
|
+
if create_empty:
|
|
158
|
+
self._create_time = int(time.time())
|
|
159
|
+
group_root = self._zarr_data.create_group(self._GROUP_ROOT_PATH)
|
|
160
|
+
for i in range(self._channel_count):
|
|
161
|
+
channel_group = group_root.create_group(str(i))
|
|
162
|
+
channel_group.create(
|
|
163
|
+
self._ARRAY_TRACES_PATH,
|
|
164
|
+
shape=(self._trace_count, self._sample_count),
|
|
165
|
+
dtype=np.int16,
|
|
166
|
+
**zarr_trace_group_kwargs,
|
|
167
|
+
)
|
|
168
|
+
channel_group.create(
|
|
169
|
+
self._ARRAY_DATA_PATH,
|
|
170
|
+
shape=(self._trace_count, self._data_length),
|
|
171
|
+
dtype=np.uint8,
|
|
172
|
+
**zarr_data_group_kwargs,
|
|
173
|
+
)
|
|
174
|
+
self._zarr_data.attrs[self._ATTR_METADATA_KEY] = {
|
|
175
|
+
"create_time": self._create_time,
|
|
176
|
+
"channel_count": self._channel_count,
|
|
177
|
+
"trace_count": self._trace_count,
|
|
178
|
+
"sample_count": self._sample_count,
|
|
179
|
+
"data_length": self._data_length,
|
|
180
|
+
"version": self._version,
|
|
181
|
+
}
|
|
182
|
+
else:
|
|
183
|
+
metadata = self._zarr_data.attrs[self._ATTR_METADATA_KEY]
|
|
184
|
+
self._create_time = metadata.get("create_time")
|
|
185
|
+
self._channel_count = metadata.get("channel_count")
|
|
186
|
+
self._trace_count = metadata.get("trace_count")
|
|
187
|
+
self._sample_count = metadata.get("sample_count")
|
|
188
|
+
self._data_length = metadata.get("data_length")
|
|
189
|
+
self._version = metadata.get("version")
|
|
190
|
+
|
|
191
|
+
@classmethod
|
|
192
|
+
def load(cls, path: str, **kwargs) -> "TraceDataset":
|
|
193
|
+
kwargs["mode"] = "r"
|
|
194
|
+
return cls(path, zarr_kwargs=kwargs)
|
|
195
|
+
|
|
196
|
+
@classmethod
|
|
197
|
+
def new(
|
|
198
|
+
cls,
|
|
199
|
+
path: str,
|
|
200
|
+
channel_count: int,
|
|
201
|
+
trace_count: int,
|
|
202
|
+
sample_count: int,
|
|
203
|
+
data_length: int,
|
|
204
|
+
version: str,
|
|
205
|
+
**kwargs,
|
|
206
|
+
) -> "TraceDataset":
|
|
207
|
+
kwargs["mode"] = "w"
|
|
208
|
+
return cls(
|
|
209
|
+
path,
|
|
210
|
+
create_empty=True,
|
|
211
|
+
channel_count=channel_count,
|
|
212
|
+
trace_count=trace_count,
|
|
213
|
+
sample_count=sample_count,
|
|
214
|
+
data_length=data_length,
|
|
215
|
+
version=version,
|
|
216
|
+
zarr_kwargs=kwargs,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
def dump(self, path: str = None, **kwargs):
|
|
220
|
+
if path is not None and path != self._zarr_path:
|
|
221
|
+
zarr.copy_store(self._zarr_data, zarr.open(path, mode="w"))
|
|
222
|
+
|
|
223
|
+
def set_trace(self, channel_index: int, trace_index: int, trace: np.ndarray, data: np.ndarray | None):
|
|
224
|
+
if channel_index not in range(0, self._channel_count):
|
|
225
|
+
raise ValueError("channel index out range")
|
|
226
|
+
if trace_index not in range(0, self._trace_count):
|
|
227
|
+
raise ValueError("trace, index out of range")
|
|
228
|
+
self._get_under_root(channel_index, self._ARRAY_TRACES_PATH)[trace_index] = trace
|
|
229
|
+
self._get_under_root(channel_index, self._ARRAY_DATA_PATH)[trace_index] = data
|
|
230
|
+
|
|
231
|
+
def get_origin_data(self):
|
|
232
|
+
return self._zarr_data
|
|
233
|
+
|
|
234
|
+
def get_trace_by_indexes(self, channel_index: int, *trace_indexes: int) -> tuple[np.ndarray, np.ndarray] | None:
|
|
235
|
+
return (
|
|
236
|
+
self._get_under_root(channel_index, self._ARRAY_TRACES_PATH)[[i for i in trace_indexes]],
|
|
237
|
+
self._get_under_root(channel_index, self._ARRAY_DATA_PATH)[[i for i in trace_indexes]],
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
def get_trace_by_range(
|
|
241
|
+
self, channel_index: int, index_start: int, index_end: int
|
|
242
|
+
) -> tuple[np.ndarray, np.ndarray] | None:
|
|
243
|
+
return (
|
|
244
|
+
self._get_under_root(channel_index, self._ARRAY_TRACES_PATH)[index_start:index_end],
|
|
245
|
+
self._get_under_root(channel_index, self._ARRAY_DATA_PATH)[index_start:index_end],
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
def _get_under_root(self, *paths: any):
|
|
249
|
+
paths = self._GROUP_ROOT_PATH, *paths
|
|
250
|
+
return self._zarr_data["/".join(str(path) for path in paths)]
|
|
251
|
+
|
|
252
|
+
def _get_trace_data(self, channel_slice, trace_slice) -> tuple[list, list, np.ndarray, np.ndarray]:
|
|
253
|
+
traces = []
|
|
254
|
+
data = []
|
|
255
|
+
|
|
256
|
+
channel_indexes, trace_indexes = self._parse_slice(channel_slice, trace_slice)
|
|
257
|
+
|
|
258
|
+
if isinstance(trace_slice, int):
|
|
259
|
+
trace_slice = slice(trace_slice, trace_slice + 1)
|
|
260
|
+
|
|
261
|
+
for channel_index in channel_indexes:
|
|
262
|
+
traces.append(self._get_under_root(channel_index, self._ARRAY_TRACES_PATH)[trace_slice])
|
|
263
|
+
data.append(self._get_under_root(channel_index, self._ARRAY_DATA_PATH)[trace_slice])
|
|
264
|
+
|
|
265
|
+
return channel_indexes, trace_indexes, np.array(traces), np.array(data)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class NumpyTraceDataset(TraceDataset):
|
|
269
|
+
_ARRAY_TRACE_PATH = "trace.npy"
|
|
270
|
+
_ARRAY_DATA_PATH = "data.npy"
|
|
271
|
+
_METADATA_PATH = "metadata.json"
|
|
272
|
+
|
|
273
|
+
def __init__(
|
|
274
|
+
self,
|
|
275
|
+
npy_trace_path: str = None,
|
|
276
|
+
npy_data_path: str = None,
|
|
277
|
+
npy_metadata_path: str = None,
|
|
278
|
+
create_empty: bool = False,
|
|
279
|
+
channel_count: int = None,
|
|
280
|
+
trace_count: int = None,
|
|
281
|
+
sample_count: int = None,
|
|
282
|
+
data_length: int = None,
|
|
283
|
+
create_time: int = None,
|
|
284
|
+
version: str = None,
|
|
285
|
+
):
|
|
286
|
+
self._logger = logger.get_logger(NumpyTraceDataset)
|
|
287
|
+
|
|
288
|
+
if create_empty:
|
|
289
|
+
if channel_count is None or trace_count is None or sample_count is None or data_length is None:
|
|
290
|
+
raise ValueError(
|
|
291
|
+
"channel_count and trace_count and sample_count and data_length "
|
|
292
|
+
"must be specified when in write mode."
|
|
293
|
+
)
|
|
294
|
+
else:
|
|
295
|
+
if npy_trace_path is None:
|
|
296
|
+
raise ValueError("The npy_trace_path must be specified when in non-write mode.")
|
|
297
|
+
elif npy_data_path is None or npy_metadata_path is None:
|
|
298
|
+
self._logger.warning(
|
|
299
|
+
"npy_data_path or npy_metadata_path is not specified, data or metadata info will be not load."
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
self._npy_trace_path: str = npy_trace_path
|
|
303
|
+
self._npy_data_path: str = npy_data_path
|
|
304
|
+
self._npy_metadata_path: str = npy_metadata_path
|
|
305
|
+
|
|
306
|
+
self._channel_count: int = channel_count
|
|
307
|
+
self._trace_count: int = trace_count
|
|
308
|
+
self._sample_count: int = sample_count
|
|
309
|
+
self._data_length: int = data_length
|
|
310
|
+
self._create_time: int = create_time
|
|
311
|
+
self._version: str = version
|
|
312
|
+
|
|
313
|
+
if create_empty:
|
|
314
|
+
self._trace_array: np.ndarray = np.zeros(
|
|
315
|
+
shape=(self._channel_count, self._trace_count, self._sample_count), dtype=np.int16
|
|
316
|
+
)
|
|
317
|
+
self._data_array: np.ndarray = np.zeros(
|
|
318
|
+
shape=(self._channel_count, self._trace_count, self._data_length), dtype=np.uint8
|
|
319
|
+
)
|
|
320
|
+
self._create_time = int(time.time())
|
|
321
|
+
|
|
322
|
+
else:
|
|
323
|
+
self._data_array: np.ndarray = np.load(self._npy_data_path)
|
|
324
|
+
self._trace_array: np.ndarray = np.load(self._npy_trace_path)
|
|
325
|
+
self._load_metadata()
|
|
326
|
+
|
|
327
|
+
def _load_metadata(self):
|
|
328
|
+
with open(self._npy_metadata_path) as f:
|
|
329
|
+
metadata = json.load(f)
|
|
330
|
+
self._channel_count: int = metadata.get("channel_count")
|
|
331
|
+
self._trace_count: int = metadata.get("trace_count")
|
|
332
|
+
self._sample_count: int = metadata.get("sample_count")
|
|
333
|
+
self._data_length: int = metadata.get("data_length")
|
|
334
|
+
self._create_time: int = metadata.get("create_time")
|
|
335
|
+
self._version: str = metadata.get("version")
|
|
336
|
+
|
|
337
|
+
def _dump_metadata(self):
|
|
338
|
+
with open(self._npy_metadata_path, "w") as f:
|
|
339
|
+
json.dump(
|
|
340
|
+
{
|
|
341
|
+
"channel_count": self._channel_count,
|
|
342
|
+
"trace_count": self._trace_count,
|
|
343
|
+
"sample_count": self._sample_count,
|
|
344
|
+
"data_length": self._data_length,
|
|
345
|
+
"create_time": self._create_time,
|
|
346
|
+
"version": self._version,
|
|
347
|
+
},
|
|
348
|
+
f,
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
def get_origin_data(self):
|
|
352
|
+
return self._trace_array, self._data_array
|
|
353
|
+
|
|
354
|
+
@classmethod
|
|
355
|
+
def load(cls, path: str, **kwargs) -> "TraceDataset":
|
|
356
|
+
return cls(
|
|
357
|
+
os.path.join(path, cls._ARRAY_TRACE_PATH),
|
|
358
|
+
os.path.join(path, cls._ARRAY_DATA_PATH),
|
|
359
|
+
os.path.join(path, cls._METADATA_PATH),
|
|
360
|
+
**kwargs,
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
@classmethod
|
|
364
|
+
def load_from_numpy_array(cls, trace: np.ndarray, data: np.ndarray = None):
|
|
365
|
+
channel_count = None
|
|
366
|
+
trace_count = None
|
|
367
|
+
sample_count = None
|
|
368
|
+
data_length = None
|
|
369
|
+
|
|
370
|
+
shape = trace.shape
|
|
371
|
+
|
|
372
|
+
if data is not None and not shape == data.shape:
|
|
373
|
+
raise ValueError("trace and data must have the same shape.")
|
|
374
|
+
|
|
375
|
+
array_size = len(shape)
|
|
376
|
+
|
|
377
|
+
if array_size == 1:
|
|
378
|
+
channel_count = 1
|
|
379
|
+
trace_count = 1
|
|
380
|
+
sample_count = shape[0]
|
|
381
|
+
data_length = data.shape[0] if data is not None else 0
|
|
382
|
+
elif array_size == 2:
|
|
383
|
+
channel_count = 1
|
|
384
|
+
trace_count = shape[0]
|
|
385
|
+
sample_count = shape[1]
|
|
386
|
+
data_length = data.shape[1] if data is not None else 0
|
|
387
|
+
elif array_size == 3:
|
|
388
|
+
channel_count = shape[0]
|
|
389
|
+
trace_count = shape[1]
|
|
390
|
+
sample_count = shape[2]
|
|
391
|
+
data_length = data.shape[2] if data is not None else 0
|
|
392
|
+
|
|
393
|
+
ds = cls(
|
|
394
|
+
create_empty=True,
|
|
395
|
+
channel_count=channel_count,
|
|
396
|
+
trace_count=trace_count,
|
|
397
|
+
sample_count=sample_count,
|
|
398
|
+
data_length=data_length,
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
if array_size == 1:
|
|
402
|
+
ds.set_trace(0, 0, trace, data)
|
|
403
|
+
elif array_size == 2:
|
|
404
|
+
for t in range(shape[0]):
|
|
405
|
+
ds.set_trace(0, t, trace[t], data[t] if data is not None else None)
|
|
406
|
+
elif array_size == 3:
|
|
407
|
+
for c in range(shape[0]):
|
|
408
|
+
for t in range(shape[1]):
|
|
409
|
+
ds.set_trace(c, t, trace[c, t], data[c, t] if data is not None else None)
|
|
410
|
+
|
|
411
|
+
return ds
|
|
412
|
+
|
|
413
|
+
@classmethod
|
|
414
|
+
def new(
|
|
415
|
+
cls,
|
|
416
|
+
path: str,
|
|
417
|
+
channel_count: int,
|
|
418
|
+
trace_count: int,
|
|
419
|
+
sample_count: int,
|
|
420
|
+
data_length: int,
|
|
421
|
+
version: str,
|
|
422
|
+
**kwargs,
|
|
423
|
+
) -> "TraceDataset":
|
|
424
|
+
if not os.path.exists(path):
|
|
425
|
+
os.makedirs(path)
|
|
426
|
+
elif os.path.isfile(path):
|
|
427
|
+
raise Exception(f"{path} is not a file.")
|
|
428
|
+
|
|
429
|
+
npy_trace_path = os.path.join(path, cls._ARRAY_TRACE_PATH)
|
|
430
|
+
npy_data_path = os.path.join(path, cls._ARRAY_DATA_PATH)
|
|
431
|
+
npy_metadata_path = os.path.join(path, cls._METADATA_PATH)
|
|
432
|
+
|
|
433
|
+
return cls(
|
|
434
|
+
npy_trace_path=npy_trace_path,
|
|
435
|
+
npy_data_path=npy_data_path,
|
|
436
|
+
npy_metadata_path=npy_metadata_path,
|
|
437
|
+
create_empty=True,
|
|
438
|
+
channel_count=channel_count,
|
|
439
|
+
trace_count=trace_count,
|
|
440
|
+
sample_count=sample_count,
|
|
441
|
+
data_length=data_length,
|
|
442
|
+
version=version,
|
|
443
|
+
**kwargs,
|
|
444
|
+
)
|
|
445
|
+
|
|
446
|
+
def dump(self, path: str = None, **kwargs):
|
|
447
|
+
np.save(self._npy_trace_path, self._trace_array)
|
|
448
|
+
np.save(self._npy_data_path, self._data_array)
|
|
449
|
+
self._dump_metadata()
|
|
450
|
+
|
|
451
|
+
def set_trace(self, channel_index: int, trace_index: int, trace: np.ndarray, data: np.ndarray | None):
|
|
452
|
+
self._trace_array[channel_index, trace_index, :] = trace
|
|
453
|
+
if data is not None:
|
|
454
|
+
self._data_array[channel_index, trace_index, :] = data
|
|
455
|
+
|
|
456
|
+
def _get_trace_data(self, channel_slice, trace_slice) -> tuple[list, list, np.ndarray, np.ndarray]:
|
|
457
|
+
c, t = self._parse_slice(channel_slice, trace_slice)
|
|
458
|
+
if isinstance(channel_slice, int):
|
|
459
|
+
channel_slice = slice(channel_slice, channel_slice + 1)
|
|
460
|
+
if isinstance(trace_slice, int):
|
|
461
|
+
trace_slice = slice(trace_slice, trace_slice + 1)
|
|
462
|
+
return c, t, self._trace_array[channel_slice, trace_slice], self._data_array[channel_slice, trace_slice]
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
# def add_trace(self, index: int, trace: np.ndarray, data: bytes):
|
|
466
|
+
# self._trace_array[index:] = trace
|
|
467
|
+
# self._data_array[index:] = data
|
|
468
|
+
#
|
|
469
|
+
# def load_from_numpy_data_file(self, path: str, transpose=False) -> "TraceDataset":
|
|
470
|
+
# """
|
|
471
|
+
# Load traces from numpy data file.
|
|
472
|
+
# :param path: file path.
|
|
473
|
+
# :param transpose: if axes 0 is not represent trace and axes 1 is not represent trace data(sample)
|
|
474
|
+
# """
|
|
475
|
+
# self.traces = np.load(path)
|
|
476
|
+
# if transpose:
|
|
477
|
+
# self.traces = self.traces.T
|
|
478
|
+
# sample_count, trace_count = self.traces.shape
|
|
479
|
+
# else:
|
|
480
|
+
# trace_count, sample_count = self.traces.shape
|
|
481
|
+
#
|
|
482
|
+
# self._metadata.trace_count = trace_count
|
|
483
|
+
# self._metadata.sample_count = sample_count
|
|
484
|
+
#
|
|
485
|
+
# return self
|
|
486
|
+
#
|
|
487
|
+
# def load_from_zarr(self, path: str, structure: str = "scarr"):
|
|
488
|
+
# if structure == "scarr":
|
|
489
|
+
# self.load_from_scarr(path)
|
|
490
|
+
# # todo other
|
|
491
|
+
#
|
|
492
|
+
# def load_from_scarr(self, path: str):
|
|
493
|
+
# scarr_data = zarr.open(path, "r")
|
|
494
|
+
# self.traces = scarr_data["0/0/traces"]
|
|
495
|
+
# trace_count = self.traces.shape[0]
|
|
496
|
+
# sample_count = self.traces.shape[1]
|
|
497
|
+
# data = scarr_data["0/0/plaintext"]
|
|
498
|
+
#
|
|
499
|
+
# self._metadata.trace_count = trace_count
|
|
500
|
+
# self._metadata.sample_count = sample_count
|
|
501
|
+
# self.data = data
|
|
502
|
+
#
|
|
503
|
+
# def load_from_hdf5(self, path: str): ...
|
|
504
|
+
#
|
|
505
|
+
# # def add_trace(self, trace: np.ndarray, index: int = None):
|
|
506
|
+
# # if index is None:
|
|
507
|
+
# # index = self._current_create_trace_index
|
|
508
|
+
# # self._current_create_trace_index += 1
|
|
509
|
+
# # self.traces[index:] = trace
|
|
510
|
+
#
|
|
511
|
+
# def add_data(self, data: bytes, index: int = None):
|
|
512
|
+
# if index is None:
|
|
513
|
+
# index = self._current_create_data_index
|
|
514
|
+
# self._current_create_data_index += 1
|
|
515
|
+
# self.data[index:] = data
|
|
516
|
+
#
|
|
517
|
+
# def update_metadata_environment_info(self, cracknuts: str, cracker: str, nuts: str): ...
|
|
518
|
+
#
|
|
519
|
+
# def save_as_numpy_file(self, path):
|
|
520
|
+
# np.save(os.path.join(path, "trace.npy"), self.traces)
|
|
521
|
+
# np.save(os.path.join(path, "data.npy"), self.data)
|
|
522
|
+
#
|
|
523
|
+
# def save_as_zarr(self, path): ... # todo
|
|
524
|
+
# ...
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
def get_bytes_matrix(data):
|
|
2
|
+
hex_matrix = ""
|
|
3
|
+
|
|
4
|
+
bytes_per_line = 16
|
|
5
|
+
|
|
6
|
+
hex_matrix += f"Total bytes: {len(data)}\n"
|
|
7
|
+
|
|
8
|
+
hex_matrix += " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 01234567 89ABCDEF\n"
|
|
9
|
+
hex_matrix += " ------------------------------------------------- -------------------\n"
|
|
10
|
+
|
|
11
|
+
for i in range(0, len(data), bytes_per_line):
|
|
12
|
+
chunk = data[i : i + bytes_per_line]
|
|
13
|
+
|
|
14
|
+
hex_matrix_line = ""
|
|
15
|
+
|
|
16
|
+
hex_matrix_line += f"{i:08X}: "
|
|
17
|
+
|
|
18
|
+
hex_values = " ".join([f"{byte:02X}" for byte in chunk[:8]])
|
|
19
|
+
hex_values += " " if len(chunk) > 8 else ""
|
|
20
|
+
hex_values += " ".join([f"{byte:02X}" for byte in chunk[8:]])
|
|
21
|
+
hex_matrix_line += f"{hex_values:<49}"
|
|
22
|
+
|
|
23
|
+
ascii_values = "".join([chr(byte) if 32 <= byte <= 126 else "." for byte in chunk[:8]])
|
|
24
|
+
ascii_values += " " if len(chunk) > 8 else ""
|
|
25
|
+
ascii_values += "".join([chr(byte) if 32 <= byte <= 126 else "." for byte in chunk[8:]])
|
|
26
|
+
hex_matrix_line += f"| {ascii_values:<17} |"
|
|
27
|
+
|
|
28
|
+
hex_matrix += hex_matrix_line + "\n"
|
|
29
|
+
|
|
30
|
+
return hex_matrix
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_hex(b: bytes):
|
|
34
|
+
return " ".join(f"{byte:02x}" for byte in b)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if __name__ == "__main__":
|
|
38
|
+
get_bytes_matrix(bytes(range(256)))
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [2024] [Cracknuts org]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: cracknuts
|
|
3
|
+
Version: 0.0.1.dev2
|
|
4
|
+
Summary: A library for cracknuts device.
|
|
5
|
+
Author-email: Dingzb <dingzibiao@gmail.com>
|
|
6
|
+
Maintainer-email: Dingzb <dingzibiao@gmail.com>
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) [2024] [Cracknuts org]
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
Project-URL: homepage, https://cracknuts.io
|
|
29
|
+
Requires-Python: >=3.12
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Requires-Dist: numpy ~=1.26.4
|
|
33
|
+
Requires-Dist: pandas ~=2.2.2
|
|
34
|
+
Requires-Dist: click ~=8.1.7
|
|
35
|
+
Requires-Dist: zarr ~=2.18.2
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: ruff >=0.6.3 ; extra == 'dev'
|
|
38
|
+
Requires-Dist: typos ~=1.24.4 ; extra == 'dev'
|
|
39
|
+
Requires-Dist: build ~=1.2.1 ; extra == 'dev'
|
|
40
|
+
Requires-Dist: pre-commit ~=3.8.0 ; extra == 'dev'
|
|
41
|
+
Provides-Extra: test
|
|
42
|
+
Requires-Dist: pytest ~=8.3.2 ; extra == 'test'
|
|
43
|
+
|
|
44
|
+
# Cracknuts
|
|
45
|
+
|
|
46
|
+
A library for cracknuts device.
|
|
47
|
+
|
|
48
|
+
## Install
|
|
49
|
+
|
|
50
|
+
```shell
|
|
51
|
+
pip install cracknuts
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
And then execute the following script. A successful output of the version number indicates a successful installation.
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import cracknuts
|
|
58
|
+
cracknuts.version()
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
***More details will be available soon.***
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
cracknuts/__init__.py,sha256=h3yCE4BlO4TKuUMMjq4B4oRYE_CZKcYnqihPXPhtOQo,67
|
|
2
|
+
cracknuts/__main__.py,sha256=Wz3b38yV0iZK1Yf8v-TCQEuqaDN86aEKe9I08pa4-EM,1000
|
|
3
|
+
cracknuts/logger.py,sha256=7QiIyrnfYIoB2t3wbs5HrDOWDKsxiu8tuCA8dwb--qQ,2557
|
|
4
|
+
cracknuts/acquisition/__init__.py,sha256=PKBH5o0Uj3Alvt9wee8VW4tdTegBi3WaRjWA-HAz0Jg,127
|
|
5
|
+
cracknuts/acquisition/acquisition.py,sha256=3uWxpecGgoKrZoQI2_uyyXE6fp_T7GzzywPUTzkdaJg,20393
|
|
6
|
+
cracknuts/cracker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
cracknuts/cracker/basic_cracker.py,sha256=x2DFbGZZ9VYnd8FdJAJ44FW_NDgeIxzfwgtiqzxCnnA,14905
|
|
8
|
+
cracknuts/cracker/cracker.py,sha256=owQV24WqMPZpSFx7V2RrmRcCWn9SpPFoVOjEV7VIsRU,15929
|
|
9
|
+
cracknuts/cracker/mock_cracker.py,sha256=on4MTfUTu6CLUUrTSDdo3-QwgKLisV0mfvb6G7PsRk8,6159
|
|
10
|
+
cracknuts/cracker/protocol.py,sha256=UJQFr0qfRsXfQtRo4iy0QqaGe243irf76OcMhLix4do,2796
|
|
11
|
+
cracknuts/cracker/stateful_cracker.py,sha256=uLmi8SmRoCsf2IAUpKx_j03BuDDx1hvPfLZ_nXplVKA,7811
|
|
12
|
+
cracknuts/solver/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
13
|
+
cracknuts/solver/trace.py,sha256=tNTjXIzzQk1p7ayhL2Bijjs8UFIOVvdJ-IKg8RDcUGI,18802
|
|
14
|
+
cracknuts/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
cracknuts/utils/hex_util.py,sha256=mhXxtpGnIBzFGUwFG9cXh0FY9Jqfhh7QxxT19oyEPpU,1246
|
|
16
|
+
cracknuts-0.0.1.dev2.dist-info/LICENSE,sha256=nGKiJWWtbS6GzTuavzxssXHjF5GLIAjm1wRcMVBXUVU,1073
|
|
17
|
+
cracknuts-0.0.1.dev2.dist-info/METADATA,sha256=JAN-D74c4JN7Gk26zvofwM10Q7y4gFAUH6XTfaTDF9E,2283
|
|
18
|
+
cracknuts-0.0.1.dev2.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
19
|
+
cracknuts-0.0.1.dev2.dist-info/entry_points.txt,sha256=nEPlDyUvGueBi_4lFft6Fls_tt7Q029gY5JRBeurYPM,54
|
|
20
|
+
cracknuts-0.0.1.dev2.dist-info/top_level.txt,sha256=7Gl3DJme_PYVJnFM800XseM1lHOFNswZqwrAP3KgzYw,10
|
|
21
|
+
cracknuts-0.0.1.dev2.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cracknuts
|