def sign(self, z: int) -> tuple: if not self.is_secret_set: raise Exception("secret is not set") n = self.curve.order k = Element(randint(2, n - 1), n) r = Element((int(k) * self.g).unpack()[0], n) s = (Element(z, n) + r * self.d) / k return (int(r), int(s))
def on_curve(self, point): _x, _y = point if _x is None and _y is None: return True if _x is None or _y is None: return False x, y = Element(_x, self.p), Element(_y, self.p) return y**2 == x**3 + self.a * x + self.b
def __add__(self, point): self.raise_different_curve_err(point) if self.is_o(): return point if point.is_o(): return self if self.x == point.x and self.y == -point.y: return self.curve.get_o() if self == point: s = (Element(3, self.curve.p) * self.x**2 + self.curve.a) / \ (Element(2, self.curve.p) * self.y) else: s = (point.y - self.y) / (point.x - self.x) ret_x = s**2 - self.x - point.x ret_y = s * (self.x - ret_x) - self.y return self.__class__(ret_x.x, ret_y.x, self.curve)
def __init__(self, a, b, p): self.a = Element(a, p) self.b = Element(b, p) self.p = p self.order = None # todo: calculating order
def verify(self, r: int, s: int, z: int) -> bool: n = self.curve.order r, s, z = Element(r, n), Element(s, n), Element(z, n) u, v = z / s, r / s kg = int(u) * self.g + int(v) * self.q return kg.unpack()[0] == int(r)
def set_secret(self, d: int) -> None: self.d = Element(d, self.curve.order) if d * self.g != self.q: raise ValueError("invalid secret")
def __calc_rhs(self, x: int) -> int: x = Element(x, self.p) return int(x**3 + self.a * x + self.b)
def __init__(self, x, y, curve): self.x = Element(x, curve.p) if x is not None else None self.y = Element(y, curve.p) if x is not None else None if not curve.on_curve((x, y)): raise ValueError(f"({x}, {y}) is not on curve: {curve}") self.curve = curve