point.py 3.9 KB

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