Как подписать ключ curve25519 в golang?
Я пытаюсь реализовать алгоритм X3DH из Signal in Go. Однако я застрял на том, как подписать PreKey с публичной подписью.
Согласно спецификациям это должен быть ключ X25519. Глядя на предыдущие реализации на Github, они создали[32]byte
ключ от curve25519
пакет, а затем преобразовал его в ed25519
ключ, а затем подписал его.
Однако пакеты, которые они использовали для преобразования, устарели (github.com/agl/ed25519
). Следовательно, мне либо нужно иметь возможность конвертировать ключи вed25519
так что я могу подписать их текущим ed25519
пакет (golang.org/x/crypto/25519
) или реализовать функцию подписи и проверки для curve25519
ключи.
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, обсуждающего эту тему.
Он принимает открытый ключ 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"