aboutsummaryrefslogtreecommitdiff
path: root/pyecsca/ec/curve.py
blob: 3c0b200ac9c9aa5d6bd98e83651df6cda6eec5f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from typing import MutableMapping, Union

from public import public

from .coordinates import CoordinateModel
from .mod import Mod
from .model import CurveModel
from .point import Point


@public
class EllipticCurve(object):
    model: CurveModel
    coordinate_model: CoordinateModel
    prime: int
    parameters: MutableMapping[str, Mod]

    def __init__(self, model: CurveModel, coordinate_model: CoordinateModel,
                 prime: int, parameters: MutableMapping[str, Union[Mod, int]]):
        if coordinate_model not in model.coordinates.values():
            raise ValueError
        if set(model.parameter_names).symmetric_difference(parameters.keys()):
            raise ValueError
        self.model = model
        self.coordinate_model = coordinate_model
        self.prime = prime
        self.parameters = {}
        for name, value in parameters.items():
            if isinstance(value, Mod):
                if value.n != prime:
                    raise ValueError
            else:
                value = Mod(value, prime)
            self.parameters[name] = value

    def is_on_curve(self, point: Point) -> bool:
        if point.coordinate_model.curve_model != self.model:
            return False
        loc = {**self.parameters, **point.to_affine().coords}
        return eval(compile(self.model.equation, "", mode="eval"), loc)

    def __repr__(self):
        params = ", ".join((f"{key}={val}" for key, val in self.parameters.items()))
        return f"EllipticCurve([{params}] on {self.model} using {self.coordinate_model})"