Вторая часть про ECC!
Так вот, мы установили, что с точками на кривой можно выполнять математические операции и это, на самом деле, принципиально важный момент, связанный с получением открытого ключа. В частности, две точки можно складывать и результатом будет другая точка на кривой. Как именно сложение происходит визуально, можно также увидеть вот на этом сервисе
https://www.desmos.com/calculator/ialhd71we3 В частности, на нём вы увидите две точки - оранжевую и синюю, - через которые проведена прямая. Третья точка чёрного цвета, где эта прямая пересекает кривую, и есть результат сложения (только заметьте, что эта точка инвертирована относительно оси X и финальный результат оказывается по другую сторону).
Какие там используются формулы для сложения точек, вы можете посмотреть в умных книжках, но нас это не сильно интересует. Важно то, что этот подход мы можем использовать для получения открытого ключа. Алгоритм выглядит так:
- На кривой задаётся изначальная точка G, которая называется генераторной. Про неё ещё потом скажу пару слов в третьей части. Важно то, что для конкретного алгоритма эта точка известна абсолютно всем: к примеру, для secp256k1 её координаты равны
02 79BE667E F9DCBBAC 55A06295 CE870B07 029BFCDB 2DCE28D9 59F2815B 16F81798. Вы можете спросить, а почему тут только одна координата, но про это будет позднее. Пока просто поверьте, что это координаты точки по двум осям, только в сжатом виде.
- Мы можем сложить эту точку саму с собой - как ни странно, это тоже допустимо. В результате мы получим новую точку A, которую можно записать простым выражением
A = G + G. Ну, а коль скоро у нас есть сложение, то и умножение мы тоже можем сделать, то есть
A = 2 * G. Кстати, на мой скромный взгляд, во многих руководствах вот этому моменту вообще не уделяется внимания. Часто пишут в духе "возьмём две точки, проведём прямую, получим третью". Но, пардон, изначально-то генераторная точка одна - откуда тогда взялась ещё и вторая?
- Затем мы можем посчитать точку B путём сложения G с уже посчитанной точкой A.
B = G + A = G + 2 * G = 3 * G.
- Guess what: мы можем продолжать эту операцию сколько угодно раз. Проделайте эти вычисления самостоятельно вот на этом калькуляторе
https://andrea.corbellini.name/ecc/interactive/modk-add.html введя параметры
a = 0,
b = 7,
p = 17 (маленькое поле для простоты, но помните, что в реальной жизни оно гигантское). Затем просто задайте координаты для обеих точек в
(15, 13) (в калькуляторе эти точки названы P и Q, но суть не меняется) и вы увидите, что результатом сложения выступит точка
(2, 10). Потом можете повторить сложение
(15, 13) и
(2, 10), и так далее.
Вспоминается старый анекдот: куда мы попадём, если будем долго бурить землю на экваторе? Видимо, в сумасшедший дом. Тут можно задать тот же вопрос: где мы окажемся, если будем повторять это умножение и, самое главное, нафига вообще это нужно?
- Ответ на первый вопрос очень простой: в конце концов мы окажемся в какой-то точке на кривой, обозначенной P, у которой также есть координаты x и y, причём выражены они тоже целыми числами.
- Ответ на второй вопрос тоже не сильно сложный: координаты финальной точки P будут выступать открытым ключом. Да, это два числа, но мы можем просто слепить их воедино. К примеру, для Ethereum каждая координата имеет размерность 256 бит, значит две координаты дают размерность 512 бит - это и есть размер открытого ключа в несжатом виде.
Ладно, а где тогда закрытый ключ? А закрытый ключ, дорогие друзья, - это то число, на которое мы умножаем G. Скажем, в примере выше у нас получилось, что
B = 3 * G, значит закрытый ключ k равен 3. Естественно, это очень простой пример, а в реальности же закрытые ключи лежат в диапазоне от
1 до
2 ** 256 - 1, то есть опять же числа нереально здоровые. Закрытый ключ можно получить хотя бы из мнемонической фразы, которая пропущена через тот же keccak256 - так как алгоритм гарантирует, что выходное шестнадцатиричное число будет меньше, чем
2 ** 256, то нас это прекрасным образом устраивает (хотя схемы могут быть сложнее).