point.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. if self.isNone():
  46. return False
  47. x, y = self.coords()
  48. c = self.curve
  49. return (y * y - x * x * x - c.a * x - c.b) % c.p == 0
  50. # Вычисление наклона прямой, проходящей через 2 точки эллиптической кривой
  51. def getIncline(self, point):
  52. m = 0
  53. cur = self.curve
  54. x1, y1 = self.coords()
  55. x2, y2 = point.coords()
  56. if self.x == point.x:
  57. # точки равны.
  58. c = self.curve
  59. m = (3 * x1 * x1 + cur.a) * cur.inverseMod(2 * y1, cur.p)
  60. else:
  61. # точки не равны
  62. m = (y1 - y2) * cur.inverseMod(x1 - x2, cur.p)
  63. return m
  64. # Сложение
  65. def __add__(self, point):
  66. #assert is_on_curve(point1)
  67. #assert is_on_curve(point2)
  68. if self.isNone():
  69. return point.copy()
  70. if point.isNone():
  71. return self.copy()
  72. if self.x == point.x and self.y != point.y:
  73. # p + (-p) = 0, симметричная точка
  74. return self.pointNull()
  75. # вычисление наклона прямой, прходящей через 2 точки
  76. m = self.getIncline(point)
  77. # вычисление результирующих координат
  78. rx = m * m - self.x - point.x
  79. ry = self.y + m * (rx - self.x)
  80. return self.initXY(
  81. x = rx % self.curve.p,
  82. y = -ry % self.curve.p,
  83. )
  84. # Унарный -
  85. def __neg__(self):
  86. return self.initXY(
  87. x = self.x,
  88. y = -self.y % self.curve.p,
  89. )
  90. # Сравнение. Точки считаются равны, если они совпадают по оси x
  91. def __eq__(self, point):
  92. # Точки считаются равны при совпадении по оси x
  93. return self.x == point.x
  94. # Умножение
  95. def __mul__(self, k):
  96. #assert is_on_curve(point)
  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. #assert is_on_curve(result)
  112. return res