aboutsummaryrefslogtreecommitdiffhomepage
path: root/pyecsca/ec
diff options
context:
space:
mode:
authorJ08nY2025-03-13 19:38:06 +0100
committerJ08nY2025-03-13 19:38:06 +0100
commiteccc58127b4c0c10f50e4d05e699d3585391e8a1 (patch)
tree5e3f96febfc3051778d2b588484bacfc6d9d148c /pyecsca/ec
parent314d7c78bb91ab7579c41fe9dc91d238e04c8fe1 (diff)
downloadpyecsca-eccc58127b4c0c10f50e4d05e699d3585391e8a1.tar.gz
pyecsca-eccc58127b4c0c10f50e4d05e699d3585391e8a1.tar.zst
pyecsca-eccc58127b4c0c10f50e4d05e699d3585391e8a1.zip
Add "bits" param to scalarmults to have control over their range.
Diffstat (limited to 'pyecsca/ec')
-rw-r--r--pyecsca/ec/countermeasures.py8
-rw-r--r--pyecsca/ec/mult/base.py6
-rw-r--r--pyecsca/ec/mult/binary.py4
-rw-r--r--pyecsca/ec/mult/comb.py14
-rw-r--r--pyecsca/ec/mult/fake.py2
-rw-r--r--pyecsca/ec/mult/fixed.py12
-rw-r--r--pyecsca/ec/mult/ladder.py7
-rw-r--r--pyecsca/ec/mult/naf.py8
-rw-r--r--pyecsca/ec/mult/window.py14
9 files changed, 42 insertions, 33 deletions
diff --git a/pyecsca/ec/countermeasures.py b/pyecsca/ec/countermeasures.py
index 8a479b6..19afb06 100644
--- a/pyecsca/ec/countermeasures.py
+++ b/pyecsca/ec/countermeasures.py
@@ -70,6 +70,11 @@ class GroupScalarRandomization(ScalarMultiplierCountermeasure):
super().__init__(mult)
self.rand_bits = rand_bits
+ def init(self, params: DomainParameters, point: Point):
+ self.params = params
+ self.point = point
+ self.mult.init(self.params, self.point, bits=params.full_order.bit_length() + self.rand_bits)
+
def multiply(self, scalar: int) -> Point:
if self.params is None or self.point is None:
raise ValueError("Not initialized.")
@@ -189,8 +194,7 @@ class EuclideanSplitting(ScalarMultiplierCountermeasure):
if self.params is None or self.point is None:
raise ValueError("Not initialized.")
with ScalarMultiplicationAction(self.point, self.params, scalar) as action:
- order = self.params.order
- half_bits = order.bit_length() // 2
+ half_bits = self.params.order.bit_length() // 2
r = Mod.random(1 << half_bits)
R = self.mult.multiply(int(r))
diff --git a/pyecsca/ec/mult/base.py b/pyecsca/ec/mult/base.py
index f7a8c5b..15f2fd5 100644
--- a/pyecsca/ec/mult/base.py
+++ b/pyecsca/ec/mult/base.py
@@ -87,6 +87,7 @@ class ScalarMultiplier(ABC):
"""All formulas the multiplier was initialized with."""
_params: DomainParameters
_point: Point
+ _bits: int
_initialized: bool = False
def __init__(self, short_circuit: bool = True, **formulas: Optional[Formula]):
@@ -202,7 +203,7 @@ class ScalarMultiplier(ABC):
def __repr__(self):
return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit})"
- def init(self, params: DomainParameters, point: Point):
+ def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None):
"""
Initialize the scalar multiplier with :paramref:`~.init.params` and a :paramref:`~.init.point`.
@@ -211,6 +212,8 @@ class ScalarMultiplier(ABC):
:param params: The domain parameters to initialize the multiplier with.
:param point: The point to initialize the multiplier with.
+ :param bits: The number of bits to use in the scalar multiplication (i.e. no scalar will be larger than 2^bits).
+ The default is the bit length of the full order of the curve (including cofactor).
"""
coord_model = set(self.formulas.values()).pop().coordinate_model
if (
@@ -222,6 +225,7 @@ class ScalarMultiplier(ABC):
)
self._params = params
self._point = point
+ self._bits = bits if bits is not None else params.full_order.bit_length()
self._initialized = True
@abstractmethod
diff --git a/pyecsca/ec/mult/binary.py b/pyecsca/ec/mult/binary.py
index 5b6bed7..f0cb5ac 100644
--- a/pyecsca/ec/mult/binary.py
+++ b/pyecsca/ec/mult/binary.py
@@ -94,7 +94,7 @@ class DoubleAndAddMultiplier(AccumulatorMultiplier, ScalarMultiplier, ABC):
if self.complete:
q = self._point
r = copy(self._params.curve.neutral)
- top = self._params.order.bit_length() - 1
+ top = self._bits - 1
else:
q = copy(self._point)
r = copy(self._point)
@@ -112,7 +112,7 @@ class DoubleAndAddMultiplier(AccumulatorMultiplier, ScalarMultiplier, ABC):
q = self._point
r = copy(self._params.curve.neutral)
if self.complete:
- top = self._params.order.bit_length()
+ top = self._bits
else:
top = scalar.bit_length()
for _ in range(top):
diff --git a/pyecsca/ec/mult/comb.py b/pyecsca/ec/mult/comb.py
index 35d1678..1a6c0c2 100644
--- a/pyecsca/ec/mult/comb.py
+++ b/pyecsca/ec/mult/comb.py
@@ -85,10 +85,10 @@ class BGMWMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMultiplier)
def __repr__(self):
return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, width={self.width}, direction={self.direction.name}, accumulation_order={self.accumulation_order.name})"
- def init(self, params: DomainParameters, point: Point):
+ def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None):
with PrecomputationAction(params, point) as action:
- super().init(params, point)
- d = ceil(params.order.bit_length() / self.width)
+ super().init(params, point, bits)
+ d = ceil(self._bits / self.width)
self._points = {}
current_point = point
for i in range(d):
@@ -179,10 +179,10 @@ class CombMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMultiplier)
def __repr__(self):
return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, width={self.width}, accumulation_order={self.accumulation_order.name})"
- def init(self, params: DomainParameters, point: Point):
+ def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None):
with PrecomputationAction(params, point) as action:
- super().init(params, point)
- d = ceil(params.order.bit_length() / self.width)
+ super().init(params, point, bits)
+ d = ceil(self._bits / self.width)
base_points = {}
current_point = point
for i in range(self.width):
@@ -208,7 +208,7 @@ class CombMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMultiplier)
if scalar == 0:
return action.exit(copy(self._params.curve.neutral))
q = copy(self._params.curve.neutral)
- d = ceil(self._params.order.bit_length() / self.width)
+ d = ceil(self._bits / self.width)
recoded = convert_base(scalar, 2**d)
if len(recoded) != self.width:
recoded.extend([0] * (self.width - len(recoded)))
diff --git a/pyecsca/ec/mult/fake.py b/pyecsca/ec/mult/fake.py
index f89d622..391696b 100644
--- a/pyecsca/ec/mult/fake.py
+++ b/pyecsca/ec/mult/fake.py
@@ -9,7 +9,7 @@ from pyecsca.ec.params import DomainParameters
def fake_mult(mult_class: Type[ScalarMultiplier], mult_factory: Callable, params: DomainParameters) -> ScalarMultiplier:
"""
- Get a multiplier with FakeFormulas.
+ Get a multiplier with `FakeFormula`s.
:param mult_class: The class of the scalar multiplier to use.
:param mult_factory: A callable that takes the formulas and instantiates the multiplier.
diff --git a/pyecsca/ec/mult/fixed.py b/pyecsca/ec/mult/fixed.py
index 2c01648..070aaec 100644
--- a/pyecsca/ec/mult/fixed.py
+++ b/pyecsca/ec/mult/fixed.py
@@ -90,20 +90,20 @@ class FullPrecompMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMult
def __repr__(self):
return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, accumulation_order={self.accumulation_order.name}, always={self.always}, complete={self.complete})"
- def init(self, params: DomainParameters, point: Point):
+ def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None):
with PrecomputationAction(params, point) as action:
- super().init(params, point)
+ super().init(params, point, bits)
self._points = {}
current_point = point
- for i in range(params.order.bit_length() + 1):
+ for i in range(self._bits + 1):
self._points[i] = current_point
- if i != params.order.bit_length():
+ if i != self._bits:
current_point = self._dbl(current_point)
action.exit(self._points)
def _ltr(self, scalar: int) -> Point:
if self.complete:
- top = self._params.order.bit_length() - 1
+ top = self._bits - 1
else:
top = scalar.bit_length() - 1
r = copy(self._params.curve.neutral)
@@ -118,7 +118,7 @@ class FullPrecompMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMult
def _rtl(self, scalar: int) -> Point:
r = copy(self._params.curve.neutral)
if self.complete:
- top = self._params.order.bit_length()
+ top = self._bits
else:
top = scalar.bit_length()
for i in range(top):
diff --git a/pyecsca/ec/mult/ladder.py b/pyecsca/ec/mult/ladder.py
index 5f5d8a2..3635ada 100644
--- a/pyecsca/ec/mult/ladder.py
+++ b/pyecsca/ec/mult/ladder.py
@@ -12,6 +12,7 @@ from pyecsca.ec.formula import (
LadderFormula,
DifferentialAdditionFormula,
)
+from pyecsca.ec.params import DomainParameters
from pyecsca.ec.point import Point
@@ -87,7 +88,7 @@ class LadderMultiplier(ScalarMultiplier):
if self.complete:
p0 = copy(self._params.curve.neutral)
p1 = self._point
- top = self._params.full_order.bit_length() - 1
+ top = self._bits - 1
elif self.full:
p0 = copy(self._params.curve.neutral)
p1 = self._point
@@ -154,7 +155,7 @@ class SimpleLadderMultiplier(ScalarMultiplier):
if scalar == 0:
return action.exit(copy(self._params.curve.neutral))
if self.complete:
- top = self._params.full_order.bit_length() - 1
+ top = self._bits - 1
else:
top = scalar.bit_length() - 1
p0 = copy(self._params.curve.neutral)
@@ -232,7 +233,7 @@ class DifferentialLadderMultiplier(ScalarMultiplier):
if self.complete:
p0 = copy(self._params.curve.neutral)
p1 = copy(q)
- top = self._params.full_order.bit_length() - 1
+ top = self._bits - 1
elif self.full:
p0 = copy(self._params.curve.neutral)
p1 = copy(q)
diff --git a/pyecsca/ec/mult/naf.py b/pyecsca/ec/mult/naf.py
index 83dc0dc..b886552 100644
--- a/pyecsca/ec/mult/naf.py
+++ b/pyecsca/ec/mult/naf.py
@@ -81,9 +81,9 @@ class BinaryNAFMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMultip
def __repr__(self):
return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, direction={self.direction.name}, accumulation_order={self.accumulation_order.name})"
- def init(self, params: DomainParameters, point: Point):
+ def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None):
with PrecomputationAction(params, point) as action:
- super().init(params, point)
+ super().init(params, point, bits)
self._point_neg = self._neg(point)
action.exit({-1: self._point_neg})
@@ -195,9 +195,9 @@ class WindowNAFMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMultip
def __repr__(self):
return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, width={self.width}, precompute_negation={self.precompute_negation}, accumulation_order={self.accumulation_order.name})"
- def init(self, params: DomainParameters, point: Point):
+ def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None):
with PrecomputationAction(params, point) as action:
- super().init(params, point)
+ super().init(params, point, bits)
self._points = {}
self._points_neg = {}
current_point = point
diff --git a/pyecsca/ec/mult/window.py b/pyecsca/ec/mult/window.py
index 6fbee24..1a0ecec 100644
--- a/pyecsca/ec/mult/window.py
+++ b/pyecsca/ec/mult/window.py
@@ -90,9 +90,9 @@ class SlidingWindowMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMu
def __repr__(self):
return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, width={self.width}, recoding_direction={self.recoding_direction.name}, accumulation_order={self.accumulation_order.name})"
- def init(self, params: DomainParameters, point: Point):
+ def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None):
with PrecomputationAction(params, point) as action:
- super().init(params, point)
+ super().init(params, point, bits)
self._points = {}
current_point = point
double_point = self._dbl(point)
@@ -186,9 +186,9 @@ class FixedWindowLTRMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarM
def __repr__(self):
return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, m={self.m}, accumulation_order={self.accumulation_order.name})"
- def init(self, params: DomainParameters, point: Point):
+ def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None):
with PrecomputationAction(params, point) as action:
- super().init(params, point)
+ super().init(params, point, bits)
double_point = self._dbl(point)
self._points = {1: point, 2: double_point}
current_point = double_point
@@ -298,9 +298,9 @@ class WindowBoothMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMult
def __repr__(self):
return f"{self.__class__.__name__}({', '.join(map(str, self.formulas.values()))}, short_circuit={self.short_circuit}, width={self.width}, precompute_negation={self.precompute_negation}, accumulation_order={self.accumulation_order.name})"
- def init(self, params: DomainParameters, point: Point):
+ def init(self, params: DomainParameters, point: Point, bits: Optional[int] = None):
with PrecomputationAction(params, point) as actions:
- super().init(params, point)
+ super().init(params, point, bits)
double_point = self._dbl(point)
self._points = {1: point, 2: double_point}
if self.precompute_negation:
@@ -323,7 +323,7 @@ class WindowBoothMultiplier(AccumulatorMultiplier, PrecompMultiplier, ScalarMult
if scalar == 0:
return action.exit(copy(self._params.curve.neutral))
scalar_booth = booth_window(
- scalar, self.width, self._params.order.bit_length()
+ scalar, self.width, self._bits
)
q = copy(self._params.curve.neutral)
for val in scalar_booth: