You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In golang/go#20504 (comment)@FiloSottile pointed out that I should use ristretto255 for key exchange with uniform-looking public keys. However it is not super clear what I am supposed to do, and the only example I could find is from libsodium but it has a very different looking API
// -------- First party -------- Send blinded p(x)unsigned charx[crypto_core_ristretto255_HASHBYTES];
randombytes_buf(x, sizeofx);
// Compute px = p(x), a group element derived from xunsigned charpx[crypto_core_ristretto255_BYTES];
crypto_core_ristretto255_from_hash(px, x);
// Compute a = p(x) * g^runsigned charr[crypto_core_ristretto255_SCALARBYTES];
unsigned chargr[crypto_core_ristretto255_BYTES];
unsigned chara[crypto_core_ristretto255_BYTES];
crypto_core_ristretto255_scalar_random(r);
crypto_scalarmult_ristretto255_base(gr, r);
crypto_core_ristretto255_add(a, px, gr);
// -------- Second party -------- Send g^k and a^kunsigned chark[crypto_core_ristretto255_SCALARBYTES];
randombytes_buf(k, sizeofk);
// Compute v = g^kunsigned charv[crypto_core_ristretto255_BYTES];
crypto_scalarmult_ristretto255_base(v, k);
// Compute b = a^kunsigned charb[crypto_core_ristretto255_BYTES];
if (crypto_scalarmult_ristretto255(b, k, a) !=0) {
return-1;
}
// -------- First party -------- Unblind f(x)// Compute vir = v^(-r)unsigned charir[crypto_core_ristretto255_SCALARBYTES];
unsigned charvir[crypto_core_ristretto255_BYTES];
crypto_core_ristretto255_scalar_negate(ir, r);
crypto_scalarmult_ristretto255(vir, ir, v);
// Compute f(x) = b * v^(-r) = (p(x) * g^r)^k * (g^k)^(-r)// = (p(x) * g)^k * g^(-k) = p(x)^kunsigned charfx[crypto_core_ristretto255_BYTES];
crypto_core_ristretto255_add(fx, b, vir);
Anyway I figure since this is Go, maybe the API should be similar to x/crypto/x25519? So I wrote the following test code which seems to be working fine
import (
"crypto/rand""testing"
r255 "github.com/gtank/ristretto255"
)
funcTestKx(t*testing.T) {
seed:=make([]byte, 64)
// party 1rand.Read(seed)
sk1:=r255.NewScalar().FromUniformBytes(seed)
pk1:=r255.NewElement().ScalarBaseMult(sk1) // send pk1.Encode(nil) to party 2// party 2rand.Read(seed)
sk2:=r255.NewScalar().FromUniformBytes(seed)
pk2:=r255.NewElement().ScalarBaseMult(sk2) // send pk2.Encode(nil) to party 1shared1:=r255.NewElement().ScalarMult(sk1, pk2)
shared2:=r255.NewElement().ScalarMult(sk2, pk1)
ifshared1.Equal(shared2) !=1 {
t.Fatal("kx failed")
}
t.Logf("pk1: %x", pk1.Encode(nil))
t.Logf("sk1: %x", sk1.Encode(nil))
t.Logf("pk2: %x", pk2.Encode(nil))
t.Logf("sk2: %x", sk2.Encode(nil))
t.Logf("shared: %x", shared1.Encode(nil))
}
Did I do something stupid and dangerous?
Does the 32-byte encoded pk1 look random and uniform?
x25519 public keys have only 255 bits with the most significant bit of the byte 31 cleared, and x25519 secret keys have only 251 bits with the lower 3 bits of byte 0 and highest bit of byte 31 cleared and bit 6 of byte 31 set. Is there any similarity here for ristretto255 encoded public and secret keys?
How to relate and translate between the above Go code (assuming it's correct) and the libsodium API for interoperability?
It SHOULD be possible for a ristretto255 implementation to change its
underlying curve without causing any breaking change. A ristretto255
implementation MUST be interoperable with any other implementation,
even if that implementation uses a different curve internally. Any
operation on ristretto255 elements that only works correctly or leads
to different results based on the underlying curve is explicitly
disallowed.
Does it mean that if the above key exchange procedure is correct, either party1 or party2 could use a different underlying curve and the key exchange still works?
The text was updated successfully, but these errors were encountered:
FiloSottile
added a commit
to FiloSottile/edwards25519
that referenced
this issue
Sep 28, 2020
In golang/go#20504 (comment) @FiloSottile pointed out that I should use ristretto255 for key exchange with uniform-looking public keys. However it is not super clear what I am supposed to do, and the only example I could find is from libsodium but it has a very different looking API
Anyway I figure since this is Go, maybe the API should be similar to
x/crypto/x25519
? So I wrote the following test code which seems to be working finepk1
look random and uniform?Does it mean that if the above key exchange procedure is correct, either party1 or party2 could use a different underlying curve and the key exchange still works?
The text was updated successfully, but these errors were encountered: