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.
@@ -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,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ cracknuts = cracknuts.__main__:main
@@ -0,0 +1 @@
1
+ cracknuts