import numpy as np
from typing import Optional, Tuple
from public import public
from ...ec.coordinates import CoordinateModel
from ...ec.mod import Mod
from ...ec.model import CurveModel
from ...ec.params import DomainParameters
from ...ec.point import Point
from ...ec.mult import ScalarMultiplier
from ...ec.key_generation import KeyGeneration
from ...ec.key_agreement import KeyAgreement
from ...ec.signature import Signature, SignatureResult
from ...ec.formula import FormulaAction
from ...ec.context import DefaultContext, local
from ..attack import LeakageModel
from ..trace import Trace
from .base import Target
[docs]
@public
class LeakageTarget(Target):
model: CurveModel
coords: CoordinateModel
mult: ScalarMultiplier
leakage_model: LeakageModel
params: Optional[DomainParameters]
privkey: Optional[Mod]
pubkey: Optional[Point]
def __init__(
self,
model: CurveModel,
coords: CoordinateModel,
mult: ScalarMultiplier,
leakage_model: LeakageModel,
):
super().__init__()
self.model = model
self.coords = coords
self.mult = mult
self.leakage_model = leakage_model
self.params = None
self.privkey = None
self.pubkey = None
[docs]
def get_trace(self, context: DefaultContext) -> Trace:
def callback(action):
if isinstance(action, FormulaAction):
for intermediate in action.op_results:
leak = self.leakage_model(intermediate.value)
temp_trace.append(leak)
temp_trace: list[int] = []
context.actions.walk(callback)
return Trace(np.array(temp_trace))
[docs]
def simulate_scalar_mult_traces(
self, num_of_traces: int, scalar: int
) -> Tuple[list[Point], list[Trace]]:
if self.params is None:
raise ValueError("Missing DomainParameters")
points = [
self.params.curve.affine_random().to_model(self.coords, self.params.curve)
for _ in range(num_of_traces)
]
traces = []
for point in points:
_, trace = self.scalar_mult(scalar, point)
traces.append(trace)
return points, traces
[docs]
def simulate_ecdh_traces(
self, num_of_traces: int
) -> Tuple[list[Point], list[Trace]]:
if self.params is None:
raise ValueError("Missing DomainParameters")
other_pubs = [
self.params.curve.affine_random().to_model(self.coords, self.params.curve)
for _ in range(num_of_traces)
]
traces = []
for pub in other_pubs:
_, trace = self.ecdh(pub, None)
traces.append(trace)
return other_pubs, traces
[docs]
def set_params(self, params: DomainParameters) -> None:
self.params = params
[docs]
def set_leakage_model(self, leakage_model: LeakageModel) -> None:
self.leakage_model = leakage_model
[docs]
def scalar_mult(self, scalar: int, point: Point) -> Tuple[Point, Trace]:
if self.params is None:
raise ValueError("Missing DomainParameters")
with local(DefaultContext()) as ctx:
self.mult.init(self.params, point)
res_point = self.mult.multiply(scalar)
return res_point, self.get_trace(ctx)
[docs]
def generate(self) -> Tuple[Tuple[Mod, Point], Trace]:
if self.params is None:
raise ValueError("Missing DomainParameters")
with local(DefaultContext()) as ctx:
keygen = KeyGeneration(self.mult, self.params, False)
priv, pub = keygen.generate()
return (priv, pub), self.get_trace(ctx)
[docs]
def set_privkey(self, privkey: Mod) -> None:
self.privkey = privkey
[docs]
def set_pubkey(self, pubkey: Point) -> None:
self.pubkey = pubkey
[docs]
def ecdh(self, other_pubkey: Point, hash_algo=None) -> Tuple[bytes, Trace]:
if self.params is None:
raise ValueError("Missing DomainParameters")
if self.privkey is None:
raise ValueError("Missing privkey")
with local(DefaultContext()) as ctx:
ecdh = KeyAgreement(
self.mult, self.params, other_pubkey, self.privkey, hash_algo
)
shared_secret = ecdh.perform()
return shared_secret, self.get_trace(ctx)
[docs]
def ecdsa_sign(self, data: bytes, hash_algo=None) -> Tuple[SignatureResult, Trace]:
if self.params is None:
raise ValueError("Missing DomainParameters")
if self.privkey is None:
raise ValueError("Missing privkey")
with local(DefaultContext()) as ctx:
ecdsa = Signature(self.mult, self.params, self.mult.formulas["add"], self.pubkey, self.privkey, hash_algo) # type: ignore
signed_data = ecdsa.sign_data(data)
return signed_data, self.get_trace(ctx)
[docs]
def ecdsa_verify(
self, data: bytes, signature: SignatureResult, hash_algo=None
) -> Tuple[bool, Trace]:
if self.params is None:
raise ValueError
if self.pubkey is None:
raise ValueError("Missing pubkey")
with local(DefaultContext()) as ctx:
ecdsa = Signature(self.mult, self.params, self.mult.formulas["add"], self.pubkey, hash_algo) # type: ignore
verified = ecdsa.verify_data(signature, data)
return verified, self.get_trace(ctx)
[docs]
def debug(self):
return self.model.shortname, self.coords.name
[docs]
def connect(self):
pass
[docs]
def disconnect(self):
pass
[docs]
def set_trigger(self):
pass