aboutsummaryrefslogtreecommitdiff
path: root/pyecsca/ec/point.py
blob: 052165f17b9cde53738406a4454afc2df5ab7c2e (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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
from copy import copy
from public import public
from typing import Mapping

from .coordinates import CoordinateModel, AffineCoordinateModel
from .mod import Mod
from .op import CodeOp


@public
class Point(object):
    coordinate_model: CoordinateModel
    coords: Mapping[str, Mod]

    def __init__(self, model: CoordinateModel, **coords: Mod):
        if not set(model.variables) == set(coords.keys()):
            raise ValueError
        self.coordinate_model = model
        self.coords = coords

    def to_affine(self):
        if isinstance(self.coordinate_model, AffineCoordinateModel):
            return copy(self)
        ops = set()
        for s in self.coordinate_model.satisfying:
            try:
                ops.add(CodeOp(s))
            except:
                pass
        affine_model = AffineCoordinateModel(self.coordinate_model.curve_model)
        # TODO: just fill in with undefined
        if not set(map(lambda x: x.result, ops)).issuperset(affine_model.variables):
            raise NotImplementedError
        result = {}
        for op in ops:
            result[op.result] = op(**self.coords)
        return Point(affine_model, **result)

    @staticmethod
    def from_affine(affine_point):
        # TODO
        pass

    def equals(self, other):
        if not isinstance(other, Point):
            return False
        if self.coordinate_model.curve_model != other.coordinate_model.curve_model:
            return False
        return self.to_affine() == other.to_affine()

    def __eq__(self, other):
        if not isinstance(other, Point):
            return False
        if self.coordinate_model != other.coordinate_model:
            return False
        return self.coords == other.coords

    def __str__(self):
        args = ", ".join([f"{key}={val}" for key, val in self.coords.items()])
        return f"[{args}]"

    def __repr__(self):
        return f"Point([{str(self)}] in {self.coordinate_model})"


@public
class InfinityPoint(Point):

    def __init__(self, model: CoordinateModel):
        self.coordinate_model = model
        self.coords = {}

    def to_affine(self):
        return InfinityPoint(AffineCoordinateModel(self.coordinate_model.curve_model))

    @staticmethod
    def from_affine(affine_point):
        raise NotImplementedError

    def equals(self, other):
        return self == other

    def __eq__(self, other):
        if type(other) is not InfinityPoint:
            return False
        else:
            return self.coordinate_model == other.coordinate_model

    def __str__(self):
        return "Infinity"

    def __repr__(self):
        return f"InfinityPoint({self.coordinate_model})"