def show_nicv(values, traces, nr_digits=4): """ Compute the Normalized Inter-Class Variance as in the article """ import numpy as np values = np.array(values, dtype=np.uint8) traces = np.array(traces) from lascar import TraceBatchContainer, Session, NicvEngine, hamming # Use the Hamming weight of leaked values and add some noise # through the 'leakage_processing' parameter t = TraceBatchContainer( traces, values, leakage_processing=lambda x: np.array( [hamming(i) for i in x], dtype=np.uint ) + np.random.normal(0, 0.5, len(x)), ) s = Session(t) ## Input value leakage # s.add_engines([NicvEngine('a'+str(i), lambda v,z=i:v[z], range(9)) for i in range(nr_digits)]) ## Difference leakage s.add_engines([NicvEngine('a'+str(i), lambda v,z=i:np.int8(v[z]) - np.int8(STORED_PIN[z]), range(-9,8)) for i in range(nr_digits)]) ## below is a variant on the carry bit # s.add_engines([NicvEngine('c'+str(i), lambda v,z=i:v[z]>int(STORED_PIN[z]), range(16)) for i in range(nr_digits)]) s.run() return np.array([s[eng]._finalize() for eng in s.engines if eng not in ['mean', 'var']])
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") K = list( map(lambda x: int(x, 16), "f0 33 1c e0 26 6a da ce 86 a8 a1 3b fa 14 67 40".split()) ) for i, n in enumerate([f"cpa{i}" for i in range(16)]): print(