Source code for pyecsca.sca.attack.leakage_model

"""
Provides leakage models to simulate leakage.
"""
import abc
import sys
from typing import Literal, ClassVar

from numpy.random import default_rng
from public import public

from ...sca.trace import Trace

if sys.version_info[0] < 3 or sys.version_info[0] == 3 and sys.version_info[1] < 10:
    def hw(i):
        return bin(i).count("1")
else:
    def hw(i):
        return i.bit_count()


[docs] @public class Noise: pass
[docs] @public class ZeroNoise(Noise): def __call__(self, *args, **kwargs): return args[0]
[docs] @public class NormalNoice(Noise): """ https://www.youtube.com/watch?v=SAfq55aiqPc """ def __init__(self, mean: float, sdev: float): self.rng = default_rng() self.mean = mean self.sdev = sdev def __call__(self, *args, **kwargs): arg = args[0] if isinstance(arg, Trace): return Trace(arg.samples + self.rng.normal(self.mean, self.sdev, len(arg.samples))) return arg + self.rng.normal(self.mean, self.sdev)
[docs] @public class LeakageModel(abc.ABC): """An abstract leakage model.""" num_args: ClassVar[int] @abc.abstractmethod def __call__(self, *args, **kwargs) -> int: """Get the leakage from the arg(s).""" raise NotImplementedError
[docs] @public class Identity(LeakageModel): """Identity leakage model, leaks the thing itself.""" num_args = 1 def __call__(self, *args, **kwargs) -> int: return int(args[0])
[docs] @public class Bit(LeakageModel): """Bit leakage model, leaks a selected bit.""" num_args = 1 def __init__(self, which: int): if which < 0: raise ValueError("which must be >= 0.") self.which = which self.mask = 1 << which def __call__(self, *args, **kwargs) -> Literal[0, 1]: return (int(args[0]) & self.mask) >> self.which # type: ignore
[docs] @public class Slice(LeakageModel): """Slice leakage model, leaks a slice of bits.""" num_args = 1 def __init__(self, begin: int, end: int): if begin > end: raise ValueError("begin must be <= than end.") self.begin = begin self.end = end self.mask = 0 for i in range(begin, end): self.mask |= 1 << i def __call__(self, *args, **kwargs) -> int: return (int(args[0]) & self.mask) >> self.begin
[docs] @public class HammingWeight(LeakageModel): """Hamming-weight leakage model, leaks the Hamming-weight of the thing.""" num_args = 1 def __call__(self, *args, **kwargs) -> int: return hw(int(args[0]))
[docs] @public class HammingDistance(LeakageModel): """Hamming-distance leakage model, leaks the Hamming-distance between the two things.""" num_args = 2 def __call__(self, *args, **kwargs) -> int: return hw(int(args[0]) ^ int(args[1]))
[docs] @public class BitLength(LeakageModel): """Bit-length leakage model, leaks the bit-length of the thing.""" num_args = 1 def __call__(self, *args, **kwargs) -> int: return int(args[0]).bit_length()