point.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import hashlib
  2. class Point:
  3. # Конструктор
  4. def __init__(self, x, y, curve):
  5. self.curve = curve
  6. self.x = x
  7. self.y = y
  8. # Копирование объекта точки
  9. def copy(self):
  10. return Point(
  11. curve = self.curve,
  12. x = self.x,
  13. y = self.y,
  14. )
  15. # HEX формат строки с координатами
  16. def show(self):
  17. if self.isNone():
  18. return "None"
  19. return "(0x{:x}, 0x{:x})".format(self.x, self.y)
  20. # Числовой формат строки с координатами
  21. def showCoords(self):
  22. if self.isNone():
  23. return "None"
  24. return "({}, {})".format(self.x, self.y)
  25. # Инициализация новой точки по координатам
  26. def initXY(self, x, y):
  27. return Point(
  28. curve = self.curve,
  29. x = x,
  30. y = y
  31. )
  32. # Инициализация новой точки с неопределенными координатами
  33. def pointNull(self):
  34. return Point(
  35. x = None,
  36. y = None,
  37. curve = self.curve
  38. )
  39. # Проверка, определена ли точка.
  40. # Точка считается неопределенной, если одна из координат или объект эллиптической кривой не определены
  41. def isNone(self):
  42. return self.x is None or self.y is None or self.curve is None
  43. # возвращает координаты x и y
  44. def coords(self):
  45. return self.x, self.y
  46. # Проверка пренадлежности точки к эллиптической кривой
  47. def isInCurve(self):
  48. if self.isNone():
  49. return False
  50. x, y = self.coords()
  51. c = self.curve
  52. return (y * y - x * x * x - c.a * x - c.b) % c.p == 0
  53. # Вычисление наклона прямой, проходящей через 2 точки эллиптической кривой
  54. def getIncline(self, point):
  55. m = 0
  56. cur = self.curve
  57. x1, y1 = self.coords()
  58. x2, y2 = point.coords()
  59. if self.x == point.x:
  60. # точки равны
  61. c = self.curve
  62. m = (3 * x1 * x1 + cur.a) * cur.inverseMod(2 * y1, cur.p)
  63. else:
  64. # точки не равны
  65. m = (y1 - y2) * cur.inverseMod(x1 - x2, cur.p)
  66. return m
  67. # Скалярное сложение точек
  68. def __add__(self, point):
  69. if self.isNone():
  70. return point.copy()
  71. if point.isNone():
  72. return self.copy()
  73. if self.x == point.x and self.y != point.y:
  74. # p + (-p) = 0, симметричная точка
  75. return self.pointNull()
  76. # вычисление наклона прямой, прходящей через 2 точки
  77. m = self.getIncline(point)
  78. # вычисление результирующих координат
  79. rx = m * m - self.x - point.x
  80. ry = self.y + m * (rx - self.x)
  81. return self.initXY(
  82. x = rx % self.curve.p,
  83. y = -ry % self.curve.p,
  84. )
  85. # Унарный -
  86. def __neg__(self):
  87. return self.initXY(
  88. x = self.x,
  89. y = -self.y % self.curve.p,
  90. )
  91. # Сравнение. Точки считаются равны, если они совпадают по оси x
  92. def __eq__(self, point):
  93. # Точки считаются равны при совпадении по оси x
  94. return self.x == point.x
  95. # Умножение
  96. def __mul__(self, k):
  97. if self.isNone() or k % self.curve.n == 0:
  98. return self.pointNull()
  99. if k < 0:
  100. # k * point = -k * (-point)
  101. return -self * -k
  102. res = self.pointNull()
  103. addend = self.copy()
  104. while k:
  105. if k & 1:
  106. # Add.
  107. res = res + addend
  108. # Double.
  109. addend = addend + addend
  110. k >>= 1
  111. return res
  112. # Вычисление хэша точки (числовая строка суммы координат)
  113. def md5(self):
  114. src = str(self.x + self.y)
  115. return hashlib.md5(src.encode('utf-8')).digest()
  116. # Вычисление хэша по оси x
  117. def md5X(self):
  118. return hashlib.md5(str(self.x).encode('utf-8')).digest()
  119. # Вычисление хэша по оси y
  120. def md5Y(self):
  121. return hashlib.md5(str(self.y).encode('utf-8')).digest()
  122. # Проверка совпадения координат 2х точек по осям x и y
  123. def isEqual(self, point):
  124. x1, y1 = self.coords()
  125. x2, y2 = point.coords()
  126. return x1 == x2 and y1 == y2