Example #1
0
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())
Example #2
0
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())
Example #3
0
def _create_params(curve, coords, infty):
    if curve["field"]["type"] == "Binary":
        raise ValueError("Binary field curves are currently not supported.")
    if curve["field"]["type"] == "Extension":
        raise ValueError("Extension field curves are currently not supported.")

    # Get model and param names
    model: CurveModel
    field = int(curve["field"]["p"], 16)
    order = int(curve["order"], 16)
    cofactor = int(curve["cofactor"], 16)
    if curve["form"] == "Weierstrass":
        model = ShortWeierstrassModel()
        param_names = ["a", "b"]
    elif curve["form"] == "Montgomery":
        model = MontgomeryModel()
        param_names = ["a", "b"]
    elif curve["form"] == "Edwards":
        model = EdwardsModel()
        param_names = ["c", "d"]
    elif curve["form"] == "TwistedEdwards":
        model = TwistedEdwardsModel()
        param_names = ["a", "d"]
    else:
        raise ValueError("Unknown curve model.")
    params = {
        name: Mod(int(curve["params"][name]["raw"], 16), field)
        for name in param_names
    }

    # Check coordinate model name and assumptions
    coord_model: CoordinateModel
    if coords == "affine":
        coord_model = AffineCoordinateModel(model)
    else:
        if coords not in model.coordinates:
            raise ValueError("Coordinate model not supported for curve.")
        coord_model = model.coordinates[coords]
        for assumption in coord_model.assumptions:
            # Try to execute assumption, if it works, check with curve parameters
            # if it doesn't work, move all over to rhs and construct a sympy polynomial of it
            # then find roots and take first one for new value for new coordinate parameter.
            try:
                alocals: Dict[str, Union[Mod, int]] = {}
                compiled = compile(assumption, "", mode="exec")
                exec(compiled, None, alocals)
                for param, value in alocals.items():
                    if params[param] != value:
                        raise_unsatisified_assumption(
                            getconfig().ec.
                            unsatisfied_coordinate_assumption_action,
                            f"Coordinate model {coord_model} has an unsatisifed assumption on the {param} parameter (= {value}).",
                        )
            except NameError:
                k = FF(field)
                assumption_string = unparse(assumption)
                lhs, rhs = assumption_string.split(" = ")
                expr = sympify(f"{rhs} - {lhs}")
                for curve_param, value in params.items():
                    expr = expr.subs(curve_param, k(value))
                if (len(expr.free_symbols) > 1
                        or (param := str(expr.free_symbols.pop()))
                        not in coord_model.parameters):
                    raise ValueError(
                        f"This coordinate model couldn't be loaded due to an unsupported assumption ({assumption_string})."
                    )
                poly = Poly(expr, symbols(param), domain=k)
                roots = poly.ground_roots()
                for root in roots:
                    params[param] = Mod(int(root), field)
                    break
                else:
                    raise UnsatisfiedAssumptionError(
                        f"Coordinate model {coord_model} has an unsatisifed assumption on the {param} parameter (0 = {expr})."
                    )
Example #4
0
    def __validate_assumptions(self, field, params):
        # Validate assumptions and compute formula parameters.
        # TODO: Should this also validate coordinate assumptions and compute their parameters?
        is_symbolic = any(isinstance(x, SymbolicMod) for x in params.values())
        for assumption in self.assumptions:
            assumption_string = unparse(assumption)[1:-2]
            lhs, rhs = assumption_string.split(" == ")
            if lhs in params:
                # Handle an assumption check on value of input points.
                alocals: Dict[str, Union[Mod, int]] = {**params}
                compiled = compile(assumption, "", mode="eval")
                holds = eval(compiled, None, alocals)
                if not holds:
                    # The assumption doesn't hold, see what is the current configured action and do it.
                    raise_unsatisified_assumption(
                        getconfig().ec.unsatisfied_formula_assumption_action,
                        f"Unsatisfied assumption in the formula ({assumption_string}).",
                    )
            elif lhs in self.parameters and is_symbolic:
                # Handle a symbolic assignment to a new parameter.
                k = FF(field)
                expr = sympify(rhs, evaluate=False)
                for curve_param, value in params.items():
                    if isinstance(value, SymbolicMod):
                        expr = expr.subs(curve_param, value.x)
                    else:
                        expr = expr.subs(curve_param, k(value))
                params[lhs] = SymbolicMod(expr, field)
            else:
                k = FF(field)
                expr = sympify(f"{rhs} - {lhs}", evaluate=False)
                for curve_param, value in params.items():
                    if isinstance(value, SymbolicMod):
                        expr = expr.subs(curve_param, value.x)
                    else:
                        expr = expr.subs(curve_param, k(value))
                if (len(expr.free_symbols) > 1 or (param := str(
                        expr.free_symbols.pop())) not in self.parameters):
                    raise ValueError(
                        f"This formula couldn't be executed due to an unsupported assumption ({assumption_string})."
                    )

                def resolve(expression):
                    if not expression.args:
                        return expression
                    args = []
                    for arg in expression.args:
                        if isinstance(arg, Rational):
                            a = arg.p
                            b = arg.q
                            arg = k(a) / k(b)
                        else:
                            arg = resolve(arg)
                        args.append(arg)
                    return expression.func(*args)

                expr = resolve(expr)
                poly = Poly(expr, symbols(param), domain=k)
                roots = poly.ground_roots()
                for root in roots:
                    params[param] = Mod(int(root), field)
                    break
                else:
                    raise UnsatisfiedAssumptionError(
                        f"Unsatisfied assumption in the formula ({assumption_string}).\n"
                        f"'{expr}' has no roots in the base field {k}.")