diff options
| author | J08nY | 2023-08-31 18:14:16 +0200 |
|---|---|---|
| committer | J08nY | 2023-08-31 18:14:16 +0200 |
| commit | c341419b7a67fe2ac1367f56e0c5a91ab551fe05 (patch) | |
| tree | d53d0060ad862dabfaae9c43461c4e8ee85f19f0 /pyecsca/ec | |
| parent | b01f37d1dfaa447f53f44fb9ced1e7c39251d7de (diff) | |
| download | pyecsca-c341419b7a67fe2ac1367f56e0c5a91ab551fe05.tar.gz pyecsca-c341419b7a67fe2ac1367f56e0c5a91ab551fe05.tar.zst pyecsca-c341419b7a67fe2ac1367f56e0c5a91ab551fe05.zip | |
Add more curve model transformaations.
Thanks @vojtechsu.
Diffstat (limited to 'pyecsca/ec')
| -rw-r--r-- | pyecsca/ec/configuration.py | 2 | ||||
| -rw-r--r-- | pyecsca/ec/params.py | 2 | ||||
| -rw-r--r-- | pyecsca/ec/transformations.py | 171 |
3 files changed, 137 insertions, 38 deletions
diff --git a/pyecsca/ec/configuration.py b/pyecsca/ec/configuration.py index eb70ddc..7e90102 100644 --- a/pyecsca/ec/configuration.py +++ b/pyecsca/ec/configuration.py @@ -113,7 +113,7 @@ class Configuration: @public -def all_configurations(**kwargs) -> Generator[Configuration, Configuration, None]: +def all_configurations(**kwargs) -> Generator[Configuration, None, None]: """ Get all implementation configurations that match the given `kwargs`. diff --git a/pyecsca/ec/params.py b/pyecsca/ec/params.py index 19ed974..54656d4 100644 --- a/pyecsca/ec/params.py +++ b/pyecsca/ec/params.py @@ -238,6 +238,8 @@ def _create_params(curve, coords, infty): infinity_coords[coordinate] = value infinity = Point(coord_model, **infinity_coords) elliptic_curve = EllipticCurve(model, coord_model, field, infinity, params) # type: ignore[arg-type] + if "generator" not in curve: + raise ValueError("Cannot construct curve, missing generator.") affine = Point( AffineCoordinateModel(model), x=Mod(int(curve["generator"]["x"]["raw"], 16), field), diff --git a/pyecsca/ec/transformations.py b/pyecsca/ec/transformations.py index 894421f..de1915c 100644 --- a/pyecsca/ec/transformations.py +++ b/pyecsca/ec/transformations.py @@ -1,16 +1,18 @@ """Provides functions for transforming curves to different models.""" +from typing import Tuple, Generator + from public import public from sympy import FF, symbols, Poly from .coordinates import AffineCoordinateModel from .curve import EllipticCurve from .mod import Mod -from .model import ShortWeierstrassModel, MontgomeryModel, TwistedEdwardsModel +from .model import ShortWeierstrassModel, MontgomeryModel, TwistedEdwardsModel, EdwardsModel from .params import DomainParameters from .point import InfinityPoint, Point -def __M_map(params, param_names, map_parameters, map_point, model): +def __map(params, param_names, map_parameters, map_point, model): param_one = params.curve.parameters[param_names[0]] param_other = params.curve.parameters[param_names[1]] parameters = map_parameters(param_one, param_other) @@ -19,10 +21,11 @@ def __M_map(params, param_names, map_parameters, map_point, model): neutral = InfinityPoint(aff) else: neutral = map_point(param_one, param_other, params.curve.neutral, aff) + generator = map_point(param_one, param_other, params.generator, aff) curve = EllipticCurve(model, aff, params.curve.prime, neutral, parameters) return DomainParameters( curve, - map_point(param_one, param_other, params.generator, aff), + generator, params.order, params.cofactor, ) @@ -37,7 +40,7 @@ def M2SW(params: DomainParameters) -> DomainParameters: :return: The converted domain parameters. """ if not isinstance(params.curve.model, MontgomeryModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel + params.curve.coordinate_model, AffineCoordinateModel ): raise ValueError @@ -51,7 +54,7 @@ def M2SW(params: DomainParameters) -> DomainParameters: v = pt.y / B return Point(aff, x=u, y=v) - return __M_map( + return __map( params, ("a", "b"), map_parameters, map_point, ShortWeierstrassModel() ) @@ -65,7 +68,7 @@ def M2TE(params: DomainParameters) -> DomainParameters: :return: The converted domain parameters. """ if not isinstance(params.curve.model, MontgomeryModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel + params.curve.coordinate_model, AffineCoordinateModel ): raise ValueError @@ -79,7 +82,33 @@ def M2TE(params: DomainParameters) -> DomainParameters: v = (pt.x - 1) / (pt.x + 1) return Point(aff, x=u, y=v) - return __M_map(params, ("a", "b"), map_parameters, map_point, TwistedEdwardsModel()) + return __map(params, ("a", "b"), map_parameters, map_point, TwistedEdwardsModel()) + + +@public +def M2E(params: DomainParameters) -> DomainParameters: + """ + Convert a Montgomery curve to Edwards. + + :param params: The domain parameters to convert. + :return: The converted domain parameters. + """ + if not isinstance(params.curve.model, MontgomeryModel) or not isinstance( + params.curve.coordinate_model, AffineCoordinateModel + ): + raise ValueError + + def map_parameters(A, B): + c = (B / (A + 2)).sqrt() + d = (A ** 2 - 4) / (B ** 2) + return {"c": c, "d": d} + + def map_point(A, B, pt, aff): + u = pt.x / pt.y + v = ((pt.x - 1) / (pt.x + 1)) * (B / (A + 2)).sqrt() + return Point(aff, x=u, y=v) + + return __map(params, ("a", "b"), map_parameters, map_point, EdwardsModel()) @public @@ -91,7 +120,7 @@ def TE2M(params: DomainParameters) -> DomainParameters: :return: The converted domain parameters. """ if not isinstance(params.curve.model, TwistedEdwardsModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel + params.curve.coordinate_model, AffineCoordinateModel ): raise ValueError @@ -105,19 +134,64 @@ def TE2M(params: DomainParameters) -> DomainParameters: v = (1 + pt.y) / ((1 - pt.y) * pt.x) return Point(aff, x=u, y=v) - return __M_map(params, ("a", "d"), map_parameters, map_point, MontgomeryModel()) + return __map(params, ("a", "d"), map_parameters, map_point, MontgomeryModel()) @public -def SW2M(params: DomainParameters) -> DomainParameters: +def TE2E(params: DomainParameters) -> DomainParameters: """ - Convert a ShortWeierstrass curve to Montgomery. + Convert a TwistedEdwards curve to Edwards. :param params: The domain parameters to convert. :return: The converted domain parameters. """ + if not isinstance(params.curve.model, TwistedEdwardsModel) or not isinstance( + params.curve.coordinate_model, AffineCoordinateModel + ): + raise ValueError + + def map_parameters(a, d): + c = a.sqrt().inverse() + d = a * d + return {"c": c, "d": d} + + def map_point(a, d, pt, aff): + u = pt.x + v = pt.y / a.sqrt().inverse() + return Point(aff, x=u, y=v) + + return __map(params, ("a", "d"), map_parameters, map_point, EdwardsModel()) + + +@public +def TE2SW(params: DomainParameters) -> DomainParameters: + """ + Convert a TwistedEdwards curve to ShortWeierstrass. + + :param params: The domain parameters to convert. + :return: The converted domain parameters. + """ + if not isinstance(params.curve.model, TwistedEdwardsModel) or not isinstance( + params.curve.coordinate_model, AffineCoordinateModel + ): + raise ValueError + + def map_parameters(A, D): + a = -(A ** 2 + 14 * D * A + D ** 2) / 48 + b = (A + D) * (-A ** 2 + 34 * A * D - D ** 2) / 864 + return {"a": a, "b": b} + + def map_point(A, D, pt, aff): + u = (5 * A + A * pt.y - 5 * D * pt.y - D) / (12 - 12 * pt.y) + v = (A + A * pt.y - D * pt.y - D) / (4 * pt.x - 4 * pt.x * pt.y) + return Point(aff, x=u, y=v) + + return __map(params, ("a", "d"), map_parameters, map_point, ShortWeierstrassModel()) + + +def __sw_ab(params: DomainParameters) -> Generator[Tuple[Mod, Mod], None, None]: if not isinstance(params.curve.model, ShortWeierstrassModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel + params.curve.coordinate_model, AffineCoordinateModel ): raise ValueError ax = symbols("α") @@ -132,10 +206,23 @@ def SW2M(params: DomainParameters) -> DomainParameters: roots = rhs.ground_roots() if not roots: raise ValueError( - "Curve cannot be transformed to Montgomery model (x^3 + ax + b has no root)." + "Curve cannot be transformed (x^3 + ax + b has no root)." ) - alpha = Mod(int(next(iter(roots.keys()))), params.curve.prime) - beta = (3 * alpha ** 2 + params.curve.parameters["a"]).sqrt() + for root in roots: + alpha = Mod(int(root), params.curve.prime) + beta = (3 * alpha ** 2 + params.curve.parameters["a"]).sqrt() + yield alpha, beta + + +@public +def SW2M(params: DomainParameters) -> DomainParameters: + """ + Convert a ShortWeierstrass curve to Montgomery. + + :param params: The domain parameters to convert. + :return: The converted domain parameters. + """ + alpha, beta = next(iter(__sw_ab(params))) def map_parameters(a, b): A = (3 * alpha) / beta @@ -147,7 +234,7 @@ def SW2M(params: DomainParameters) -> DomainParameters: v = pt.y / beta return Point(aff, x=u, y=v) - return __M_map(params, ("a", "b"), map_parameters, map_point, MontgomeryModel()) + return __map(params, ("a", "b"), map_parameters, map_point, MontgomeryModel()) @public @@ -158,26 +245,7 @@ def SW2TE(params: DomainParameters) -> DomainParameters: :param params: The domain parameters to convert. :return: The converted domain parameters. """ - if not isinstance(params.curve.model, ShortWeierstrassModel) or not isinstance( - params.curve.coordinate_model, AffineCoordinateModel - ): - raise ValueError - ax = symbols("α") - field = FF(params.curve.prime) - rhs = Poly( - ax ** 3 - + field(int(params.curve.parameters["a"])) * ax - + field(int(params.curve.parameters["b"])), - ax, - domain=field, - ) - roots = rhs.ground_roots() - if not roots: - raise ValueError( - "Curve cannot be transformed to Montgomery model (x^3 + ax + b has no root)." - ) - alpha = Mod(int(next(iter(roots.keys()))), params.curve.prime) - beta = (3 * alpha ** 2 + params.curve.parameters["a"]).sqrt() + alpha, beta = next(iter(__sw_ab(params))) def map_parameters(a, b): a = 3 * alpha + 2 * beta @@ -196,4 +264,33 @@ def SW2TE(params: DomainParameters) -> DomainParameters: v = (pt.x - alpha - beta) / (pt.x - alpha + beta) return Point(aff, x=u, y=v) - return __M_map(params, ("a", "b"), map_parameters, map_point, TwistedEdwardsModel()) + return __map(params, ("a", "b"), map_parameters, map_point, TwistedEdwardsModel()) + + +@public +def SW2E(params: DomainParameters) -> DomainParameters: + """ + Convert a ShortWeierstrass curve to Edwards. + + :param params: The domain parameters to convert. + :return: The converted domain parameters. + """ + for alpha, beta in __sw_ab(params): + s = beta.inverse() + t = (s / (3 * s * alpha + 2)) + if not t.is_residue(): + continue + t = t.sqrt() + + def map_parameters(a, b): + c = t + d = -4 * a - 3 * alpha ** 2 + return {"c": c, "d": d} + + def map_point(a, b, pt, aff): + u = (pt.x - alpha) / pt.y + v = (s * (pt.x - alpha) - 1) / (s * (pt.x - alpha) + 1) * t + return Point(aff, x=u, y=v) + + return __map(params, ("a", "b"), map_parameters, map_point, EdwardsModel()) + raise ValueError("Cannot convert.") |
