diff options
| author | J08nY | 2021-01-20 21:23:37 +0100 |
|---|---|---|
| committer | J08nY | 2021-01-20 21:23:37 +0100 |
| commit | 0187393abd059d8b05b5bf78a31da8c6a8668d13 (patch) | |
| tree | c53ecaa9188381331ff423e4069674b7524edfa2 /pyecsca/ec | |
| parent | 9ec68bdb56882777e5b3670380bf1e1ad7d0a7a3 (diff) | |
| download | pyecsca-0187393abd059d8b05b5bf78a31da8c6a8668d13.tar.gz pyecsca-0187393abd059d8b05b5bf78a31da8c6a8668d13.tar.zst pyecsca-0187393abd059d8b05b5bf78a31da8c6a8668d13.zip | |
Add more curve transformations.
Diffstat (limited to 'pyecsca/ec')
| -rw-r--r-- | pyecsca/ec/transformations.py | 116 |
1 files changed, 108 insertions, 8 deletions
diff --git a/pyecsca/ec/transformations.py b/pyecsca/ec/transformations.py index 6e3b24c..986064b 100644 --- a/pyecsca/ec/transformations.py +++ b/pyecsca/ec/transformations.py @@ -2,25 +2,27 @@ This module provides functions for transforming curves to different models. """ 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 .params import DomainParameters from .point import InfinityPoint, Point -def __M_map(params, map_parameters, map_point, model): - A = params.curve.parameters["a"] - B = params.curve.parameters["b"] - parameters = map_parameters(A, B) +def __M_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) aff = AffineCoordinateModel(model) if isinstance(params.curve.neutral, InfinityPoint): neutral = InfinityPoint(aff) else: - neutral = map_point(A, B, params.curve.neutral, aff) + neutral = map_point(param_one, param_other, params.curve.neutral, aff) curve = EllipticCurve(model, aff, params.curve.prime, neutral, parameters) - return DomainParameters(curve, map_point(A, B, params.generator, aff), params.order, + return DomainParameters(curve, map_point(param_one, param_other, params.generator, aff), params.order, params.cofactor) @@ -46,7 +48,7 @@ def M2SW(params: DomainParameters) -> DomainParameters: v = pt.y / B return Point(aff, x=u, y=v) - return __M_map(params, map_parameters, map_point, ShortWeierstrassModel()) + return __M_map(params, ("a", "b"), map_parameters, map_point, ShortWeierstrassModel()) @public @@ -71,4 +73,102 @@ def M2TE(params: DomainParameters) -> DomainParameters: v = (pt.x - 1) / (pt.x + 1) return Point(aff, x=u, y=v) - return __M_map(params, map_parameters, map_point, TwistedEdwardsModel()) + return __M_map(params, ("a", "b"), map_parameters, map_point, TwistedEdwardsModel()) + + +@public +def TE2M(params: DomainParameters) -> DomainParameters: + """ + Convert a TwistedEdwards curve to Montgomery. + + :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 = (2 * (a + d)) / (a - d) + B = 4 / (a - d) + return {"a": A, "b": B} + + def map_point(a, d, pt, aff): + u = (1 + pt.y) / (1 - pt.y) + 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()) + + +@public +def SW2M(params: DomainParameters) -> DomainParameters: + """ + Convert a ShortWeierstrass curve to Montgomery. + + :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() + + def map_parameters(a, b): + A = (3 * alpha) / beta + B = 1 / beta + return {"a": A, "b": B} + + def map_point(a, b, pt, aff): + u = (pt.x - alpha) / beta + v = pt.y / beta + return Point(aff, x=u, y=v) + + return __M_map(params, ("a", "b"), map_parameters, map_point, MontgomeryModel()) + + +@public +def SW2TE(params: DomainParameters) -> DomainParameters: + """ + Convert a ShortWeierstrass curve to TwistedEdwards. + + :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() + + def map_parameters(a, b): + a = 3 * alpha + 2 * beta + d = 3 * alpha - 2 * beta + return {"a": a, "d": d} + + def map_point(a, b, pt, aff): + if params.curve.is_neutral(pt): + u = Mod(0, params.curve.prime) + v = Mod(1, params.curve.prime) + elif pt.x == alpha and pt.y == 0: + u = Mod(0, params.curve.prime) + v = Mod(-1, params.curve.prime) + else: + u = (pt.x - alpha) / pt.y + 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()) |
