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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
"""Provides "fake" formulas."""
from abc import ABC
from typing import Any, Tuple
from functools import cache
from public import public
from pyecsca.ec.formula.base import (
AdditionFormula,
FormulaAction,
Formula,
DoublingFormula,
TriplingFormula,
LadderFormula,
NegationFormula,
ScalingFormula,
DifferentialAdditionFormula,
)
from pyecsca.ec.mod import Mod, Undefined
from pyecsca.ec.point import Point
@public
class FakeFormula(Formula, ABC):
"""
No matter what the input point is, it just returns the right amount of FakePoints.
Useful for computing with the scalar multipliers without having concrete formulas
and points (for example, to get the addition chain via the :py:class:`~.MultipleContext`).
"""
def __init__(self, coordinate_model):
# TODO: This is missing all of the other attributes
self.coordinate_model = coordinate_model
self.code = []
def __call__(self, field: int, *points: Any, **params: Mod) -> Tuple[Any, ...]:
with FormulaAction(self, *points, **params) as action:
for i in range(self.num_outputs):
res = FakePoint(self.coordinate_model)
action.output_points.append(res)
return action.exit(tuple(action.output_points))
@public
class FakeAdditionFormula(FakeFormula, AdditionFormula):
name = "fake"
@public
class FakeDoublingFormula(FakeFormula, DoublingFormula):
name = "fake"
@public
class FakeTriplingFormula(FakeFormula, TriplingFormula):
name = "fake"
@public
class FakeNegationFormula(FakeFormula, NegationFormula):
name = "fake"
@public
class FakeScalingFormula(FakeFormula, ScalingFormula):
name = "fake"
@public
class FakeDifferentialAdditionFormula(FakeFormula, DifferentialAdditionFormula):
name = "fake"
@public
class FakeLadderFormula(FakeFormula, LadderFormula):
name = "fake"
@cache
def _fake_coords(model):
"""Return a dictionary of fake coordinates for the given model."""
return {key: Undefined() for key in model.variables}
@public
class FakePoint(Point):
"""Just a fake point."""
def __init__(self, model): # noqa: We initialize everything here
self.coordinate_model = model
@property
def field(self):
return 0
@field.setter
def field(self, value):
"""Setter for field, does nothing."""
pass
@property
def coords(self):
return _fake_coords(self.coordinate_model)
@coords.setter
def coords(self, value):
"""Setter for coordinates, does nothing."""
pass
def __str__(self):
return f"FakePoint{id(self)}"
def __repr__(self):
return str(self)
def __eq__(self, other):
return self is other
def __hash__(self):
return id(self)
def __copy__(self):
return self
def __deepcopy__(self, memo):
return self
def __getstate__(self):
return {"model": self.coordinate_model}
def __setstate__(self, state):
self.coordinate_model = state["model"]
|