При использовании N = 2 ...
... не программист.
Нашёл другой способ вычисления публичного ключа из приватного, в котором последний раскладывать по степеням совсем не обязательно!
Если приватник выражается 64-значным 16-ричным числом, его можно представить как сумму не более 64-х чисел, каждое из которых
содержит только одно отличное от нуля значение.
Например:
Key = F1F3BE4BDBC7AB23D7BE32B818FD727C31086FC924E8303CBEAA88572D9FAB38
Сумма:
1) F000...............0000
2) 0100...............0000
3) 00F0...............0000
4) 0003...............0000
................................
61) 0000...............A000
62) 0000...............0B00
63) 0000...............0030
64) 0000...............0008
Зная публичные ключи для каждого из указанных слагаемых, искомый публичник для Key будет просто равен их сумме.
Максимальное число слагаемых - 64.
Поскольку интересны только 15 значений (от 1 до F), общая база ключей составит всего 15*64 = 960 элементов.
Пока писал "пробную" программку, пришла идея для уменьшения числа слагаемых (увеличения скорости расчёта)
разбивать приватник не по одному элементу, а по четыре:
Получаем сумму:
1) F1F30000...................00000000
2) 0000BE4B...................00000000
.................................................
15) 00000000...................2D9F0000
16) 00000000...................0000AB38
В этом случае максимальное число слагаемых составит всего 16, а общее количество публичных ключей в базе = 16^4 * 16 - 16 = 1 048 560
(- 16 означает игнорирование "нулевых" значений).
К сожалению, как и в случае с разложением приватного ключа в степенной ряд, для "больших" приватников" библиотека рулит".
Видимо, её разработчик был большим спецом.
Программка второго варианта (без защиты от кривых рук):
import binascii, ecdsa
import datetime
# ----------------------------------- Сложение публичных ключей ------------------------------------
def EC_Add(P, Q):
if P == '0': return Q
if Q == '0': return P
p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
px = int(P[2:66], 16)
py = int(P[66:], 16)
qx = int(Q[2:66], 16)
qy = int(Q[66:], 16)
if (px == qx) and (py == qy):
dydx = (3 * px**2) * pow(2 * py, p - 2, p)
else:
dydx = (qy - py) * pow(qx - px, p - 2, p)
x = (dydx**2 - px - qx) % p
y = (dydx * (px - x) - py) % p
return '04' + hex(x)[2:].zfill(64) + hex(y)[2:].zfill(64)
# --------------------- Публичный ключ от произвольного числа HEX (библиотека) ---------------------
def U_pub(x):
sk = ecdsa.SigningKey.from_string(binascii.unhexlify(x.encode()), curve=ecdsa.SECP256k1)
vk = sk.get_verifying_key()
return '04' + binascii.hexlify(vk.to_string()).decode()
# --------------------------------------------------------------------------------------------------
Max = 115792089237316195423570985008687907852837564279074904382605163141518161494336
simbols = '0123456789abcdef'
Base_pub = dict()
print('Ждите, идёт создание базы публичных ключей ...')
for i in range(16):
for k in range(16):
for m in range(16):
for n in range(16):
for q in range(16):
if (str(simbols[k:k + 1]) + str(simbols[m:m + 1]) + str(simbols[n:n + 1]) + str(simbols[q:q + 1])) != '0000':
Base_pub[str(i * 4 + 1).zfill(2) + str(simbols[k:k + 1]) + str(simbols[m:m + 1]) + str(simbols[n:n + 1]) + str(simbols[q:q + 1])] = U_pub('0' * (i * 4) + (simbols[k:k + 1] + simbols[m:m + 1] + simbols[n:n + 1] + simbols[q:q + 1] + '0' * (60 - i * 4)))
print('Ключей в базе :', len(Base_pub))
PK_0 = int(input('Введите приватный ключ: ("0" - завершение программы) '))
if PK_0 > Max: PK_0 = int(str(PK_0)[:77])
while PK_0 != 0:
MM = int(input('Введите число итераций : '))
date_1 = datetime.datetime.today()
for k in range(MM):
PK = PK_0 + k
hexPrv = hex(PK)[2:66].zfill(64)
Priv_set = set()
P = '0'
for i in range(16):
if hexPrv[i * 4:i * 4 + 4] != '0000':
Priv_set.add(Base_pub[str(i * 4 + 1).zfill(2) + hexPrv[i * 4:i * 4 + 4]])
for i in Priv_set:
P = EC_Add(P, i)
date_2 = datetime.datetime.today()
print('продолжительность :', date_2 - date_1)
print('Key =', PK, '; P =', P)
date_1 = datetime.datetime.today()
for i in range(MM):
PK = PK_0 + k
P = U_pub(hex(PK)[2:66].zfill(64))
date_2 = datetime.datetime.today()
print('продолжительность :', date_2 - date_1)
print('Key =', PK, '; P =', P)
PK_0 = int(input('Введите приватный ключ: ("0" - завершение программы) '))
if PK_0 > Max: PK_0 = int(str(PK_0)[:77])P.S.
Претензии по качеству софта не принимаются - я не программист.