123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- 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
|