Post
Topic
Board Кодеры
Re: Вопрос по эллипт кривой, непонятен ОДИН ша
by
Ctrl_A
on 01/06/2022, 16:18:58 UTC
При использовании 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 означает игнорирование "нулевых" значений).

К сожалению, как и в случае с разложением приватного ключа в степенной ряд, для "больших" приватников" библиотека рулит". Sad
Видимо, её разработчик был большим спецом.

Программка второго варианта (без защиты от кривых рук):

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.
Претензии по качеству софта не принимаются - я не программист.