import hashlib class Point: # Конструктор def __init__(self, x, y, curve): self.curve = curve self.x = x self.y = y # Копирование объекта точки def copy(self): return Point( curve = self.curve, x = self.x, y = self.y, ) # HEX формат строки с координатами def show(self): if self.isNone(): return "None" return "(0x{:x}, 0x{:x})".format(self.x, self.y) # Числовой формат строки с координатами def showCoords(self): if self.isNone(): return "None" return "({}, {})".format(self.x, self.y) # Инициализация новой точки по координатам def initXY(self, x, y): return Point( curve = self.curve, x = x, y = y ) # Инициализация новой точки с неопределенными координатами def pointNull(self): return Point( x = None, y = None, curve = self.curve ) # Проверка, определена ли точка. # Точка считается неопределенной, если одна из координат или объект эллиптической кривой не определены def isNone(self): return self.x is None or self.y is None or self.curve is None # возвращает координаты x и y def coords(self): return self.x, self.y # Проверка пренадлежности точки к эллиптической кривой def isInCurve(self): if self.isNone(): return False x, y = self.coords() c = self.curve return (y * y - x * x * x - c.a * x - c.b) % c.p == 0 # Вычисление наклона прямой, проходящей через 2 точки эллиптической кривой def getIncline(self, point): m = 0 cur = self.curve x1, y1 = self.coords() x2, y2 = point.coords() if self.x == point.x: # точки равны c = self.curve m = (3 * x1 * x1 + cur.a) * cur.inverseMod(2 * y1, cur.p) else: # точки не равны m = (y1 - y2) * cur.inverseMod(x1 - x2, cur.p) return m # Скалярное сложение точек def __add__(self, point): if self.isNone(): return point.copy() if point.isNone(): return self.copy() if self.x == point.x and self.y != point.y: # p + (-p) = 0, симметричная точка return self.pointNull() # вычисление наклона прямой, прходящей через 2 точки m = self.getIncline(point) # вычисление результирующих координат rx = m * m - self.x - point.x ry = self.y + m * (rx - self.x) return self.initXY( x = rx % self.curve.p, y = -ry % self.curve.p, ) # Унарный - def __neg__(self): return self.initXY( x = self.x, y = -self.y % self.curve.p, ) # Сравнение. Точки считаются равны, если они совпадают по оси x def __eq__(self, point): # Точки считаются равны при совпадении по оси x return self.x == point.x # Умножение def __mul__(self, k): if self.isNone() or k % self.curve.n == 0: return self.pointNull() if k < 0: # k * point = -k * (-point) return -self * -k res = self.pointNull() addend = self.copy() while k: if k & 1: # Add. res = res + addend # Double. addend = addend + addend k >>= 1 return res # Вычисление хэша точки (числовая строка суммы координат) def md5(self): src = str(self.x + self.y) return hashlib.md5(src.encode('utf-8')).digest() # Вычисление хэша по оси x def md5X(self): return hashlib.md5(str(self.x).encode('utf-8')).digest() # Вычисление хэша по оси y def md5Y(self): return hashlib.md5(str(self.y).encode('utf-8')).digest() # Проверка совпадения координат 2х точек по осям x и y def isEqual(self, point): x1, y1 = self.coords() x2, y2 = point.coords() return x1 == x2 and y1 == y2