aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJ08nY2023-10-04 16:40:31 +0200
committerJ08nY2023-10-04 16:40:31 +0200
commitbff6dc1e9777000d9a1867ce3f0863cbb3900896 (patch)
tree75c3c972853b94ddf3a19536c899e26ca4b63479
parent1c25c3fa1b752c170092d0fff34e1a14f363c602 (diff)
downloadpyecsca-bff6dc1e9777000d9a1867ce3f0863cbb3900896.tar.gz
pyecsca-bff6dc1e9777000d9a1867ce3f0863cbb3900896.tar.zst
pyecsca-bff6dc1e9777000d9a1867ce3f0863cbb3900896.zip
More docs for scalarmults.
-rw-r--r--docs/index.rst95
-rw-r--r--docs/references.rst1
-rw-r--r--pyecsca/ec/mult/__init__.py1
-rw-r--r--pyecsca/ec/mult/base.py24
-rw-r--r--pyecsca/ec/mult/binary.py29
-rw-r--r--pyecsca/ec/mult/comb.py1
-rw-r--r--pyecsca/ec/mult/ladder.py39
-rw-r--r--pyecsca/ec/mult/naf.py31
-rw-r--r--pyecsca/ec/mult/window.py17
-rw-r--r--pyecsca/sca/re/rpa.py5
-rw-r--r--pyecsca/sca/re/zvp.py5
11 files changed, 178 insertions, 70 deletions
diff --git a/docs/index.rst b/docs/index.rst
index e3448a5..19cf666 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -66,13 +66,13 @@ It is currently in an alpha stage of development and thus only provides:
.. grid-item-card:: Codegen
- The `codegen <https://github.com/J08nY/pyecsca-codegen>`_ package contains
- the code generation functionality.
+ The `codegen <https://github.com/J08nY/pyecsca-codegen>`_ package contains
+ the code generation functionality.
.. grid-item-card:: Notebook
- The `notebook <https://github.com/J08nY/pyecsca-notebook>`_ repository contains
- example notebooks that showcase functionality of the toolkit.
+ The `notebook <https://github.com/J08nY/pyecsca-notebook>`_ repository contains
+ example notebooks that showcase functionality of the toolkit.
:fas:`book` Notebooks
@@ -121,66 +121,66 @@ Requirements
.. dropdown:: General
- - Numpy_
- - Scipy_
- - sympy_
- - atpublic_
- - fastdtw_
- - asn1crypto_
- - h5py_
- - holoviews_
- - bokeh_
- - datashader_
- - matplotlib_
- - xarray_
- - astunparse_
- - numba_
+ - Numpy_
+ - Scipy_
+ - sympy_
+ - atpublic_
+ - fastdtw_
+ - asn1crypto_
+ - h5py_
+ - holoviews_
+ - bokeh_
+ - datashader_
+ - matplotlib_
+ - xarray_
+ - astunparse_
+ - numba_
- - **Optionally**:
+ - **Optionally**:
- - **Oscilloscope support:**
+ - **Oscilloscope support:**
- - picosdk_
- - picoscope_
- - chipwhisperer_
- - **Smartcard support:**
+ - picosdk_
+ - picoscope_
+ - chipwhisperer_
+ - **Smartcard support:**
- - pyscard_
- - **LEIA support:**
+ - pyscard_
+ - **LEIA support:**
- - leia_
- - **Faster arithmetic:**
+ - leia_
+ - **Faster arithmetic:**
- - gmpy2_ (and also GMP library)
+ - gmpy2_ (and also GMP library)
- *pyecsca* contains data from the `Explicit-Formulas Database`_ by Daniel J. Bernstein and Tanja Lange.
- The data was partially changed, to make working with it easier. It is available on Github at `crocs-muni/efd`_.
+ *pyecsca* contains data from the `Explicit-Formulas Database`_ by Daniel J. Bernstein and Tanja Lange.
+ The data was partially changed, to make working with it easier. It is available on Github at `crocs-muni/efd`_.
- It uses `ChipWhisperer`_ as one of its targets. It also supports working with Riscure_ Inspector trace sets, which are of a proprietary format.
+ It uses `ChipWhisperer`_ as one of its targets. It also supports working with Riscure_ Inspector trace sets, which are of a proprietary format.
.. dropdown:: Testing & Development
- See the Makefile for tests, performance measurement, codestyle and type checking commands.
- Use black_ for code-formatting.
+ See the Makefile for tests, performance measurement, codestyle and type checking commands.
+ Use black_ for code-formatting.
- - pytest_
- - mypy_
- - flake8_
- - coverage_
- - interrogate_
- - pyinstrument_
- - pre-commit_
- - black_
+ - pytest_
+ - mypy_
+ - flake8_
+ - coverage_
+ - interrogate_
+ - pyinstrument_
+ - pre-commit_
+ - black_
.. dropdown:: Docs
- - sphinx_
- - sphinx-autodoc-typehints_
- - nbsphinx_
- - sphinx-paramlinks_
- - sphinx-design_
+ - sphinx_
+ - sphinx-autodoc-typehints_
+ - nbsphinx_
+ - sphinx-paramlinks_
+ - sphinx-design_
License
=======
@@ -230,7 +230,6 @@ Development was supported by the Masaryk University grant `MUNI/C/1707/2018 <htt
.. _numba: https://numba.pydata.org/
.. _picosdk: https://github.com/picotech/picosdk-python-wrappers/
.. _picoscope: https://github.com/colinoflynn/pico-python
-.. _chipwhisperer: https://github.com/newaetech/chipwhisperer
.. _pyscard: https://pyscard.sourceforge.io/
.. _leia: https://pypi.org/project/smartleia/
.. _gmpy2: https://gmpy2.readthedocs.io/
diff --git a/docs/references.rst b/docs/references.rst
index d215948..a805ce8 100644
--- a/docs/references.rst
+++ b/docs/references.rst
@@ -13,3 +13,4 @@ References
.. [EPA] Exceptional procedure attack on elliptic curve cryptosystems, https://doi.org/10.1007/3-540-36288-6_17
.. [FFD] A formula for disaster: a unified approach to elliptic curve special-point-based attacks, https://eprint.iacr.org/2021/1595.pdf
.. [MT1991] Mazur, B., & Tate, J. (1991). The `p`-adic sigma function. Duke Mathematical Journal, 62 (3), 663-688.
+.. [CO2002] Jean-Sébastien Coron. Resistance against Differential Power Analysis for Elliptic Curve Cryptosystems, https://link.springer.com/chapter/10.1007/3-540-48059-5_25
diff --git a/pyecsca/ec/mult/__init__.py b/pyecsca/ec/mult/__init__.py
index 419e5ff..e032913 100644
--- a/pyecsca/ec/mult/__init__.py
+++ b/pyecsca/ec/mult/__init__.py
@@ -2,6 +2,7 @@
from .base import *
from .binary import *
+from .comb import *
from .ladder import *
from .naf import *
from .window import *
diff --git a/pyecsca/ec/mult/base.py b/pyecsca/ec/mult/base.py
index a0584d1..5bfef73 100644
--- a/pyecsca/ec/mult/base.py
+++ b/pyecsca/ec/mult/base.py
@@ -1,3 +1,6 @@
+"""Provides (mostly abstract) base classes for scalar multipliers, enums used to specify their parameters
+and actions used in them."""
+
from abc import ABC, abstractmethod
from copy import copy
from enum import Enum
@@ -71,9 +74,9 @@ class ScalarMultiplier(ABC):
"""
requires: ClassVar[Set[Type]] # Type[Formula] but mypy has a false positive
- """The set of formulas that the multiplier requires."""
+ """The set of formula types that the multiplier requires."""
optionals: ClassVar[Set[Type]] # Type[Formula] but mypy has a false positive
- """The optional set of formulas that the multiplier can use."""
+ """The optional set of formula types that the multiplier can use."""
short_circuit: bool
"""Whether the formulas will short-circuit upon input of the point at infinity."""
formulas: Mapping[str, Formula]
@@ -93,9 +96,23 @@ class ScalarMultiplier(ABC):
)
!= 1
):
- raise ValueError
+ raise ValueError("Formulas need to belong to the same coordinate model.")
self.short_circuit = short_circuit
self.formulas = {k: v for k, v in formulas.items() if v is not None}
+ found_required = set()
+ for formula in self.formulas.values():
+ for required in self.requires:
+ if isinstance(formula, required):
+ found_required.add(required)
+ break
+ else:
+ for optional in self.optionals:
+ if isinstance(formula, optional):
+ break
+ else:
+ raise ValueError("Not required or optional formulas provided.")
+ if found_required != self.requires:
+ raise ValueError("Required formulas missing.")
def _add(self, one: Point, other: Point) -> Point:
if "add" not in self.formulas:
@@ -216,6 +233,7 @@ class AccumulatorMultiplier(ScalarMultiplier, ABC):
:param accumulation_order: The order of accumulation of points.
"""
accumulation_order: AccumulationOrder
+ """The order of accumulation of points."""
def __init__(self, *args, accumulation_order: AccumulationOrder = AccumulationOrder.PeqPR, **kwargs):
super().__init__(*args, **kwargs)
diff --git a/pyecsca/ec/mult/binary.py b/pyecsca/ec/mult/binary.py
index 6145828..905646c 100644
--- a/pyecsca/ec/mult/binary.py
+++ b/pyecsca/ec/mult/binary.py
@@ -1,3 +1,4 @@
+"""Provides binary scalar multipliers (LTR and RTL), that process the scalar as-is, bit-by-bit."""
from abc import ABC
from copy import copy
from typing import Optional
@@ -19,16 +20,24 @@ class DoubleAndAddMultiplier(AccumulatorMultiplier, ScalarMultiplier, ABC):
"""
Classic double and add scalar multiplication algorithm.
+ .. note::
+ This is an ABC, you should use the `LTRMultiplier` and `RTLMultiplier` classes.
+
+ :param short_circuit: Whether the use of formulas will be guarded by short-circuit on inputs
+ of the point at infinity.
:param always: Whether the double and add always method is used.
:param direction: Whether it is LTR or RTL.
:param accumulation_order: The order of accumulation of points.
- :param complete: (Only for LTR, always false for RTL) Whether it starts processing at full order-bit-length.
+ :param complete: Whether it starts processing at full order-bit-length.
"""
requires = {AdditionFormula, DoublingFormula}
optionals = {ScalingFormula}
always: bool
+ """Whether the double and add always method is used."""
direction: ProcessingDirection
+ """Whether it is LTR or RTL."""
complete: bool
+ """Whether it starts processing at full order-bit-length."""
def __init__(
self,
@@ -112,6 +121,12 @@ class DoubleAndAddMultiplier(AccumulatorMultiplier, ScalarMultiplier, ABC):
class LTRMultiplier(DoubleAndAddMultiplier):
"""
Classic double and add scalar multiplication algorithm, that scans the scalar left-to-right (msb to lsb).
+
+ :param short_circuit: Whether the use of formulas will be guarded by short-circuit on inputs
+ of the point at infinity.
+ :param always: Whether the double and add always method is used.
+ :param accumulation_order: The order of accumulation of points.
+ :param complete: Whether it starts processing at full order-bit-length.
"""
def __init__(
@@ -133,6 +148,12 @@ class LTRMultiplier(DoubleAndAddMultiplier):
class RTLMultiplier(DoubleAndAddMultiplier):
"""
Classic double and add scalar multiplication algorithm, that scans the scalar right-to-left (lsb to msb).
+
+ :param short_circuit: Whether the use of formulas will be guarded by short-circuit on inputs
+ of the point at infinity.
+ :param always: Whether the double and add always method is used.
+ :param accumulation_order: The order of accumulation of points.
+ :param complete: Whether it starts processing at full order-bit-length.
"""
def __init__(
@@ -155,10 +176,10 @@ class CoronMultiplier(ScalarMultiplier):
"""
Coron's double and add resistant against SPA.
- From:
- **Resistance against Differential Power Analysis for Elliptic Curve Cryptosystems**
+ From [CO2002]_.
- https://link.springer.com/content/pdf/10.1007/3-540-48059-5_25.pdf
+ :param short_circuit: Whether the use of formulas will be guarded by short-circuit on inputs
+ of the point at infinity.
"""
requires = {AdditionFormula, DoublingFormula}
diff --git a/pyecsca/ec/mult/comb.py b/pyecsca/ec/mult/comb.py
new file mode 100644
index 0000000..f25e177
--- /dev/null
+++ b/pyecsca/ec/mult/comb.py
@@ -0,0 +1 @@
+"""Provides Comb-like scalar multipliers, such as BGMW or Lim-Lee.""" \ No newline at end of file
diff --git a/pyecsca/ec/mult/ladder.py b/pyecsca/ec/mult/ladder.py
index ad90730..2fc1244 100644
--- a/pyecsca/ec/mult/ladder.py
+++ b/pyecsca/ec/mult/ladder.py
@@ -1,3 +1,4 @@
+"""Provides ladder-based scalar multipliers, either using the ladder formula, or (diffadd, dbl) or (add, dbl)."""
from copy import copy
from typing import Optional
from public import public
@@ -15,11 +16,20 @@ from ..point import Point
@public
class LadderMultiplier(ScalarMultiplier):
- """Montgomery ladder multiplier, using a three input, two output ladder formula."""
+ """
+ Montgomery ladder multiplier, using a three input, two output ladder formula.
+
+ Optionally takes a doubling formula, and if `complete` is false, it requires one.
+
+ :param short_circuit: Whether the use of formulas will be guarded by short-circuit on inputs
+ of the point at infinity.
+ :param complete: Whether it starts processing at full order-bit-length.
+ """
requires = {LadderFormula}
optionals = {DoublingFormula, ScalingFormula}
complete: bool
+ """Whether it starts processing at full order-bit-length."""
def __init__(
self,
@@ -42,6 +52,9 @@ class LadderMultiplier(ScalarMultiplier):
return False
return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.complete == other.complete
+ def __repr__(self):
+ return f"{self.__class__.__name__}({tuple(self.formulas.values())}, short_circuit={self.short_circuit}, complete={self.complete})"
+
def multiply(self, scalar: int) -> Point:
if not self._initialized:
raise ValueError("ScalarMultiplier not initialized.")
@@ -69,11 +82,18 @@ class LadderMultiplier(ScalarMultiplier):
@public
class SimpleLadderMultiplier(ScalarMultiplier):
- """Montgomery ladder multiplier, using addition and doubling formulas."""
+ """
+ Montgomery ladder multiplier, using addition and doubling formulas.
+
+ :param short_circuit: Whether the use of formulas will be guarded by short-circuit on inputs
+ of the point at infinity.
+ :param complete: Whether it starts processing at full order-bit-length.
+ """
requires = {AdditionFormula, DoublingFormula}
optionals = {ScalingFormula}
complete: bool
+ """Whether it starts processing at full order-bit-length."""
def __init__(
self,
@@ -94,6 +114,9 @@ class SimpleLadderMultiplier(ScalarMultiplier):
return False
return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.complete == other.complete
+ def __repr__(self):
+ return f"{self.__class__.__name__}({tuple(self.formulas.values())}, short_circuit={self.short_circuit}, complete={self.complete})"
+
def multiply(self, scalar: int) -> Point:
if not self._initialized:
raise ValueError("ScalarMultiplier not initialized.")
@@ -120,11 +143,18 @@ class SimpleLadderMultiplier(ScalarMultiplier):
@public
class DifferentialLadderMultiplier(ScalarMultiplier):
- """Montgomery ladder multiplier, using differential addition and doubling formulas."""
+ """
+ Montgomery ladder multiplier, using differential addition and doubling formulas.
+
+ :param short_circuit: Whether the use of formulas will be guarded by short-circuit on inputs
+ of the point at infinity.
+ :param complete: Whether it starts processing at full order-bit-length.
+ """
requires = {DifferentialAdditionFormula, DoublingFormula}
optionals = {ScalingFormula}
complete: bool
+ """Whether it starts processing at full order-bit-length."""
def __init__(
self,
@@ -145,6 +175,9 @@ class DifferentialLadderMultiplier(ScalarMultiplier):
return False
return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.complete == other.complete
+ def __repr__(self):
+ return f"{self.__class__.__name__}({tuple(self.formulas.values())}, short_circuit={self.short_circuit}, complete={self.complete})"
+
def multiply(self, scalar: int) -> Point:
if not self._initialized:
raise ValueError("ScalarMultiplier not initialized.")
diff --git a/pyecsca/ec/mult/naf.py b/pyecsca/ec/mult/naf.py
index 1cec8b0..9304475 100644
--- a/pyecsca/ec/mult/naf.py
+++ b/pyecsca/ec/mult/naf.py
@@ -1,3 +1,4 @@
+"""Provides scalar multipliers based on the Non Adjacent Form (NAF) recoding."""
from copy import copy
from typing import Optional, List, MutableMapping
from public import public
@@ -17,7 +18,14 @@ from ..scalar import naf, wnaf
@public
class BinaryNAFMultiplier(AccumulatorMultiplier, ScalarMultiplier):
- """Binary NAF (Non Adjacent Form) multiplier."""
+ """
+ Binary NAF (Non Adjacent Form) multiplier.
+
+ :param short_circuit: Whether the use of formulas will be guarded by short-circuit on inputs
+ of the point at infinity.
+ :param direction: Whether it is LTR or RTL.
+ :param accumulation_order: The order of accumulation of points.
+ """
requires = {AdditionFormula, DoublingFormula, NegationFormula}
optionals = {ScalingFormula}
@@ -45,7 +53,10 @@ class BinaryNAFMultiplier(AccumulatorMultiplier, ScalarMultiplier):
def __eq__(self, other):
if not isinstance(other, BinaryNAFMultiplier):
return False
- return self.formulas == other.formulas and self.short_circuit == other.short_circuit
+ return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.direction == other.direction and self.accumulation_order == other.accumulation_order
+
+ def __repr__(self):
+ return f"{self.__class__.__name__}({tuple(self.formulas.values())}, short_circuit={self.short_circuit}, direction={self.direction}, accumulation_order={self.accumulation_order})"
def init(self, params: DomainParameters, point: Point):
with PrecomputationAction(params, point):
@@ -93,14 +104,25 @@ class BinaryNAFMultiplier(AccumulatorMultiplier, ScalarMultiplier):
@public
class WindowNAFMultiplier(AccumulatorMultiplier, ScalarMultiplier):
- """Window NAF (Non Adjacent Form) multiplier, left-to-right."""
+ """
+ Window NAF (Non Adjacent Form) multiplier, left-to-right.
+
+ :param short_circuit: Whether the use of formulas will be guarded by short-circuit on inputs
+ of the point at infinity.
+ :param width: The width of the window.
+ :param accumulation_order: The order of accumulation of points.
+ :param precompute_negation: Whether to precompute the negation of the precomputed points as well.
+ It is computed on the fly otherwise.
+ """
requires = {AdditionFormula, DoublingFormula, NegationFormula}
optionals = {ScalingFormula}
_points: MutableMapping[int, Point]
_points_neg: MutableMapping[int, Point]
precompute_negation: bool = False
+ """Whether to precompute the negation of the precomputed points as well."""
width: int
+ """The width of the window."""
def __init__(
self,
@@ -127,6 +149,9 @@ class WindowNAFMultiplier(AccumulatorMultiplier, ScalarMultiplier):
return False
return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.width == other.width and self.precompute_negation == other.precompute_negation and self.accumulation_order == other.accumulation_order
+ def __repr__(self):
+ return f"{self.__class__.__name__}({tuple(self.formulas.values())}, short_circuit={self.short_circuit}, precompute_negation={self.precompute_negation}, accumulation_order={self.accumulation_order})"
+
def init(self, params: DomainParameters, point: Point):
with PrecomputationAction(params, point):
super().init(params, point)
diff --git a/pyecsca/ec/mult/window.py b/pyecsca/ec/mult/window.py
index 8b1ae2c..3ee8c50 100644
--- a/pyecsca/ec/mult/window.py
+++ b/pyecsca/ec/mult/window.py
@@ -1,3 +1,4 @@
+"""Provides sliding window and fixed window scalar multipliers (including m-ary, for non power-of-2 m)."""
from copy import copy
from typing import Optional, MutableMapping
from public import public
@@ -49,6 +50,9 @@ class SlidingWindowMultiplier(AccumulatorMultiplier, ScalarMultiplier):
return False
return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.width == other.width and self.recoding_direction == other.recoding_direction and self.accumulation_order == other.accumulation_order
+ def __repr__(self):
+ return f"{self.__class__.__name__}({tuple(self.formulas.values())}, short_circuit={self.short_circuit}, width={self.width}, recoding_direction={self.recoding_direction}, accumulation_order={self.accumulation_order})"
+
def init(self, params: DomainParameters, point: Point):
with PrecomputationAction(params, point):
super().init(params, point)
@@ -81,7 +85,15 @@ class SlidingWindowMultiplier(AccumulatorMultiplier, ScalarMultiplier):
@public
class FixedWindowLTRMultiplier(AccumulatorMultiplier, ScalarMultiplier):
- """Like LTRMultiplier, but not binary, but m-ary."""
+ """
+ Like LTRMultiplier, but m-ary, not binary.
+
+ For `m` a power-of-2 this is a fixed window multiplier
+ that works on `log_2(m)` wide windows and uses only doublings
+ to perform the multiplication-by-m between each window addition.
+
+ For other `m` values, this is the m-ary multiplier.
+ """
requires = {AdditionFormula, DoublingFormula}
optionals = {ScalingFormula}
@@ -114,6 +126,9 @@ class FixedWindowLTRMultiplier(AccumulatorMultiplier, ScalarMultiplier):
return False
return self.formulas == other.formulas and self.short_circuit == other.short_circuit and self.m == other.m and self.accumulation_order == other.accumulation_order
+ def __repr__(self):
+ return f"{self.__class__.__name__}({tuple(self.formulas.values())}, short_circuit={self.short_circuit}, m={self.m}, accumulation_order={self.accumulation_order})"
+
def init(self, params: DomainParameters, point: Point):
with PrecomputationAction(params, point):
super().init(params, point)
diff --git a/pyecsca/sca/re/rpa.py b/pyecsca/sca/re/rpa.py
index 5a44a0f..5459ff2 100644
--- a/pyecsca/sca/re/rpa.py
+++ b/pyecsca/sca/re/rpa.py
@@ -1,8 +1,5 @@
"""
-Provides functionality inspired by the Refined-Power Analysis attack by Goubin.
-
- A Refined Power-Analysis Attack on Elliptic Curve Cryptosystems, Louis Goubin, PKC '03
- `<https://dl.acm.org/doi/10.5555/648120.747060>`_
+Provides functionality inspired by the Refined-Power Analysis attack by Goubin [RPA]_.
"""
from public import public
from typing import MutableMapping, Optional, Callable, List
diff --git a/pyecsca/sca/re/zvp.py b/pyecsca/sca/re/zvp.py
index 53a38a2..7e3d790 100644
--- a/pyecsca/sca/re/zvp.py
+++ b/pyecsca/sca/re/zvp.py
@@ -1,8 +1,5 @@
"""
-Provides functionality inspired by the Zero-value point attack.
-
- Zero-Value Point Attacks on Elliptic Curve Cryptosystem, Toru Akishita & Tsuyoshi Takagi , ISC '03
- `<https://doi.org/10.1007/10958513_17>`_
+Provides functionality inspired by the Zero-value point attack [ZVP]_.
Implements ZVP point construction from [FFD]_.
"""