Рейтинг:1

Как найти целую точку кривой ec в заданном диапазоне?

флаг it

Я изучал основы ecc и обнаружил, что примеры из Интернета либо используют непрерывную кривую домена, либо используют очень маленькое простое число. п как 17 в дискретном домене, чтобы показать точки.

Мне очень любопытно, если я смогу найти точку с действительно большим п на практике. Например, secp256k1 использует очень большой п=2^256–2^32–977 в домене (p,a,b,G,n,h).

Ниже приведен код Python, который я использую для вычета возможного целого числа y из решения уравнения с диапазоном целых чисел. Икс. К моему удивлению, нет находки даже в диапазоне 1 миллион!

Итак, мой вопрос: правильный ли код ниже? А во-вторых, если это правильно или исправлено каким-то настоящим экспертом, то в каком диапазоне значений мне попробовать?

P.S. Мне интересно, как точка генератора г тоже выбирается. Но для этого может потребоваться более глубокое понимание темы.

импортировать математику

# secp256k1
# у**2 = х**3 + 7 (по модулю р)
Р = 2**256 - 2**32 - 977
А = 0
В = 7

# нист P256
P = 115792089210356248762697446949407573530086143415290314195533631308867097853951
А = -3
B = 41058363725152142129326129780047268409114441015993725554835256314039467401291

определение in_curve(x):
    кривая = х**3 + А*х + В
    y_float = math.sqrt (кривая)
    если abs(math.modf(y_float)[0]) < 0,0001 или \
          (1 - абс (math.modf (y_float) [0]) < 0,0001):
        # печать (y_float)
        # ошибка: y_int = int(math.modf(y_float)[1])
        y_int = int (круглый (y_float))
        если y_int * y_int == (кривая):
            печать (y_int)
            вернуть y_int
    возврат Нет
 
для x в диапазоне (1, 1000000):
    у = in_curve (х)
    если y не None:
        напечатать (х, у)

Обновление 1

Предыдущий код неверен, так как sqrt() с плавающей запятой вызовет недопустимую ошибку при преобразовании обратно в целое число.

Но после замены math.sqrt() к math.isqrt(), это все еще не делает вещи разумными.

Обновление 2

Спасибо за советы от всех ответивших в теме. Используя точку генератора для проверки моего алгоритма, я теперь ясно знаю, почему я терпел неудачу.

Дело в том, что помимо использования % для всех умножений и сложений я должен также используйте модульный квадратный корень, чтобы найти решение, вместо целый квадратный корень вместе с %. Это абсолютно неправильное использование % наверняка.

Модифицированный код проходит тест с некоторыми тестовыми векторами.

импорт модульный_sqrt
# например Я использовал код из https://eli.thegreenplace.net/2009/03/07/computing-modular-square-roots-in-python.
# пожалуйста, спросите разрешения, если использование выходит за рамки образовательного хобби, и всегда указывайте заслугу порядочного человека ;-)

# nist P256, взято с https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186-draft.pdf
P = 115792089210356248762697446949407573530086143415290314195533631308867097853951
А = -3
B = 41058363725152142129326129780047268409114441015993725554835256314039467401291
Gx = 48439561293906451759052585252797914202762949526041747995844080717082404635286
Гр = 36134250956749795798585127919587881956611106672985015071877198253568414405109

защита get_y_in_curve(x):
    у2 = х**3 + А*х + В
    y_int = модульный_sqrt (y2, P)
    если y_int и ((y_int * y_int) % P) == (y2 % P):
        вернуть y_int
    возврат Нет

утверждать get_y_in_curve(Gx) == Gy
fgrieu avatar
флаг ng
Код неверный. Основная проблема заключается в том, что криптосистема Elliptic Curve не работает с $x$ и $y$ в бесконечном наборе. Он использует [конечное поле](https://en.wikipedia.org/wiki/Finite_field). secp256k1 использует поле $\mathbb F_p$, а также [кольцо целых чисел по модулю](https://en.wikipedia.org/w/index.php?title=Ring_of_integers_modulo_n) $p$. Таким образом, код должен вычислять свою `кривую`, уменьшенную по модулю `P`, и вычислять (когда она существует) модульный квадратный корень из нее; см. [это] (https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm) для одного метода. Улучшите или закройте вопрос.
Match Man avatar
флаг it
@fgrieu Да, я понял свою ошибку сразу после того, как Даниэль указал на нее. Теперь вопрос обновлен с исправленным алгоритмом. Вы хотите, чтобы я закрыл вопрос, поскольку он *был* неправильным? Или оставьте его как пример того, как все должно быть сделано в конечном пространстве ECC. Или даже просто, как что-то может пойти не так при переходе от «кривой» бесконечного пространства к конечному пространству? :)
fgrieu avatar
флаг ng
Обновленный вопрос в порядке. Поскольку ответ помог, я думаю, лучше всего принять его, и все будет хорошо. Обратите внимание на новый код: было бы более элегантно переименовать `curve` в `y2`; вычислить его по модулю `P` ранее (например, `y2 = (x**3 + A*x + B) % P` или `y2 = (pow(x, 3, P) + A*x + B) % P )`; и повторно использовать его в `y_int = module_sqrt(y2)` и `if ((y_int * y_int) % P) == y2:`. Не сразу понятно, что делает `modular_sqrt` в случае сбоя. Независимо от того, допустимо ли использование `modular_sqrt` другого человека в контексте? Это вовлеченная часть!
Match Man avatar
флаг it
Код рефакторинг. module_sqrt вернет 0 в случае ошибки, и новый код также добавил эту проверку. Я не использую код Эли напрямую, а ссылаюсь на его код в качестве примера.
Рейтинг:3
флаг ru

Я не совсем уверен, что вы имеете в виду под $р$ и я не уверен, что вы имели в виду, чтобы ваш код распечатывался.

Однако похоже, что вы пытаетесь найти целочисленные точки на эллиптической кривой. $у^2=х^3+7$ исчерпав $х$ значения, и я не могу обнаружить ошибку, кроме оператора печати. НО Зигель показал, что в общем случае эллиптические кривые над рациональными числами имеют только конечное число целочисленных точек, и мы ожидаем, что они действительно будут очень редкими. Фактически для кривая, которую вы выбрали целых точек вообще нет.

Возможно, вы пытаетесь найти целые числа $х$ и $у$ так что $ у ^ 2 \ эквив х ^ 3 + 7 \ pmod p $ для некоторого большого простого числа $р$. В этом случае вы должны взять квадратный корень по модулю $р$ а не над реальными числами. Это использует другой расчет. Выбор большого простого числа $р$ а потом брать любой $х$ значение имеет примерно 50% шанс найти подходящее $у$ извлекая модульный квадратный корень из $х^3+17$.

Match Man avatar
флаг it
Я добавил значение `p` в вопросе. Он настолько велик, что мне не нужно выполнять модуляцию с каким-то малым числом вроде 1 миллиарда... > На самом деле для выбранной вами кривой вообще нет целых точек.
Daniel S avatar
флаг ru
Ага, понятно. В этом случае, если вы попытаетесь сгенерировать точки без использования какой-либо модульной арифметики, это не сработает, потому что тогда они будут целыми точками, а на этой кривой их нет. Обратите внимание, что «маленькие» числа, которые не являются идеальными квадратами, могут иметь квадратные корни по модулю $p$, если кто-то готов использовать модульную арифметику.
Match Man avatar
флаг it
Вы имеете в виду, что я должен изменить if y_int * y_int == (x ^ 3 + 7) на if y_int * y_int == (x ^ 3 + 7) % P, где P = 2 ^ 256–2 ^ 32– 977? Насколько я понимаю, secp256k1 определяется над â¤p, поэтому предыдущее вычисление с плавающей запятой предназначено только для того, чтобы определить, достаточно ли близко y, чтобы быть целым числом. Есть действительно много возможных кандидатов на 1 миллион, но ни один из них на самом деле не один...
Daniel S avatar
флаг ru
Нет. Я имею в виду, что (используя тот факт, что $p\equiv 3\pmod 4$) вы должны заменить y_float=math.sqrt(x^3+7) на y_int=pow(x^3+7,(p+ 1)/4,p), а затем проверьте, соответствует ли y_int*y_int==(x^3+7)%p. Это не даст вам малое значение $y$, но не существует решения с малым значением как $x$, так и $y$. Посмотрите ссылку на вычисление квадратных корней по модулю $p$.
Match Man avatar
флаг it
Понятно. Теперь вопрос обновлен с правильной работой. Спасибо.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.