mirror of
https://github.com/elseif/MikroTikPatch.git
synced 2025-01-23 21:44:59 +03:00
141 lines
5.2 KiB
Python
141 lines
5.2 KiB
Python
#
|
|
# toyecc - A small Elliptic Curve Cryptography Demonstration.
|
|
# Copyright (C) 2011-2022 Johannes Bauer
|
|
#
|
|
# This file is part of toyecc.
|
|
#
|
|
# toyecc is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; this program is ONLY licensed under
|
|
# version 3 of the License, later versions are explicitly excluded.
|
|
#
|
|
# toyecc is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with toyecc; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
# Johannes Bauer <JohannesBauer@gmx.de>
|
|
#
|
|
|
|
from .FieldElement import FieldElement
|
|
from .Exceptions import NoSuchCurveException
|
|
|
|
class CurveOpIsomorphism(object):
|
|
def _twist(self, d = None, sqrt_d = None):
|
|
"""Returns the twisted curve with the twist coefficient d. If d is a
|
|
quadratic non-residue mod p then this function will yield a curve that
|
|
is isomorphous on the field extension GF(sqrt(d)). If it is a quadratic
|
|
residue, it will return an GF(p)-isomorphous curve."""
|
|
assert(self.curvetype == "shortweierstrass")
|
|
ShortWeierstrassCurve = self.__class__
|
|
|
|
if sqrt_d is not None:
|
|
# If a square root is given, then it must be a correct square root
|
|
assert(sqrt_d ** 2 == d)
|
|
|
|
a = self.a * (d ** 2)
|
|
b = self.b * (d ** 3)
|
|
if d.is_qr and self.hasgenerator:
|
|
# Quadratic twist will return an GF(p)-isomorphous curve -> convert
|
|
# generator point as well
|
|
if sqrt_d is None:
|
|
sqrt_d = d.sqrt()[0]
|
|
Gx = int(self.G.x * d)
|
|
Gy = int(self.G.y * (sqrt_d ** 3))
|
|
|
|
n = self.n
|
|
h = self.h
|
|
else:
|
|
# Quadratic twist will return an isomorphous curve on the
|
|
# GF(sqrt(d)) field extension -> no generator point conversion for
|
|
# now
|
|
# Gx = int(self.G.x * d)
|
|
# Gy = int(self.G.y * d)
|
|
Gx = None
|
|
Gy = None
|
|
|
|
# If the original curve had q + 1 - t points, then its twist will
|
|
# have q + 1 + t points. TODO: Does this help us to find the order
|
|
# of the generator point G? I don't think it does :-( Leave n and h
|
|
# therefore unset for the moment.
|
|
n = None
|
|
h = None
|
|
|
|
return ShortWeierstrassCurve(a = int(a), b = int(b), p = self.p, n = n, h = h, Gx = Gx, Gy = Gy)
|
|
|
|
def twist(self, d = None):
|
|
"""If the twist coefficient d is omitted, the function will
|
|
automatically look for an arbitrary quadratic non-residue in F_P."""
|
|
if d == 0:
|
|
raise Exception("Domain error: d must be nonzero.")
|
|
elif d is None:
|
|
# Search for a QNR in F_P
|
|
d = FieldElement.any_qnr(self.p)
|
|
else:
|
|
d = FieldElement(d, self.p)
|
|
if d.is_qr:
|
|
raise Exception("Twist requested, but twist coefficient d is a quadratic-residue mod p. Refusing to return a GF(p)-isomorphic curve; if you want this behavior, use twist_fp_isomorphic()")
|
|
return self._twist(d)
|
|
|
|
def twist_fp_isomorphic(self, u):
|
|
"""Returns a GF(p)-isomorphous curve by applying the substituting
|
|
transformation x = u^2 x' and y = u^3 y' on the curve equation. The
|
|
function therefore returns a quadratic twist with d = u^2, i.e. it
|
|
ensures that the twist coefficient d is a quadratic residue mod p.."""
|
|
if u == 0:
|
|
raise Exception("Domain error: u must be nonzero.")
|
|
return self._twist(FieldElement(u ** 2, self.p), FieldElement(u, self.p))
|
|
|
|
def twist_fp_isomorphic_fixed_a(self, a):
|
|
"""Tries to find an GF(p)-isomorphous curve which has a particular
|
|
given value for the curve coefficient 'a'."""
|
|
|
|
# anew = a * u^4 -> u = quartic_root(anew / a)
|
|
scalar = a // self.a
|
|
u = scalar.quartic_root()
|
|
if u is None:
|
|
raise NoSuchCurveException("Cannot find an isomorphism so that a = %d because %s has no quartic root in F_P" % (a, scalar))
|
|
return self.twist_fp_isomorphic(int(u))
|
|
|
|
def is_isomorphous_curve(self, other):
|
|
"""Returns if the given curve 'other' is isomorphous in the same field
|
|
as the given curve curve."""
|
|
if other.p != self.p:
|
|
return False
|
|
|
|
try:
|
|
iso = self.twist_fp_isomorphic_fixed_a(other.a)
|
|
except NoSuchCurveException:
|
|
# No isomorphous curve with this value for a exists
|
|
return False
|
|
|
|
# The curves should be identical after the transformation if they're
|
|
# isomorphous to each other
|
|
return (iso.a == other.a) and (iso.b == other.b)
|
|
|
|
class CurveOpExportSage(object):
|
|
def export_sage(self, varname = "curve"):
|
|
"""Exports the elliptic curve to statements that can be used within the
|
|
SAGE computer algebra system."""
|
|
|
|
# EllipticCurve([a1,a2,a3,a4,a6]) means in Sage:
|
|
# y² + a1 x y + a3 y = x³ + a2 x² + a4 x + a6
|
|
# i.e. for Short Weierstrass a4 = A, a6 = B
|
|
|
|
statements = [ ]
|
|
statements.append("# %s" % (str(self)))
|
|
statements.append("%s_p = 0x%x" % (varname, int(self.p)))
|
|
statements.append("%s_F = GF(%s_p)" % (varname, varname))
|
|
if self.curvetype == "shortweierstrass":
|
|
statements.append("%s_a = 0x%x" % (varname, int(self.a)))
|
|
statements.append("%s_b = 0x%x" % (varname, int(self.b)))
|
|
statements.append("%s = EllipticCurve(%s_F, [ %s_a, %s_b ])" % (varname, varname, varname, varname))
|
|
else:
|
|
raise Exception(NotImplemented)
|
|
|
|
return statements
|