Как подписать ключ curve25519 в golang?

Я пытаюсь реализовать алгоритм X3DH из Signal в Go. Однако я застрял в том, как подписать Public Signed PreKey.

Согласно спецификациям, это должен быть ключ X25519. Глядя на предыдущие реализации на Github, они сгенерировали ключ [32]byte из пакета curve25519, а затем преобразовали его в ключ ed25519, а затем подписали его.

Однако пакеты, которые они использовали для преобразования, устарели (github.com/agl/ed25519). Поэтому мне нужно либо преобразовать ключи в ed25519, чтобы я мог подписать их текущим пакетом ed25519 (golang.org/x/crypto/25519), либо реализовать функцию подписи и проверки для ключей curve25519.


person Jadefox10200    schedule 26.06.2020    source источник


Ответы (2)


Клавиши Ed25519 можно легко преобразовать в клавиши X25519, искривленная кривая Эдвардса, используемая Ed25519, и кривая Монтгомери, используемая X25519, birationally эквивалентны.

Точки на кривой Эдвардса обычно обозначаются как (x, y), а точки на кривой Монтгомери обычно обозначаются как (u, v).

Вам не нужна библиотека для преобразования, это очень просто...

(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)
(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))

Вот отличный блог Филиппо Вальсорда, руководителя службы безопасности Golang. в Google, обсуждая эту тему.

person Woodstock    schedule 26.06.2020
comment
Я видел эту статью ранее и столкнулся с проблемой. В статье говорится: Следует упомянуть, что есть прецедент преобразования ключей между двумя кривыми: Signal XEd25519. Однако они делают противоположное тому, что мы хотим, они используют ключ X25519 для EdDSA. Это связано с проблемой: открытый ключ X25519 не содержит координату v, поэтому он может сопоставляться с двумя ключами Ed25519. Они решают эту проблему, определяя бит знака точки Эдвардса равным 0, а затем отрицая секретный скаляр Эдвардса, если он генерирует точку с положительным знаком. Скажу честно: я не понимаю, как это реализовать. - person Jadefox10200; 28.06.2020
comment
Смотрите ответ, который я разместил ниже. Это то, что я смог сделать в конце, но с использованием кода с golang.org/x/crypto/ed25519/internal. Опять же, если честно, я не полностью знаком с тонкими деталями этого процесса преобразования и очень признателен за ваш вклад, поскольку мне не ясно, как я мог бы поместить вышеизложенное в код. - person Jadefox10200; 28.06.2020
comment
@ Jadefox10200, так где ты сейчас? На какой части ты застрял? Это может быть сложно, хорошо ... - person Woodstock; 28.06.2020
comment
Хотя приведенная ниже функция работает, я на самом деле не совсем понимаю, что она делает. Функция проверки действительно проверяет подпись, но поскольку я не понимаю, как она это делает, я не уверен, что правильно реализовал процесс. Ваш ответ наверняка помог, и сейчас я трачу время на изучение, чтобы попытаться понять, как это работает. Я бы предпочел реализовать что-то самому, а не срывать код с внутренней библиотеки. - person Jadefox10200; 29.06.2020

Это берет открытый ключ curve25519 и преобразует его в открытый ключ ed25519. Я не писал этот код, но, кажется, делаю то, о чем говорит выше Вудсток. Приветствуется дополнительная информация:

func Verify(publicKey [32]byte, message []byte, signature *[64]byte) bool {

publicKey[31] &= 0x7F

/* Convert the Curve25519 public key into an Ed25519 public key.  In
particular, convert Curve25519's "montgomery" x-coordinate into an
Ed25519 "edwards" y-coordinate:
ed_y = (mont_x - 1) / (mont_x + 1)
NOTE: mont_x=-1 is converted to ed_y=0 since fe_invert is mod-exp
Then move the sign bit into the pubkey from the signature.
*/

var edY, one, montX, montXMinusOne, montXPlusOne FieldElement
FeFromBytes(&montX, &publicKey)
FeOne(&one)
FeSub(&montXMinusOne, &montX, &one)
FeAdd(&montXPlusOne, &montX, &one)
FeInvert(&montXPlusOne, &montXPlusOne)
FeMul(&edY, &montXMinusOne, &montXPlusOne)

var A_ed [32]byte
FeToBytes(&A_ed, &edY)

A_ed[31] |= signature[63] & 0x80
signature[63] &= 0x7F

var sig = make([]byte, 64)
var aed = make([]byte, 32)

copy(sig, signature[:])
copy(aed, A_ed[:])

return ed25519.Verify(aed, message, sig)

Здесь используются функции с golang.org/x/crypto/ed25519/internal.

person Jadefox10200    schedule 28.06.2020