import random from point import Point from crypt import CipherAES class Curve: def __init__(self, p, a, b, gx, gy, n, h): # размер конечного поля self.p = p # коэффиценты уравнения a и b self.a = a self.b = b # базовая точка, определяющая подгруппу self.g = Point( curve = self, x = gx, y = gy ) # порядок подруппы self.n = n # кофактор подгруппы self.h = h def point(self, x, y): return Point( curve = self, x = x, y = y ) # Обратное деление по модулю p def inverseMod(self, k, point): if k == 0: raise ZeroDivisionError('Деление на 0 невозможно!!!') if k < 0: # k ** -1 = p - (-k) ** -1 (mod p) return point - self.inverseMod(-k, point) # Расширенный алгоритм Евклида s, old_s = 0, 1 t, old_t = 1, 0 r, old_r = point, k while r != 0: quotient = old_r // r old_r, r = r, old_r - quotient * r old_s, s = s, old_s - quotient * s old_t, t = t, old_t - quotient * t gcd, x, y = old_r, old_s, old_t return x % point def randomKeypair(self): keyPriv = random.randrange(1, self.n) keyPub = self.g * keyPriv return keyPriv, keyPub # Создание публичного ключа из приватного def keyPub(self, keyPriv): # Результат - умножение точки подгруппы на приватный ключ return self.g * keyPriv # Вычисление общего секретного ключа, по которому производится шифрование и расшифровка сообщений def pointSecret(self, myKeyPrivate, friendKeyPublic): return friendKeyPublic * myKeyPrivate # Шифровка сообщения секретным ключем def encodeMessage(self, secretPoint, text): cipher = CipherAES(self, secretPoint) return cipher.encrypt(text) # Расшифровка сообщения секретным ключем def decodeMessage(self, secretPoint, encodedText): cipher = CipherAES(self, secretPoint) return cipher.decrypt(encodedText) ################################# # Тестирование if __name__ == '__main__': # Создание объекта эллиптической кривой (кривая из исходников openssl) cur = Curve( # Размер конечного поля p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f, # Коэффиценты a = 0, b = 7, # Координаты точки, определяющей подгруппу gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798, gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8, # Размер подгруппы n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141, # Кофактор подгруппы h = 1 ) # В зашифрованном обмене данными принимают участие 2 пользователя. # Далее - п1 (пользователь 1) и п2 (пользователь 2) # Каждый из пользовательей должен создать свою пару ключей (приватный и публичный) исходя из параметров одной эллиптической кривой # Создание пары ключей п1 p1KeyPriv, p1KeyPub = cur.randomKeypair() # Создание пары ключей п2 p2KeyPriv, p2KeyPub = cur.randomKeypair() # Предположим, что п1 и п2 обменялись публичными ключами # Далее каждый из них может рассчитать общий секретный ключ, используя свой приватный ключ и полученный публичный ключ контрагента # Секретный ключ идентичен для п1 и п2 и используется в качестве ключа в алгоритме симметричного шифрования, который используется # для шифровки и расшифровки сообщений # Расчет секретного ключа п1 p1KeySecret = cur.pointSecret(p1KeyPriv, p2KeyPub) # Расчет секретного ключа п2 p2KeySecret = cur.pointSecret(p2KeyPriv, p1KeyPub) # Покажем, что полученные секретные ключи идентичны у п1 и п2 print(p1KeySecret.isEqual(p2KeySecret)) # Далее п1 отправляет зашифрованное сообщение п2 p1MessageEncrypted = cur.encodeMessage(p1KeySecret, 'Привет, как дела?') #Покажем зашифрованное сообщение print("п1: ", p1MessageEncrypted) # п2 расшифровывает полученное сообщение p1MessageDecrypted = cur.decodeMessage(p2KeySecret, p1MessageEncrypted) # Покажем расшифрованное сообщение print("п1: ", p1MessageDecrypted) # п2 отправляет зашифрованным сообщением п1 p2MessageEncrypted = cur.encodeMessage(p2KeySecret, 'Спасибо, у меня всё хорошо :)') #Покажем зашифрованное сообщение print("п2: ", p2MessageEncrypted) # п1 расшифровывает полученное сообщение p2MessageDecrypted = cur.decodeMessage(p1KeySecret, p2MessageEncrypted) # Покажем расшифрованное сообщение print("п2: ", p2MessageDecrypted)