curve.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import random, sympy
  2. from point import Point
  3. '''
  4. 'secp256k1',
  5. p=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
  6. a=0,
  7. b=7,
  8. g=(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8),
  9. # Subgroup order.
  10. n=0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141,
  11. # Subgroup cofactor.
  12. h=1,
  13. '''
  14. # y2 = x3 + ax + b
  15. class Curve:
  16. def __init__(self, p, a, b, gx, gy, n, h):
  17. # размер конечного поля
  18. self.p = p
  19. # коэффиценты уравнения a и b
  20. self.a = a
  21. self.b = b
  22. # базовая точка
  23. self.g = Point(
  24. curve = self,
  25. x = gx,
  26. y = gy
  27. )
  28. # порядок подруппы
  29. self.n = n
  30. # кофактор подгруппы
  31. self.h = h
  32. def isSingular(self):
  33. res = 4 * self.a ** 3 + 27 * self.b ** 2 == 0
  34. return res
  35. def setupN(self):
  36. for self.n in range(self.p - 1, 1, -1):
  37. if sympy.isprime(self.n):
  38. return
  39. def setupG(self, processCallback = None):
  40. percent = 0
  41. for x in range(self.n, 0, -1):
  42. if processCallback is not None:
  43. dPercent = round(100 - x * 100 / self.n, 5)
  44. if dPercent != percent:
  45. percent = dPercent
  46. processCallback(percent)
  47. p1, p2 = self.pointsCurve(x)
  48. if p1.isInCurve():
  49. self.g = p1
  50. #print(p1.coords(), p1.isInCurve())
  51. #print(p2.coords(), p2.isInCurve())
  52. return
  53. def point(self, x = None, y = None):
  54. return Point(
  55. curve = self,
  56. x = x,
  57. y = y
  58. )
  59. # Определение координат пары зеркальных точек через координату x
  60. def pointsCurve(self, dx):
  61. # Инициализируем результирующие точки пустыми
  62. p1, p2 = self.point(), self.point()
  63. dy = None
  64. # Операции, обратной делению по модулю, не существует, поэтому
  65. # для определения координаты по y, необходимо, путем перебора с подстановкой y,
  66. # проверить равенство левой части уравнения, разделенного по модулю на p с
  67. # правой частью, так же разделенной по модулю на p
  68. for i in range(0, self.p):
  69. if i ** 2 % self.p == (dx **3 + self.a * dx + self.b) % self.p:
  70. dy = i
  71. break
  72. # Если dy не найден, точки не существуют, возвращаем нулевые точки
  73. if dy is None:
  74. return p1, p2
  75. # Точка найдена
  76. p1.x, p1.y = dx, dy
  77. # Расчет зеркальной точки
  78. p2.x = p1.x
  79. p2.y = -1 * p1.y % self.p
  80. return p1, p2
  81. # Обратное деление по модулю p кривой
  82. def inverseMod(self, k, point):
  83. if k == 0:
  84. raise ZeroDivisionError('division by zero')
  85. if k < 0:
  86. # k ** -1 = p - (-k) ** -1 (mod p)
  87. return point - self.inverseMod(-k, point)
  88. # Расширенный алгоритм Евклида
  89. s, old_s = 0, 1
  90. t, old_t = 1, 0
  91. r, old_r = point, k
  92. while r != 0:
  93. quotient = old_r // r
  94. old_r, r = r, old_r - quotient * r
  95. old_s, s = s, old_s - quotient * s
  96. old_t, t = t, old_t - quotient * t
  97. gcd, x, y = old_r, old_s, old_t
  98. #assert gcd == 1
  99. #assert (k * x) % p == 1
  100. return x % point
  101. def randomKeypair(self):
  102. keyPriv = random.randrange(1, self.n)
  103. keyPub = self.g * keyPriv
  104. return keyPriv, keyPub
  105. def keyPub(self, keyPriv):
  106. return self.g * keyPriv
  107. #################################
  108. '''
  109. c = Curve(
  110. p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
  111. a = 0,
  112. b = 7,
  113. gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
  114. gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8,
  115. n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141,
  116. h = 1
  117. )
  118. c = Curve(
  119. p = 6277101735386680763835789423207666416083908700390324961279,
  120. a = -3,
  121. b = 2455155546008943817740293915197451784769108058161191238065,
  122. gx = 602046282375688656758213480587526111916698976636884684818,
  123. gy = 174050332293622031404857552280219410364023488927386650641,
  124. n = 6277101735386680763835789423176059013767194773182842284081,
  125. h = 1
  126. )
  127. '''
  128. c = Curve(
  129. p = 2 ** 20,
  130. a = 5,
  131. b = 4,
  132. gx = 2,
  133. gy = 2,
  134. n = 54534432,
  135. h = 1
  136. )
  137. if c.isSingular():
  138. print('Кривая сингулярна')
  139. exit(0)
  140. def process(percent):
  141. print(percent)
  142. c.setupN()
  143. c.setupG(process)
  144. print(c.n)
  145. aPriv, aPub = c.randomKeypair()
  146. bPriv, bPub = c.randomKeypair()
  147. print(hex(aPriv))
  148. print(aPub.show())
  149. #aS = scalar_mult(alice_private_key, bob_public_key)
  150. aS = bPub * aPriv
  151. bS = aPub * bPriv
  152. print(aS.show())
  153. print(bS.show())