|
@@ -1,28 +1,17 @@
|
|
|
import random, sympy
|
|
|
from point import Point
|
|
|
+from crypt import CipherAES
|
|
|
+from tools import searchPrime
|
|
|
|
|
|
-'''
|
|
|
-'secp256k1',
|
|
|
-p=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
|
|
|
-a=0,
|
|
|
-b=7,
|
|
|
-g=(0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8),
|
|
|
-# Subgroup order.
|
|
|
-n=0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141,
|
|
|
-# Subgroup cofactor.
|
|
|
-h=1,
|
|
|
-'''
|
|
|
-
|
|
|
-# y2 = x3 + ax + b
|
|
|
class Curve:
|
|
|
|
|
|
- def __init__(self, p, a, b, gx, gy, n, h):
|
|
|
+ def __init__(self, p, a, b, gx = None, gy = None, n = None, h = 1):
|
|
|
# размер конечного поля
|
|
|
self.p = p
|
|
|
# коэффиценты уравнения a и b
|
|
|
self.a = a
|
|
|
self.b = b
|
|
|
- # базовая точка
|
|
|
+ # базовая точка, определяющая подгруппу
|
|
|
self.g = Point(
|
|
|
curve = self,
|
|
|
x = gx,
|
|
@@ -33,30 +22,58 @@ class Curve:
|
|
|
# кофактор подгруппы
|
|
|
self.h = h
|
|
|
|
|
|
+ def clear(self):
|
|
|
+ self.g = self.n = None
|
|
|
+
|
|
|
def isSingular(self):
|
|
|
res = 4 * self.a ** 3 + 27 * self.b ** 2 == 0
|
|
|
return res
|
|
|
|
|
|
+ # Поиск порядка
|
|
|
def setupN(self):
|
|
|
- for self.n in range(self.p - 1, 1, -1):
|
|
|
- if sympy.isprime(self.n):
|
|
|
+ dx, dy = self.g.x, (-1 * self.g.y) % self.p
|
|
|
+ tmpG = self.g.copy()
|
|
|
+ self.n = 1
|
|
|
+ while True:
|
|
|
+ self.n += 1
|
|
|
+ tmpG = tmpG + self.g
|
|
|
+ if tmpG.x == dx and tmpG.y == dy:
|
|
|
+ self.n += 1
|
|
|
return
|
|
|
|
|
|
- def setupG(self, processCallback = None):
|
|
|
- percent = 0
|
|
|
- for x in range(self.n, 0, -1):
|
|
|
- if processCallback is not None:
|
|
|
- dPercent = round(100 - x * 100 / self.n, 5)
|
|
|
- if dPercent != percent:
|
|
|
- percent = dPercent
|
|
|
- processCallback(percent)
|
|
|
- p1, p2 = self.pointsCurve(x)
|
|
|
- if p1.isInCurve():
|
|
|
- self.g = p1
|
|
|
- #print(p1.coords(), p1.isInCurve())
|
|
|
- #print(p2.coords(), p2.isInCurve())
|
|
|
+ # Выбор и установка случайной точки g
|
|
|
+ def setupGAuto(self):
|
|
|
+ x = random.randrange(1, self.p - 1)
|
|
|
+ p1, p2 = self.searchClosePoints(x)
|
|
|
+ if p1.isInCurve():
|
|
|
+ self.g = p1
|
|
|
+ elif p2.isInCurve():
|
|
|
+ self.g = p2
|
|
|
+
|
|
|
+ # Поиск близлежащих точек по x
|
|
|
+ def searchClosePoints(self, x):
|
|
|
+ if x >= self.p:
|
|
|
+ x = self.p - 1
|
|
|
+ if x < 0:
|
|
|
+ x = 0
|
|
|
+ kx = x
|
|
|
+ while True:
|
|
|
+ if x >= self.p and kx < 0:
|
|
|
+ return self.point()
|
|
|
+ # Поиск вправо
|
|
|
+ if x <= self.p:
|
|
|
+ p1, p2 = self.pointsCurve(x)
|
|
|
+ if p1.isInCurve():
|
|
|
+ return p1, p2
|
|
|
+ x += 1
|
|
|
+ # Поиск влево
|
|
|
+ if kx <= 0:
|
|
|
+ p1, p2 = self.pointsCurve(kx)
|
|
|
+ if p1.isInCurve():
|
|
|
+ return p1, p2
|
|
|
+ kx -= 1
|
|
|
+ return self.point()
|
|
|
|
|
|
- return
|
|
|
|
|
|
def point(self, x = None, y = None):
|
|
|
return Point(
|
|
@@ -91,7 +108,7 @@ class Curve:
|
|
|
# Обратное деление по модулю p кривой
|
|
|
def inverseMod(self, k, point):
|
|
|
if k == 0:
|
|
|
- raise ZeroDivisionError('division by zero')
|
|
|
+ raise ZeroDivisionError('Деление на 0 невозможно!!!')
|
|
|
if k < 0:
|
|
|
# k ** -1 = p - (-k) ** -1 (mod p)
|
|
|
return point - self.inverseMod(-k, point)
|
|
@@ -105,71 +122,127 @@ class Curve:
|
|
|
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
|
|
|
- #assert gcd == 1
|
|
|
- #assert (k * x) % p == 1
|
|
|
return x % point
|
|
|
|
|
|
def randomKeypair(self):
|
|
|
- keyPriv = random.randrange(1, self.n)
|
|
|
+ keyPriv = random.randrange(1, self.n - 1)
|
|
|
+ print(keyPriv)
|
|
|
+ keyPub = self.g * keyPriv
|
|
|
+ return keyPriv, keyPub
|
|
|
+
|
|
|
+ def keypair(self, keyPriv):
|
|
|
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)
|
|
|
+
|
|
|
+
|
|
|
#################################
|
|
|
-'''
|
|
|
-c = Curve(
|
|
|
- p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
|
|
|
- a = 0,
|
|
|
- b = 7,
|
|
|
- gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
|
|
|
- gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8,
|
|
|
- n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141,
|
|
|
- h = 1
|
|
|
-)
|
|
|
-
|
|
|
-c = Curve(
|
|
|
- p = 6277101735386680763835789423207666416083908700390324961279,
|
|
|
- a = -3,
|
|
|
- b = 2455155546008943817740293915197451784769108058161191238065,
|
|
|
- gx = 602046282375688656758213480587526111916698976636884684818,
|
|
|
- gy = 174050332293622031404857552280219410364023488927386650641,
|
|
|
- n = 6277101735386680763835789423176059013767194773182842284081,
|
|
|
- h = 1
|
|
|
-)
|
|
|
-'''
|
|
|
-
|
|
|
-c = Curve(
|
|
|
- p = 2 ** 20,
|
|
|
- a = 5,
|
|
|
- b = 4,
|
|
|
- gx = 2,
|
|
|
- gy = 2,
|
|
|
- n = 54534432,
|
|
|
- h = 1
|
|
|
-)
|
|
|
-
|
|
|
-if c.isSingular():
|
|
|
- print('Кривая сингулярна')
|
|
|
- exit(0)
|
|
|
-
|
|
|
-def process(percent):
|
|
|
- print(percent)
|
|
|
-
|
|
|
-c.setupN()
|
|
|
-c.setupG(process)
|
|
|
-print(c.n)
|
|
|
-
|
|
|
-aPriv, aPub = c.randomKeypair()
|
|
|
-bPriv, bPub = c.randomKeypair()
|
|
|
-
|
|
|
-print(hex(aPriv))
|
|
|
-print(aPub.show())
|
|
|
-
|
|
|
-#aS = scalar_mult(alice_private_key, bob_public_key)
|
|
|
-aS = bPub * aPriv
|
|
|
-bS = aPub * bPriv
|
|
|
-
|
|
|
-print(aS.show())
|
|
|
-print(bS.show())
|
|
|
+
|
|
|
+# Тестирование
|
|
|
+if __name__ == '__main__':
|
|
|
+
|
|
|
+ # Создание объекта эллиптической кривой (кривая из исходников openssl)
|
|
|
+ '''
|
|
|
+ cur = Curve(
|
|
|
+ # Размер конечного поля
|
|
|
+ p = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,
|
|
|
+ # Коэффиценты
|
|
|
+ a = 0,
|
|
|
+ b = 7,
|
|
|
+ # Координаты точки, определяющей подгруппу
|
|
|
+ gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
|
|
|
+ gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8,
|
|
|
+ # Размер подгруппы
|
|
|
+ n = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141,
|
|
|
+ # Кофактор подгруппы
|
|
|
+ h = 1
|
|
|
+ )
|
|
|
+ '''
|
|
|
+ cur = Curve(
|
|
|
+ p = searchPrime(2 ** 18),
|
|
|
+ a = 1550,
|
|
|
+ b = 7840
|
|
|
+ )
|
|
|
+
|
|
|
+ print('setup g')
|
|
|
+ cur.setupGAuto()
|
|
|
+ print('g', cur.g.coords(), cur.g.isInCurve())
|
|
|
+ print('setup n')
|
|
|
+ cur.setupN()
|
|
|
+ print(cur.p, cur.n)
|
|
|
+
|
|
|
+ print(cur.n, cur.g.coords(), cur.g.isInCurve())
|
|
|
+
|
|
|
+ k1, p1 = cur.keypair(10)
|
|
|
+ print(k1, p1.coords())
|
|
|
+
|
|
|
+ k2, p2 = cur.keypair(110)
|
|
|
+ print(k2, p2.coords())
|
|
|
+
|
|
|
+ #exit(0)
|
|
|
+
|
|
|
+ # В зашифрованном обмене данными принимают участие 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)
|
|
|
+ print(p1KeySecret.coords())
|
|
|
+
|
|
|
+ # Расчет секретного ключа п2
|
|
|
+ p2KeySecret = cur.pointSecret(p2KeyPriv, p1KeyPub)
|
|
|
+ print(p2KeySecret.coords())
|
|
|
+
|
|
|
+ # Покажем, что полученные секретные ключи идентичны у п1 и п2
|
|
|
+ print(p1KeySecret.isEqual(p2KeySecret))
|
|
|
+
|
|
|
+ #exit(0)
|
|
|
+
|
|
|
+ # Далее п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)
|