I2P: Подпись И Проверка Eddsa

В предыдущая статья рассмотрена реализация самой кривой Ed25519, операции сложения и умножения на число, восстановление второй координаты.

В этой статье рассматривается, как эффективно использовать эти операции для электронной подписи сообщений и работы в I2P.



Алгоритм подписи EdDSA

В отличие от RSA, где закрытый и открытый ключ могут использоваться напрямую, здесь приходится использовать более сложную схему и вводить некоторый дополнительный объект. EdDSA концептуально реализует алгоритм ДПО , распространив его на случай кривых.

Подпись представляет собой пару чисел (R, S), для EdDSA длина каждого составляет 32 байта, общая длина подписи — 64 байта.

Подписываются не сами данные, а их хеш.

В качестве хэш-функции используется SHA512. Далее маленькими буквами будут обозначаться цифры, а большими — соответствующая точка кривой, полученной умножением числа на базовую точку В.

Пусть h — хеш подписываемого сообщения, a — секретный ключ, а A — соответствующий открытый ключ (A = a*B).

Давайте возьмем случайное число r и посчитаем R = r*B и s = r+h*a. Пара (R,s) будет подписью, где R представлен координатой y. При проверке подписи получатель знает A и h и ему необходимо проверить истинность (R,s).

Для этого проверяется равенство: s*B = R+h*A. Действительно (r+h*a)*B = r*B+h*a*B = R+h*A.

I2P: подпись и проверка EdDSA

Обратите внимание, что s вычисляется непосредственно на основе секретного ключа, а не сгенерированной им точки, поэтому ошибки в реализации могут привести к его немедленной компрометации.

В частности, неудачный выбор р.

Чтобы избежать этого, Бернштейн предлагает вычислять r как хеш половины хеша секретного ключа, объединенного с подписываемыми данными, но выбор r каким-либо другим способом не нарушит алгоритм, то есть сами значения подписи будут другими, но результат проверки будет тот же.

Будем вычислять r, как предлагает Бернштейн и как это сделано в официальном I2P.

Ээффективная реализация умножения

Для дальнейших расчетов понадобится ранее неиспользованный параметр кривой l=

I2P: подпись и проверка EdDSA

, такой, что l*B=0. Из этого равенства сразу следует, что значение множителя перед точкой не должно превышать l, иначе это приведет лишь к увеличению объема вычислений.

Если множитель превышает l, то его нужно брать по модулю, в частности значение h, которое представляет собой 64-байтовый хэш SHA512. Отсюда, в свою очередь, следует, что множитель в операции умножения не превышает 32 байт и старший бит всегда равен нулю.

Как видно из формул, для подписи требуется одно умножение на базовую точку, а для проверки подписи необходимо два умножения: одно на базовую точку, а второе на открытый ключ.

Для базовой точки имеет смысл заранее рассчитать результат умножения на разные коэффициенты.

Самым простым является ряд (В, 2*В, 4*В, 8*В, .

) общим числом 255 точек, что позволяет исключить операцию удвоения на каждом шаге.

Можно пойти дальше и разложить множитель не по степени двойки, а по степени 16, и на каждые 4 бита множителя добавить к результату расчетную точку из массива.

Для этого вам потребуется посчитать и сохранить 32*2*16 точек, но делается это один раз за время всей работы.

Таким образом, умножение на B сокращается ровно до 64 сложений и подписание сообщения осуществляется быстро.

Вот как это выглядит в коде.

   

EDDSAPoint res {zero, one}; for (int i = 0; i < 32; i++) {

Теги: #C++ #i2p #Ed25519 #Криптография #программирование #i2p
Вместе с данным постом часто просматривают: