curve.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. import random, sympy
  2. from point import Point
  3. from crypt import CipherAES
  4. from tools import searchPrime
  5. class Curve:
  6. def __init__(self, p, a, b, gx = None, gy = None, n = None, h = 1):
  7. # размер конечного поля
  8. self.p = p
  9. # коэффиценты уравнения a и b
  10. self.a = a
  11. self.b = b
  12. # базовая точка, определяющая подгруппу
  13. self.g = Point(
  14. curve = self,
  15. x = gx,
  16. y = gy
  17. )
  18. # порядок подруппы
  19. self.n = n
  20. # кофактор подгруппы
  21. self.h = h
  22. def clear(self):
  23. self.g = self.n = None
  24. def isSingular(self):
  25. res = 4 * self.a ** 3 + 27 * self.b ** 2 == 0
  26. return res
  27. # Поиск порядка
  28. def setupN(self):
  29. dx, dy = self.g.x, (-1 * self.g.y) % self.p
  30. tmpG = self.g.copy()
  31. self.n = 1
  32. while True:
  33. self.n += 1
  34. tmpG = tmpG + self.g
  35. if tmpG.x == dx and tmpG.y == dy:
  36. self.n += 1
  37. return
  38. # Выбор и установка случайной точки g
  39. def setupGAuto(self):
  40. x = random.randrange(1, self.p - 1)
  41. p1, p2 = self.searchClosePoints(x)
  42. if p1.isInCurve():
  43. self.g = p1
  44. elif p2.isInCurve():
  45. self.g = p2
  46. # Поиск близлежащих точек по x
  47. def searchClosePoints(self, x):
  48. if x >= self.p:
  49. x = self.p - 1
  50. if x < 0:
  51. x = 0
  52. kx = x
  53. while True:
  54. if x >= self.p and kx < 0:
  55. return self.point()
  56. # Поиск вправо
  57. if x <= self.p:
  58. p1, p2 = self.pointsCurve(x)
  59. if p1.isInCurve():
  60. return p1, p2
  61. x += 1
  62. # Поиск влево
  63. if kx <= 0:
  64. p1, p2 = self.pointsCurve(kx)
  65. if p1.isInCurve():
  66. return p1, p2
  67. kx -= 1
  68. return self.point()
  69. def point(self, x = None, y = None):
  70. return Point(
  71. curve = self,
  72. x = x,
  73. y = y
  74. )
  75. # Определение координат пары зеркальных точек через координату x
  76. def pointsCurve(self, dx):
  77. # Инициализируем результирующие точки пустыми
  78. p1, p2 = self.point(), self.point()
  79. dy = None
  80. # Операции, обратной делению по модулю, не существует, поэтому
  81. # для определения координаты по y, необходимо, путем перебора с подстановкой y,
  82. # проверить равенство левой части уравнения, разделенного по модулю на p с
  83. # правой частью, так же разделенной по модулю на p
  84. for i in range(0, self.p):
  85. if i ** 2 % self.p == (dx **3 + self.a * dx + self.b) % self.p:
  86. dy = i
  87. break
  88. # Если dy не найден, точки не существуют, возвращаем нулевые точки
  89. if dy is None:
  90. return p1, p2
  91. # Точка найдена
  92. p1.x, p1.y = dx, dy
  93. # Расчет зеркальной точки
  94. p2.x = p1.x
  95. p2.y = -1 * p1.y % self.p
  96. return p1, p2
  97. # Обратное деление по модулю p кривой
  98. def inverseMod(self, k, point):
  99. if k == 0:
  100. raise ZeroDivisionError('Деление на 0 невозможно!!!')
  101. if k < 0:
  102. # k ** -1 = p - (-k) ** -1 (mod p)
  103. return point - self.inverseMod(-k, point)
  104. # Расширенный алгоритм Евклида
  105. s, old_s = 0, 1
  106. t, old_t = 1, 0
  107. r, old_r = point, k
  108. while r != 0:
  109. quotient = old_r // r
  110. old_r, r = r, old_r - quotient * r
  111. old_s, s = s, old_s - quotient * s
  112. old_t, t = t, old_t - quotient * t
  113. gcd, x, y = old_r, old_s, old_t
  114. return x % point
  115. def randomKeypair(self):
  116. keyPriv = random.randrange(1, self.n - 1)
  117. print(keyPriv)
  118. keyPub = self.g * keyPriv
  119. return keyPriv, keyPub
  120. def keypair(self, keyPriv):
  121. keyPub = self.g * keyPriv
  122. return keyPriv, keyPub
  123. # Создание публичного ключа из приватного
  124. def keyPub(self, keyPriv):
  125. # Результат - умножение точки подгруппы на приватный ключ
  126. return self.g * keyPriv
  127. # Вычисление общего секретного ключа, по которому производится шифрование и расшифровка сообщений
  128. def pointSecret(self, myKeyPrivate, friendKeyPublic):
  129. return friendKeyPublic * myKeyPrivate
  130. # Шифровка сообщения секретным ключем
  131. def encodeMessage(self, secretPoint, text):
  132. cipher = CipherAES(self, secretPoint)
  133. return cipher.encrypt(text)
  134. # Расшифровка сообщения секретным ключем
  135. def decodeMessage(self, secretPoint, encodedText):
  136. cipher = CipherAES(self, secretPoint)
  137. return cipher.decrypt(encodedText)
  138. #################################
  139. # Тестирование
  140. if __name__ == '__main__':
  141. # Создание объекта эллиптической кривой (кривая из исходников openssl)
  142. '''
  143. cur = Curve(
  144. # Размер конечного поля
  145. p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
  146. # Коэффиценты
  147. a = 0,
  148. b = 7,
  149. # Координаты точки, определяющей подгруппу
  150. gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
  151. gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8,
  152. # Размер подгруппы
  153. n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141,
  154. # Кофактор подгруппы
  155. h = 1
  156. )
  157. '''
  158. cur = Curve(
  159. p = searchPrime(2 ** 18),
  160. a = 1550,
  161. b = 7840
  162. )
  163. print('setup g')
  164. cur.setupGAuto()
  165. print('g', cur.g.coords(), cur.g.isInCurve())
  166. print('setup n')
  167. cur.setupN()
  168. print(cur.p, cur.n)
  169. print(cur.n, cur.g.coords(), cur.g.isInCurve())
  170. k1, p1 = cur.keypair(10)
  171. print(k1, p1.coords())
  172. k2, p2 = cur.keypair(110)
  173. print(k2, p2.coords())
  174. #exit(0)
  175. # В зашифрованном обмене данными принимают участие 2 пользователя.
  176. # Далее - п1 (пользователь 1) и п2 (пользователь 2)
  177. # Каждый из пользовательей должен создать свою пару ключей (приватный и публичный) исходя из параметров одной эллиптической кривой
  178. # Создание пары ключей п1
  179. p1KeyPriv, p1KeyPub = cur.randomKeypair()
  180. # Создание пары ключей п2
  181. p2KeyPriv, p2KeyPub = cur.randomKeypair()
  182. # Предположим, что п1 и п2 обменялись публичными ключами
  183. # Далее каждый из них может рассчитать общий секретный ключ, используя свой приватный ключ и полученный публичный ключ контрагента
  184. # Секретный ключ идентичен для п1 и п2 и используется в качестве ключа в алгоритме симметричного шифрования, который используется
  185. # для шифровки и расшифровки сообщений
  186. # Расчет секретного ключа п1
  187. p1KeySecret = cur.pointSecret(p1KeyPriv, p2KeyPub)
  188. print(p1KeySecret.coords())
  189. # Расчет секретного ключа п2
  190. p2KeySecret = cur.pointSecret(p2KeyPriv, p1KeyPub)
  191. print(p2KeySecret.coords())
  192. # Покажем, что полученные секретные ключи идентичны у п1 и п2
  193. print(p1KeySecret.isEqual(p2KeySecret))
  194. #exit(0)
  195. # Далее п1 отправляет зашифрованное сообщение п2
  196. p1MessageEncrypted = cur.encodeMessage(p1KeySecret, 'Привет, как дела?')
  197. #Покажем зашифрованное сообщение
  198. print("п1: ", p1MessageEncrypted)
  199. # п2 расшифровывает полученное сообщение
  200. p1MessageDecrypted = cur.decodeMessage(p2KeySecret, p1MessageEncrypted)
  201. # Покажем расшифрованное сообщение
  202. print("п1: ", p1MessageDecrypted)
  203. # п2 отправляет зашифрованным сообщением п1
  204. p2MessageEncrypted = cur.encodeMessage(p2KeySecret, 'Спасибо, у меня всё хорошо :)')
  205. #Покажем зашифрованное сообщение
  206. print("п2: ", p2MessageEncrypted)
  207. # п1 расшифровывает полученное сообщение
  208. p2MessageDecrypted = cur.decodeMessage(p1KeySecret, p2MessageEncrypted)
  209. # Покажем расшифрованное сообщение
  210. print("п2: ", p2MessageDecrypted)