aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJ08nY2020-03-04 00:04:53 +0100
committerJ08nY2020-03-04 00:04:53 +0100
commita97f49ebe3c8e28d2a9ba76711555a3378b62341 (patch)
treed6064aec39573ad9e83607dbed5873d7872aed21
parentdeca0e3d89ff4483dd6b6b4ad99b3400145bee5b (diff)
downloadpyecsca-a97f49ebe3c8e28d2a9ba76711555a3378b62341.tar.gz
pyecsca-a97f49ebe3c8e28d2a9ba76711555a3378b62341.tar.bz2
pyecsca-a97f49ebe3c8e28d2a9ba76711555a3378b62341.zip
Fix some type issues.
-rw-r--r--Pipfile4
-rw-r--r--pyecsca/ec/configuration.py13
-rw-r--r--pyecsca/ec/curves.py23
-rw-r--r--pyecsca/ec/mod.py1
-rw-r--r--pyecsca/sca/scope/picoscope_sdk.py3
-rw-r--r--pyecsca/sca/target/binary.py4
-rw-r--r--pyecsca/sca/target/chipwhisperer.py2
-rw-r--r--pyecsca/sca/target/flash.py2
-rw-r--r--pyecsca/sca/target/serial.py2
-rw-r--r--pyecsca/sca/target/simpleserial.py2
-rw-r--r--pyecsca/sca/trace/align.py6
-rw-r--r--pyecsca/sca/trace/combine.py6
-rw-r--r--pyecsca/sca/trace/edit.py8
-rw-r--r--pyecsca/sca/trace/filter.py2
-rw-r--r--pyecsca/sca/trace/process.py22
-rw-r--r--pyecsca/sca/trace/sampling.py6
-rw-r--r--pyecsca/sca/trace/test.py4
-rw-r--r--pyecsca/sca/trace/trace.py10
-rw-r--r--pyecsca/sca/trace_set/chipwhisperer.py2
-rw-r--r--pyecsca/sca/trace_set/inspector.py7
-rw-r--r--setup.py5
-rw-r--r--test/sca/test_align.py26
-rw-r--r--test/sca/test_combine.py6
-rw-r--r--test/sca/test_edit.py2
-rw-r--r--test/sca/test_filter.py4
-rw-r--r--test/sca/test_match.py19
-rw-r--r--test/sca/test_process.py2
-rw-r--r--test/sca/test_sampling.py8
-rw-r--r--test/sca/test_test.py25
-rw-r--r--test/sca/test_trace.py2
30 files changed, 125 insertions, 103 deletions
diff --git a/Pipfile b/Pipfile
index a8bc468..201a0a9 100644
--- a/Pipfile
+++ b/Pipfile
@@ -10,6 +10,7 @@ mypy = "*"
flake8 = "*"
sphinx = "*"
sphinx-autodoc-typehints = "*"
+parameterized = "*"
coverage = "*"
[packages]
@@ -19,8 +20,9 @@ atpublic = "*"
matplotlib = "*"
cython = "*"
fastdtw = "*"
-parameterized = "*"
asn1crypto = "*"
+h5py = "*"
+bokeh = "*"
[requires]
python_version = "3.8"
diff --git a/pyecsca/ec/configuration.py b/pyecsca/ec/configuration.py
index 0fd6976..24f3a7f 100644
--- a/pyecsca/ec/configuration.py
+++ b/pyecsca/ec/configuration.py
@@ -1,7 +1,7 @@
from dataclasses import dataclass
from enum import Enum
from itertools import product
-from typing import Set, get_type_hints, Union, get_origin, get_args, Generator
+from typing import get_type_hints, Union, get_origin, get_args, Generator, FrozenSet
from public import public
@@ -78,7 +78,7 @@ class Configuration(object):
"""An ECC implementation configuration."""
model: CurveModel
coords: CoordinateModel
- formulas: Set[Formula]
+ formulas: FrozenSet[Formula]
scalarmult: ScalarMultiplier
hash_type: HashType
mod_rand: RandomMod
@@ -107,9 +107,10 @@ def all_configurations(**kwargs) -> Generator[Configuration, Configuration, None
:param kwargs: The configuration parameters to match.
:return: A generator of the configurations
"""
+
def is_optional(arg_type):
return get_origin(arg_type) == Union and len(get_args(arg_type)) == 2 and \
- get_args(arg_type)[1] == type(None)
+ get_args(arg_type)[1] == type(None) # noqa
def leaf_subclasses(cls):
subs = cls.__subclasses__()
@@ -151,12 +152,12 @@ def all_configurations(**kwargs) -> Generator[Configuration, Configuration, None
isinstance(formula, opt_type)] + [None]
else:
options = [None] # TODO: anything here?
- elif get_origin(required_type) == None and issubclass(required_type, Formula):
+ elif get_origin(required_type) is None and issubclass(required_type, Formula):
options = [formula for formula in coords_formulas if
isinstance(formula, required_type)]
- elif get_origin(required_type) == None and issubclass(required_type, bool):
+ elif get_origin(required_type) is None and issubclass(required_type, bool):
options = [True, False]
- elif get_origin(required_type) == None and issubclass(required_type,
+ elif get_origin(required_type) is None and issubclass(required_type,
int) and name == "width":
options = [3, 5]
else:
diff --git a/pyecsca/ec/curves.py b/pyecsca/ec/curves.py
index bc8329f..aa5e146 100644
--- a/pyecsca/ec/curves.py
+++ b/pyecsca/ec/curves.py
@@ -1,5 +1,6 @@
import json
from os.path import join
+from typing import Dict, Union
from pkg_resources import resource_listdir, resource_isdir, resource_stream
from public import public
@@ -41,6 +42,7 @@ def get_params(category: str, name: str, coords: str, infty: bool = True) -> Dom
if curve["field"]["type"] == "Binary":
raise ValueError("Binary field curves are currently not supported.")
+ # Get model and param names
model: CurveModel
field = int(curve["field"]["p"], 16)
order = int(curve["order"], 16)
@@ -59,29 +61,36 @@ def get_params(category: str, name: str, coords: str, infty: bool = True) -> Dom
param_names = ["a", "d"]
else:
raise ValueError("Unknown curve model.")
+
+ # Check coordinate model name and assumptions
if coords not in model.coordinates:
raise ValueError("Coordinate model not supported for curve.")
coord_model = model.coordinates[coords]
params = {name: Mod(int(curve["params"][name], 16), field) for name in param_names}
for assumption in coord_model.assumptions:
- locals = {}
+ alocals: Dict[str, Union[Mod, int]] = {}
compiled = compile(assumption, "", mode="exec")
- exec(compiled, None, locals)
- for param, value in locals.items():
+ exec(compiled, None, alocals)
+ for param, value in alocals.items():
if params[param] != value:
raise ValueError(f"Coordinate model {coord_model} has an unsatisifed assumption on the {param} parameter (= {value}).")
+ # Construct the point at infinity
+ infinity: Point
if infty:
infinity = InfinityPoint(coord_model)
else:
- locals = {**params}
+ ilocals: Dict[str, Union[Mod, int]] = {**params}
for line in coord_model.neutral:
compiled = compile(line, "", mode="exec")
- exec(compiled, None, locals)
+ exec(compiled, None, ilocals)
infinity_coords = {}
for coordinate in coord_model.variables:
- if coordinate not in locals:
+ if coordinate not in ilocals:
raise ValueError(f"Coordinate model {coord_model} requires infty option.")
- infinity_coords[coordinate] = Mod(locals[coordinate], field)
+ value = ilocals[coordinate]
+ if isinstance(value, int):
+ value = Mod(value, field)
+ infinity_coords[coordinate] = value
infinity = Point(coord_model, **infinity_coords)
elliptic_curve = EllipticCurve(model, coord_model, field, infinity, params)
affine = Point(AffineCoordinateModel(model), x=Mod(int(curve["generator"]["x"], 16), field),
diff --git a/pyecsca/ec/mod.py b/pyecsca/ec/mod.py
index 2b16a07..1fa3f9d 100644
--- a/pyecsca/ec/mod.py
+++ b/pyecsca/ec/mod.py
@@ -51,6 +51,7 @@ def check(func):
return method
+
@public
class RandomModAction(Action):
"""A random sampling from Z_n."""
diff --git a/pyecsca/sca/scope/picoscope_sdk.py b/pyecsca/sca/scope/picoscope_sdk.py
index b21df09..a198367 100644
--- a/pyecsca/sca/scope/picoscope_sdk.py
+++ b/pyecsca/sca/scope/picoscope_sdk.py
@@ -159,6 +159,8 @@ class PicoScopeSdk(Scope): # pragma: no cover
return True
def retrieve(self, channel: str) -> Optional[np.ndarray]:
+ if self.samples is None:
+ raise ValueError
actual_samples = ctypes.c_int32(self.samples)
overflow = ctypes.c_int16()
assert_pico_ok(
@@ -179,6 +181,7 @@ class PicoScopeSdk(Scope): # pragma: no cover
raise ValueError
return method(*args, **kwargs)
+
@public
class PS5000Scope(PicoScopeSdk): # pragma: no cover
MODULE = ps5000
diff --git a/pyecsca/sca/target/binary.py b/pyecsca/sca/target/binary.py
index 9a469b6..cb4c918 100644
--- a/pyecsca/sca/target/binary.py
+++ b/pyecsca/sca/target/binary.py
@@ -14,7 +14,7 @@ class BinaryTarget(SerialTarget):
debug_output: bool
def __init__(self, binary: Union[str, List[str]], debug_output: bool = False, **kwargs):
- super().__init__(**kwargs)
+ super().__init__()
if not isinstance(binary, (str, list)):
raise TypeError
if isinstance(binary, str):
@@ -34,7 +34,7 @@ class BinaryTarget(SerialTarget):
self.process.stdin.write(data.decode())
self.process.stdin.flush()
- def read(self, num: Optional[int] = 0, timeout: Optional[int] = 0) -> bytes:
+ def read(self, num: int = 0, timeout: int = 0) -> bytes:
if self.process is None:
raise ValueError
if num != 0:
diff --git a/pyecsca/sca/target/chipwhisperer.py b/pyecsca/sca/target/chipwhisperer.py
index 3710195..3dd5686 100644
--- a/pyecsca/sca/target/chipwhisperer.py
+++ b/pyecsca/sca/target/chipwhisperer.py
@@ -36,7 +36,7 @@ class ChipWhispererTarget(Flashable, SimpleSerialTarget): # pragma: no cover
self.target.flush()
self.target.write(data.decode())
- def read(self, num: Optional[int] = 0, timeout: Optional[int] = 0) -> bytes:
+ def read(self, num: int = 0, timeout: int = 0) -> bytes:
return self.target.read(num, timeout).encode()
def reset(self):
diff --git a/pyecsca/sca/target/flash.py b/pyecsca/sca/target/flash.py
index be3cfb0..bfdb79f 100644
--- a/pyecsca/sca/target/flash.py
+++ b/pyecsca/sca/target/flash.py
@@ -8,4 +8,4 @@ class Flashable(ABC):
@abstractmethod
def flash(self, fw_path: str) -> bool:
- ... \ No newline at end of file
+ ...
diff --git a/pyecsca/sca/target/serial.py b/pyecsca/sca/target/serial.py
index 3c0b5c4..ccde326 100644
--- a/pyecsca/sca/target/serial.py
+++ b/pyecsca/sca/target/serial.py
@@ -14,5 +14,5 @@ class SerialTarget(Target):
...
@abstractmethod
- def read(self, num: Optional[int] = 0, timeout: Optional[int] = 0) -> bytes:
+ def read(self, num: int = 0, timeout: int = 0) -> bytes:
...
diff --git a/pyecsca/sca/target/simpleserial.py b/pyecsca/sca/target/simpleserial.py
index 9e26b79..1ad0b68 100644
--- a/pyecsca/sca/target/simpleserial.py
+++ b/pyecsca/sca/target/simpleserial.py
@@ -63,7 +63,7 @@ class SimpleSerialTarget(SerialTarget):
"""
data = bytes(cmd)
for i in range(0, len(data), 64):
- chunk = data[i:i+64]
+ chunk = data[i:i + 64]
sleep(0.010)
self.write(chunk)
self.write(b"\n")
diff --git a/pyecsca/sca/trace/align.py b/pyecsca/sca/trace/align.py
index 643efcf..1c9c216 100644
--- a/pyecsca/sca/trace/align.py
+++ b/pyecsca/sca/trace/align.py
@@ -27,7 +27,7 @@ def align_reference(reference: Trace, *traces: Trace,
result_samples[:length - offset] = trace.samples[offset:]
else:
result_samples[-offset:] = trace.samples[:length + offset]
- result.append(Trace(copy(trace.title), copy(trace.data), result_samples))
+ result.append(Trace(result_samples, copy(trace.title), copy(trace.data)))
return result
@@ -198,7 +198,7 @@ def align_dtw_scale(reference: Trace, *traces: Trace, radius: int = 1,
scale[x] += 1
result_samples //= scale
del scale
- result.append(Trace(copy(trace.title), copy(trace.data), result_samples))
+ result.append(Trace(result_samples, copy(trace.title), copy(trace.data)))
return result
@@ -233,5 +233,5 @@ def align_dtw(reference: Trace, *traces: Trace, radius: int = 1, fast: bool = Tr
# or manually:
# for x, y in path:
# result_samples[x] = trace.samples[y]
- result.append(Trace(copy(trace.title), copy(trace.data), result_samples))
+ result.append(Trace(result_samples, copy(trace.title), copy(trace.data)))
return result
diff --git a/pyecsca/sca/trace/combine.py b/pyecsca/sca/trace/combine.py
index c484748..2ab552a 100644
--- a/pyecsca/sca/trace/combine.py
+++ b/pyecsca/sca/trace/combine.py
@@ -16,10 +16,10 @@ def average(*traces: Trace) -> Optional[CombinedTrace]:
if not traces:
return None
if len(traces) == 1:
- return CombinedTrace(None, None, traces[0].samples.copy(), parents=traces)
+ return CombinedTrace(traces[0].samples.copy(), None, None)
dtype = traces[0].samples.dtype
result_samples = np.mean(np.array([trace.samples for trace in traces]), axis=0).astype(dtype)
- return CombinedTrace(None, None, result_samples, parents=traces)
+ return CombinedTrace(result_samples, None, None)
@public
@@ -46,4 +46,4 @@ def standard_deviation(*traces: Trace) -> Optional[CombinedTrace]:
return None
dtype = traces[0].samples.dtype
result_samples = np.std(np.array([trace.samples for trace in traces]), axis=0).astype(dtype)
- return CombinedTrace(None, None, result_samples, parents=traces)
+ return CombinedTrace(result_samples, None, None)
diff --git a/pyecsca/sca/trace/edit.py b/pyecsca/sca/trace/edit.py
index f01a0dc..f58ad57 100644
--- a/pyecsca/sca/trace/edit.py
+++ b/pyecsca/sca/trace/edit.py
@@ -22,7 +22,7 @@ def trim(trace: Trace, start: int = None, end: int = None) -> Trace:
end = len(trace.samples)
if start > end:
raise ValueError("Invalid trim arguments.")
- return Trace(copy(trace.title), copy(trace.data), trace.samples[start:end].copy())
+ return Trace(trace.samples[start:end].copy(), copy(trace.title), copy(trace.data))
@public
@@ -33,7 +33,7 @@ def reverse(trace: Trace) -> Trace:
:param trace:
:return:
"""
- return Trace(copy(trace.title), copy(trace.data), np.flipud(trace.samples))
+ return Trace(np.flipud(trace.samples), copy(trace.title), copy(trace.data))
@public
@@ -51,5 +51,5 @@ def pad(trace: Trace, lengths: Union[Tuple[int, int], int],
lengths = (lengths, lengths)
if not isinstance(values, tuple):
values = (values, values)
- return Trace(copy(trace.title), copy(trace.data),
- np.pad(trace.samples, lengths, "constant", constant_values=values))
+ return Trace(np.pad(trace.samples, lengths, "constant", constant_values=values),
+ copy(trace.title), copy(trace.data))
diff --git a/pyecsca/sca/trace/filter.py b/pyecsca/sca/trace/filter.py
index 11cc89c..6bb17b9 100644
--- a/pyecsca/sca/trace/filter.py
+++ b/pyecsca/sca/trace/filter.py
@@ -14,7 +14,7 @@ def filter_any(trace: Trace, sampling_frequency: int,
else:
b, a = butter(6, cutoff / nyq, btype=band_type, analog=False, output='ba')
result_samples = lfilter(b, a, trace.samples)
- return Trace(copy(trace.title), copy(trace.data), result_samples)
+ return Trace(result_samples, copy(trace.title), copy(trace.data))
@public
diff --git a/pyecsca/sca/trace/process.py b/pyecsca/sca/trace/process.py
index 8e983b2..4cdbeff 100644
--- a/pyecsca/sca/trace/process.py
+++ b/pyecsca/sca/trace/process.py
@@ -13,7 +13,7 @@ def absolute(trace: Trace) -> Trace:
:param trace:
:return:
"""
- return Trace(copy(trace.title), copy(trace.data), np.absolute(trace.samples))
+ return Trace(np.absolute(trace.samples), copy(trace.title), copy(trace.data))
@public
@@ -24,7 +24,7 @@ def invert(trace: Trace) -> Trace:
:param trace:
:return:
"""
- return Trace(copy(trace.title), copy(trace.data), np.negative(trace.samples))
+ return Trace(np.negative(trace.samples), copy(trace.title), copy(trace.data))
@public
@@ -39,7 +39,7 @@ def threshold(trace: Trace, value) -> Trace:
result_samples = trace.samples.copy()
result_samples[result_samples <= value] = 0
result_samples[np.nonzero(result_samples)] = 1
- return Trace(copy(trace.title), copy(trace.data), result_samples)
+ return Trace(result_samples, copy(trace.title), copy(trace.data))
def rolling_window(samples: np.ndarray, window: int) -> np.ndarray:
@@ -57,9 +57,8 @@ def rolling_mean(trace: Trace, window: int) -> Trace:
:param window:
:return:
"""
- return Trace(copy(trace.title), copy(trace.data),
- np.mean(rolling_window(trace.samples, window), -1).astype(
- dtype=trace.samples.dtype))
+ return Trace(np.mean(rolling_window(trace.samples, window), -1).astype(
+ dtype=trace.samples.dtype), copy(trace.title), copy(trace.data))
@public
@@ -71,7 +70,7 @@ def offset(trace: Trace, offset) -> Trace:
:param offset:
:return:
"""
- return Trace(copy(trace.title), copy(trace.data), trace.samples + offset)
+ return Trace(trace.samples + offset, copy(trace.title), copy(trace.data))
def root_mean_square(trace: Trace):
@@ -92,12 +91,11 @@ def recenter(trace: Trace) -> Trace:
@public
def normalize(trace: Trace) -> Trace:
- return Trace(copy(trace.title), copy(trace.data),
- (trace.samples - np.mean(trace.samples)) / np.std(trace.samples))
+ return Trace((trace.samples - np.mean(trace.samples)) / np.std(trace.samples),
+ copy(trace.title), copy(trace.data))
@public
def normalize_wl(trace: Trace) -> Trace:
- return Trace(copy(trace.title), copy(trace.data),
- (trace.samples - np.mean(trace.samples)) / (
- np.std(trace.samples) * len(trace.samples)))
+ return Trace((trace.samples - np.mean(trace.samples)) / (
+ np.std(trace.samples) * len(trace.samples)), copy(trace.title), copy(trace.data))
diff --git a/pyecsca/sca/trace/sampling.py b/pyecsca/sca/trace/sampling.py
index 29dc251..fdd5e5b 100644
--- a/pyecsca/sca/trace/sampling.py
+++ b/pyecsca/sca/trace/sampling.py
@@ -18,7 +18,7 @@ def downsample_average(trace: Trace, factor: int = 2) -> Trace:
"""
resized = np.resize(trace.samples, len(trace.samples) - (len(trace.samples) % factor))
result_samples = resized.reshape(-1, factor).mean(axis=1).astype(trace.samples.dtype)
- return Trace(copy(trace.title), copy(trace.data), result_samples)
+ return Trace(result_samples, copy(trace.title), copy(trace.data))
@public
@@ -32,7 +32,7 @@ def downsample_pick(trace: Trace, factor: int = 2, offset: int = 0) -> Trace:
:return:
"""
result_samples = trace.samples[offset::factor].copy()
- return Trace(copy(trace.title), copy(trace.data), result_samples)
+ return Trace(result_samples, copy(trace.title), copy(trace.data))
@public
@@ -45,4 +45,4 @@ def downsample_decimate(trace: Trace, factor: int = 2) -> Trace:
:return:
"""
result_samples = decimate(trace.samples, factor)
- return Trace(copy(trace.title), copy(trace.data), result_samples)
+ return Trace(result_samples, copy(trace.title), copy(trace.data))
diff --git a/pyecsca/sca/trace/test.py b/pyecsca/sca/trace/test.py
index f2cfb33..4fc0236 100644
--- a/pyecsca/sca/trace/test.py
+++ b/pyecsca/sca/trace/test.py
@@ -14,7 +14,7 @@ def ttest_func(first_set: Sequence[Trace], second_set: Sequence[Trace],
first_stack = np.stack([first.samples for first in first_set])
second_stack = np.stack([second.samples for second in second_set])
result = ttest_ind(first_stack, second_stack, axis=0, equal_var=equal_var)
- return CombinedTrace(None, None, result[0], parents=[*first_set, *second_set])
+ return CombinedTrace(result[0], None, None)
@public
@@ -61,4 +61,4 @@ def ks_test(first_set: Sequence[Trace], second_set: Sequence[Trace]) -> Optional
results = np.empty(len(first_set[0].samples), dtype=first_set[0].samples.dtype)
for i in range(len(first_set[0].samples)):
results[i] = ks_2samp(first_stack[..., i], second_stack[..., i])[0]
- return CombinedTrace(None, None, results, parents=[*first_set, *second_set])
+ return CombinedTrace(results, None, None)
diff --git a/pyecsca/sca/trace/trace.py b/pyecsca/sca/trace/trace.py
index 5324a37..18df978 100644
--- a/pyecsca/sca/trace/trace.py
+++ b/pyecsca/sca/trace/trace.py
@@ -11,8 +11,8 @@ class Trace(object):
data: Optional[bytes]
samples: ndarray
- def __init__(self, title: Optional[str], data: Optional[bytes],
- samples: ndarray, trace_set: Any = None):
+ def __init__(self, samples: ndarray, title: Optional[str], data: Optional[bytes],
+ trace_set: Any = None):
self.title = title
self.data = data
self.samples = samples
@@ -39,9 +39,9 @@ class Trace(object):
class CombinedTrace(Trace):
"""A power trace that was combined from other traces, `parents`."""
- def __init__(self, title: Optional[str], data: Optional[bytes],
- samples: ndarray, trace_set=None, parents: Sequence[Trace] = None):
- super().__init__(title, data, samples, trace_set=trace_set)
+ def __init__(self, samples: ndarray, title: Optional[str], data: Optional[bytes],
+ trace_set=None, parents: Sequence[Trace] = None):
+ super().__init__(samples, title, data, trace_set=trace_set)
self.parents = None
if parents is not None:
self.parents = weakref.WeakSet(parents)
diff --git a/pyecsca/sca/trace_set/chipwhisperer.py b/pyecsca/sca/trace_set/chipwhisperer.py
index d9dcf3f..2b37c6f 100644
--- a/pyecsca/sca/trace_set/chipwhisperer.py
+++ b/pyecsca/sca/trace_set/chipwhisperer.py
@@ -17,7 +17,7 @@ class ChipWhispererTraceSet(TraceSet):
else:
data = self.__read_data(path, name)
trace_data = data["traces"]
- traces = [Trace(None, None, trace_samples, trace_set=self) for trace_samples in trace_data]
+ traces = [Trace(trace_samples, None, None, trace_set=self) for trace_samples in trace_data]
del data["traces"]
config = self.__read_config(path, name)
super().__init__(*traces, **data, **config)
diff --git a/pyecsca/sca/trace_set/inspector.py b/pyecsca/sca/trace_set/inspector.py
index f9475c0..b07313d 100644
--- a/pyecsca/sca/trace_set/inspector.py
+++ b/pyecsca/sca/trace_set/inspector.py
@@ -197,7 +197,7 @@ class InspectorTraceSet(TraceSet):
samples = np.frombuffer(
file.read(dtype.itemsize * self.num_samples), dtype,
self.num_samples)
- result.append(Trace(title, data, samples, trace_set=self))
+ result.append(Trace(samples, title, data, trace_set=self))
return result
def __write(self, file):
@@ -229,9 +229,8 @@ class InspectorTraceSet(TraceSet):
file.write(trace.samples.tobytes())
def __scale(self, traces):
- return list(map(lambda trace: Trace(trace.title, trace.data,
- trace.samples.astype("f4") * self.y_scale,
- trace_set=self),
+ return list(map(lambda trace: Trace(trace.samples.astype("f4") * self.y_scale, trace.title,
+ trace.data, trace_set=self),
traces))
def save(self, output: Union[Path, str, BinaryIO]):
diff --git a/setup.py b/setup.py
index 1f1bffa..7ebccae 100644
--- a/setup.py
+++ b/setup.py
@@ -30,8 +30,11 @@ setup(
"scipy",
"atpublic",
"matplotlib",
+ "cython",
"fastdtw",
- "asn1crypto"
+ "asn1crypto",
+ "h5py",
+ "bokeh"
],
extras_require={
"picoscope_sdk": ["picosdk"],
diff --git a/test/sca/test_align.py b/test/sca/test_align.py
index 57f7119..96cc458 100644
--- a/test/sca/test_align.py
+++ b/test/sca/test_align.py
@@ -12,9 +12,9 @@ class AlignTests(TestCase):
first_arr = np.array([10, 64, 120, 64, 10, 10, 10, 10, 10], dtype=np.dtype("i1"))
second_arr = np.array([10, 10, 10, 10, 50, 80, 50, 20, 10], dtype=np.dtype("i1"))
third_arr = np.array([70, 30, 42, 35, 28, 21, 15, 10, 5], dtype=np.dtype("i1"))
- a = Trace(None, None, first_arr)
- b = Trace(None, None, second_arr)
- c = Trace(None, None, third_arr)
+ a = Trace(first_arr, None, None)
+ b = Trace(second_arr, None, None)
+ c = Trace(third_arr, None, None)
result = align_correlation(a, b, c, reference_offset=1, reference_length=3, max_offset=4, min_correlation=0.65)
self.assertIsNotNone(result)
self.assertEqual(len(result), 2)
@@ -36,16 +36,16 @@ class AlignTests(TestCase):
def test_peak_align(self):
first_arr = np.array([10, 64, 14, 120, 15, 30, 10, 15, 20, 15, 15, 10, 10], dtype=np.dtype("i1"))
second_arr = np.array([10, 10, 10, 10, 90, 40, 50, 20, 10, 17, 16, 10, 10], dtype=np.dtype("i1"))
- a = Trace(None, None, first_arr)
- b = Trace(None, None, second_arr)
+ a = Trace(first_arr, None, None)
+ b = Trace(second_arr, None, None)
result = align_peaks(a, b, reference_offset=2, reference_length=5, max_offset=3)
self.assertEqual(np.argmax(result[0].samples), np.argmax(result[1].samples))
def test_sad_align(self):
first_arr = np.array([10, 64, 14, 120, 15, 30, 10, 15, 20, 15, 15, 10, 10], dtype=np.dtype("i1"))
second_arr = np.array([10, 10, 10, 10, 90, 40, 50, 20, 10, 17, 16, 10, 10], dtype=np.dtype("i1"))
- a = Trace(None, None, first_arr)
- b = Trace(None, None, second_arr)
+ a = Trace(first_arr, None, None)
+ b = Trace(second_arr, None, None)
result = align_sad(a, b, reference_offset=2, reference_length=5, max_offset=3)
self.assertEqual(len(result), 2)
@@ -53,9 +53,9 @@ class AlignTests(TestCase):
first_arr = np.array([10, 64, 14, 120, 15, 30, 10, 15, 20, 15, 15, 10, 10, 8, 10, 12, 10, 13, 9], dtype=np.dtype("i1"))
second_arr = np.array([10, 10, 10, 10, 60, 40, 90, 20, 10, 17, 16, 10, 10, 10, 10, 10, 17, 12, 10], dtype=np.dtype("i1"))
third_arr = np.array([10, 30, 20, 21, 15, 8, 10, 37, 21, 77, 20, 28, 25, 10, 9, 10, 15, 9, 10], dtype=np.dtype("i1"))
- a = Trace(None, None, first_arr)
- b = Trace(None, None, second_arr)
- c = Trace(None, None, third_arr)
+ a = Trace(first_arr, None, None)
+ b = Trace(second_arr, None, None)
+ c = Trace(third_arr, None, None)
result = align_dtw_scale(a, b, c)
self.assertEqual(np.argmax(result[0].samples), np.argmax(result[1].samples))
@@ -66,9 +66,9 @@ class AlignTests(TestCase):
first_arr = np.array([10, 64, 14, 120, 15, 30, 10, 15, 20, 15, 15, 10, 10, 8, 10, 12, 10, 13, 9], dtype=np.dtype("i1"))
second_arr = np.array([10, 10, 10, 10, 60, 40, 90, 20, 10, 17, 16, 10, 10, 10, 10, 10, 17, 12, 10], dtype=np.dtype("i1"))
third_arr = np.array([10, 30, 20, 21, 15, 8, 10, 47, 21, 77, 20, 28, 25, 10, 9, 10, 15, 9, 10], dtype=np.dtype("i1"))
- a = Trace(None, None, first_arr)
- b = Trace(None, None, second_arr)
- c = Trace(None, None, third_arr)
+ a = Trace(first_arr, None, None)
+ b = Trace(second_arr, None, None)
+ c = Trace(third_arr, None, None)
result = align_dtw(a, b, c)
self.assertEqual(np.argmax(result[0].samples), np.argmax(result[1].samples))
diff --git a/test/sca/test_combine.py b/test/sca/test_combine.py
index 113eb69..7fda1fa 100644
--- a/test/sca/test_combine.py
+++ b/test/sca/test_combine.py
@@ -7,9 +7,9 @@ from pyecsca.sca import Trace, CombinedTrace, average, conditional_average, stan
class CombineTests(TestCase):
def setUp(self):
- self.a = Trace(None, b"\xff", np.array([20, 80], dtype=np.dtype("i1")))
- self.b = Trace(None, b"\xff", np.array([30, 42], dtype=np.dtype("i1")))
- self.c = Trace(None, b"\x00", np.array([78, 56], dtype=np.dtype("i1")))
+ self.a = Trace(np.array([20, 80], dtype=np.dtype("i1")), None, b"\xff")
+ self.b = Trace(np.array([30, 42], dtype=np.dtype("i1")), None, b"\xff")
+ self.c = Trace(np.array([78, 56], dtype=np.dtype("i1")), None, b"\x00")
def test_average(self):
self.assertIsNone(average())
diff --git a/test/sca/test_edit.py b/test/sca/test_edit.py
index e44cfb0..637e9b7 100644
--- a/test/sca/test_edit.py
+++ b/test/sca/test_edit.py
@@ -8,7 +8,7 @@ from pyecsca.sca import Trace, trim, reverse, pad
class EditTests(TestCase):
def setUp(self):
- self._trace = Trace(None, None, np.array([10, 20, 30, 40, 50], dtype=np.dtype("i1")))
+ self._trace = Trace(np.array([10, 20, 30, 40, 50], dtype=np.dtype("i1")), None, None)
def test_trim(self):
result = trim(self._trace, 2)
diff --git a/test/sca/test_filter.py b/test/sca/test_filter.py
index c95d5b5..9194fa4 100644
--- a/test/sca/test_filter.py
+++ b/test/sca/test_filter.py
@@ -8,7 +8,9 @@ from .utils import plot
class FilterTests(TestCase):
def setUp(self):
- self._trace = Trace(None, None, np.array([5, 12, 15, 13, 15, 11, 7, 2, -4, -8, -10, -8, -13, -9, -11, -8, -5], dtype=np.dtype("i1")))
+ self._trace = Trace(
+ np.array([5, 12, 15, 13, 15, 11, 7, 2, -4, -8, -10, -8, -13, -9, -11, -8, -5],
+ dtype=np.dtype("i1")), None, None)
def test_lowpass(self):
result = filter_lowpass(self._trace, 100, 20)
diff --git a/test/sca/test_match.py b/test/sca/test_match.py
index 9cbd284..b8663c7 100644
--- a/test/sca/test_match.py
+++ b/test/sca/test_match.py
@@ -9,21 +9,22 @@ from .utils import plot
class MatchingTests(TestCase):
def test_simple_match(self):
- pattern = Trace(None, None,
- np.array([1, 15, 12, -10, 0, 13, 17, -1, 0], dtype=np.dtype("i1")))
- base = Trace(None, None, np.array(
+ pattern = Trace(np.array([1, 15, 12, -10, 0, 13, 17, -1, 0], dtype=np.dtype("i1")), None,
+ None)
+ base = Trace(np.array(
[0, 1, 3, 1, 2, -2, -3, 1, 15, 12, -10, 0, 13, 17, -1, 0, 3, 1],
- dtype=np.dtype("i1")))
+ dtype=np.dtype("i1")), None, None)
filtered = match_part(base, 7, 9)
self.assertListEqual(filtered, [7])
plot(self, base=base, pattern=pad(pattern, (filtered[0], 0)))
def test_multiple_match(self):
- pattern = Trace(None, None,
- np.array([1, 15, 12, -10, 0, 13, 17, -1, 0], dtype=np.dtype("i1")))
- base = Trace(None, None, np.array(
- [0, 1, 3, 1, 2, -2, -3, 1, 18, 10, -5, 0, 13, 17, -1, 0, 3, 1, 2, 5, 13, 8, -8, 1, 11, 15, 0, 1, 5, 2, 4],
- dtype=np.dtype("i1")))
+ pattern = Trace(np.array([1, 15, 12, -10, 0, 13, 17, -1, 0], dtype=np.dtype("i1")), None,
+ None)
+ base = Trace(np.array(
+ [0, 1, 3, 1, 2, -2, -3, 1, 18, 10, -5, 0, 13, 17, -1, 0, 3, 1, 2, 5, 13, 8, -8, 1,
+ 11, 15, 0, 1, 5, 2, 4],
+ dtype=np.dtype("i1")), None, None)
filtered = match_pattern(base, pattern, 0.9)
self.assertListEqual(filtered, [7, 19])
plot(self, base=base, pattern1=pad(pattern, (filtered[0], 0)), pattern2=pad(pattern, (filtered[1], 0)))
diff --git a/test/sca/test_process.py b/test/sca/test_process.py
index 5b80d1f..f039a95 100644
--- a/test/sca/test_process.py
+++ b/test/sca/test_process.py
@@ -7,7 +7,7 @@ from pyecsca.sca import Trace, absolute, invert, threshold, rolling_mean, offset
class ProcessTests(TestCase):
def setUp(self):
- self._trace = Trace(None, None, np.array([30, -60, 145, 247], dtype=np.dtype("i2")))
+ self._trace = Trace(np.array([30, -60, 145, 247], dtype=np.dtype("i2")), None, None)
def test_absolute(self):
result = absolute(self._trace)
diff --git a/test/sca/test_sampling.py b/test/sca/test_sampling.py
index 75a227d..40eaa7d 100644
--- a/test/sca/test_sampling.py
+++ b/test/sca/test_sampling.py
@@ -8,7 +8,7 @@ from .utils import plot
class SamplingTests(TestCase):
def setUp(self):
- self._trace = Trace(None, None, np.array([20, 40, 50, 50, 10], dtype=np.dtype("i1")))
+ self._trace = Trace(np.array([20, 40, 50, 50, 10], dtype=np.dtype("i1")), None, None)
def test_downsample_average(self):
result = downsample_average(self._trace, 2)
@@ -27,9 +27,9 @@ class SamplingTests(TestCase):
self.assertEqual(result.samples[1], 50)
def test_downsample_decimate(self):
- trace = Trace(None, None, np.array([20, 30, 55, 18, 15, 10, 35, 24, 21, 15, 10, 8, -10, -5,
- -8, -12, -15, -18, -34, -21, -17, -10, -5, -12, -6, -2,
- 4, 8, 21, 28], dtype=np.dtype("i1")))
+ trace = Trace(np.array([20, 30, 55, 18, 15, 10, 35, 24, 21, 15, 10, 8, -10, -5,
+ -8, -12, -15, -18, -34, -21, -17, -10, -5, -12, -6, -2,
+ 4, 8, 21, 28], dtype=np.dtype("i1")), None, None)
result = downsample_decimate(trace, 2)
self.assertIsNotNone(result)
self.assertIsInstance(result, Trace)
diff --git a/test/sca/test_test.py b/test/sca/test_test.py
index 898c6d6..5277c20 100644
--- a/test/sca/test_test.py
+++ b/test/sca/test_test.py
@@ -8,16 +8,19 @@ from pyecsca.sca import Trace, welch_ttest, student_ttest, ks_test
class TTestTests(TestCase):
def setUp(self):
- self.a = Trace(None, b"\xff", np.array([20, 80], dtype=np.dtype("i1")))
- self.b = Trace(None, b"\xff", np.array([30, 42], dtype=np.dtype("i1")))
- self.c = Trace(None, b"\x00", np.array([78, 56], dtype=np.dtype("i1")))
- self.d = Trace(None, b"\x00", np.array([98, 36], dtype=np.dtype("i1")))
+ self.a = Trace(np.array([20, 80], dtype=np.dtype("i1")), None, b"\xff")
+ self.b = Trace(np.array([30, 42], dtype=np.dtype("i1")), None, b"\xff")
+ self.c = Trace(np.array([78, 56], dtype=np.dtype("i1")), None, b"\x00")
+ self.d = Trace(np.array([98, 36], dtype=np.dtype("i1")), None, b"\x00")
def test_welch_ttest(self):
self.assertIsNotNone(welch_ttest([self.a, self.b], [self.c, self.d]))
- a = Trace(None, None, np.array([19.8, 20.4, 19.6, 17.8, 18.5, 18.9, 18.3, 18.9, 19.5, 22.0]))
- b = Trace(None, None, np.array([28.2, 26.6, 20.1, 23.3, 25.2, 22.1, 17.7, 27.6, 20.6, 13.7]))
- c = Trace(None, None, np.array([20.2, 21.6, 27.1, 13.3, 24.2, 20.1, 11.7, 25.6, 26.6, 21.4]))
+ a = Trace(np.array([19.8, 20.4, 19.6, 17.8, 18.5, 18.9, 18.3, 18.9, 19.5, 22.0]), None,
+ None)
+ b = Trace(np.array([28.2, 26.6, 20.1, 23.3, 25.2, 22.1, 17.7, 27.6, 20.6, 13.7]), None,
+ None)
+ c = Trace(np.array([20.2, 21.6, 27.1, 13.3, 24.2, 20.1, 11.7, 25.6, 26.6, 21.4]), None,
+ None)
result = welch_ttest([a, b], [b, c])
self.assertIsNotNone(result)
@@ -32,8 +35,8 @@ class KolmogorovSmirnovTests(TestCase):
def test_ks_test(self):
self.assertIsNone(ks_test([], []))
- a = Trace(None, b"\xff", np.array([20, 80], dtype=np.dtype("i1")))
- b = Trace(None, b"\xff", np.array([30, 42], dtype=np.dtype("i1")))
- c = Trace(None, b"\x00", np.array([78, 56], dtype=np.dtype("i1")))
- d = Trace(None, b"\x00", np.array([98, 36], dtype=np.dtype("i1")))
+ a = Trace(np.array([20, 80], dtype=np.dtype("i1")), None, b"\xff")
+ b = Trace(np.array([30, 42], dtype=np.dtype("i1")), None, b"\xff")
+ c = Trace(np.array([78, 56], dtype=np.dtype("i1")), None, b"\x00")
+ d = Trace(np.array([98, 36], dtype=np.dtype("i1")), None, b"\x00")
self.assertIsNotNone(ks_test([a, b], [c, d]))
diff --git a/test/sca/test_trace.py b/test/sca/test_trace.py
index 91b7161..3399c09 100644
--- a/test/sca/test_trace.py
+++ b/test/sca/test_trace.py
@@ -6,7 +6,7 @@ from pyecsca.sca import Trace
class TraceTests(TestCase):
def test_basic(self):
- trace = Trace("Name", b"\xff\xaa", np.array([10, 15, 24], dtype=np.dtype("i1")))
+ trace = Trace(np.array([10, 15, 24], dtype=np.dtype("i1")), "Name", b"\xff\xaa")
self.assertIsNotNone(trace)
self.assertIn("Trace", str(trace))
self.assertIsNone(trace.trace_set)