def test_save_load(self, leakages, values): filename = tempfile.mkdtemp() + "/tmp.npy" container = TraceBatchContainer(leakages, values, copy=True) container.save(filename) container_bis = TraceBatchContainer.load(filename) for i, trace in enumerate(container_bis): assert np.all(trace.leakage == leakages[i]) assert np.all(trace.value == values[i])
def test_constructor(self, leakages, values): container = TraceBatchContainer(leakages, values, copy=True) for i, trace in enumerate(container): assert np.all(trace.leakage == leakages[i]) assert np.all(trace.value == values[i])
def test_from_arrays(self, leakages, values): filename = tempfile.mkdtemp() + "/tmp.h5" container = Hdf5Container.export(TraceBatchContainer(leakages, values), filename) for i, trace in enumerate(container): assert np.all(trace.leakage == leakages[i]) assert np.all(trace.value == values[i])
lgst_dim = max(map(len, traces)) tmp = np.zeros((len(traces), lgst_dim), dtype=np.float32) for i, t in enumerate(traces): # pad to longest trace (even though they might well be all the same length) tmp[i][: len(t)] = np.array(t, dtype=np.float32) traces = tmp ## Phase 2 : attack with Lascar ## Launch 16 CPAs on the outputs of the sbox from lascar.container import TraceBatchContainer from lascar import Session, CpaEngine, ConsoleOutputMethod from lascar.tools.aes import sbox t = TraceBatchContainer(traces, values) s = Session(t, output_method=ConsoleOutputMethod()) s.add_engines( [ CpaEngine(f"cpa{i}", lambda v, k, z=i: sbox[v[z] ^ k], range(256)) for i in range(16) ] ) s.run() print(s.output_method.finalize()) # Check the results : print("Key should be : f0 33 1c e0 26 6a da ce 86 a8 a1 3b fa 14 67 40")
def __setitem__(self, key, value): TraceBatchContainer.__setitem__(self, key, value)
def __getitem__(self, key): return TraceBatchContainer.__getitem__(self, key)
But the more important is TraceBatchContainer, which actualy stores in RAM both the leakages and values as np.arrays (sharing the same first dimension: the number of traces of the Container In the following, we build a TraceBatchContainer from two np.arrays: 'leakages' and 'values': """ print("TraceBatchContainer example of a batch with 10 traces:") leakages = np.random.rand( 10, 100 ) # 10 fake side-channel leakages, each one with 10 time samples: as a np.ndarray values = np.random.randint(0, 256, ( 10, 16, )) # the 10 values associated, each one of as 16 uint8: as a np.ndarray trace_batch = TraceBatchContainer(leakages, values) # The corresponding TraceBatch print("trace_batch =", trace_batch) print() """ Containers implements a getter which will return either a Trace, or a TraceBatchContainer (if several Traces are asked) A TraceBatchContainer is also iterable """ print("trace_batch[0] =", trace_batch[0]) print("trace_batch[:5] =", trace_batch[:5]) print("trace_batch[range(3)] =", trace_batch[range(3)]) print() for trace in trace_batch: # a container is iterable (it delivers its traces during iteration) print("iteration, trace =", trace)
import pytest import itertools from lascar.container import TraceBatchContainer from lascar.tools.processing import * from sklearn.decomposition import PCA, FastICA import tempfile leakages = np.random.rand(500, 100) values = np.random.randint(0, 256, (500, 16)).astype(np.uint8) container = TraceBatchContainer(leakages, values, copy=True) functions = [ lambda x: -x, lambda x: x[::2], lambda x: -x[0], ] @pytest.mark.parametrize('container, function', [(container, f) for f in functions]) def test_function(container, function): container.leakage_processing = function for i, trace in enumerate(container): assert np.all(trace.leakage == function(leakages[i])) rois = [ [[2], [3]], [[0, 1], [2, 3]], [[0, 1], [2, 3], [4, 5]], ]