paulmillr/noble-ed25519

.equals not recognizing equal points

davidspies opened this issue · 4 comments

> curve = require("noble-ed25519");
> q = curve.ExtendedPoint.fromRistrettoBytes(new Uint8Array([78,7,201,185,190,254,158,249,198,210,211,189,204,72,156,195,218,195,144,152,106,35,46,206,165,35,154,201,238,165,26,10]))
> s = 2247802787217874114338511867005927249421637399982938640834856366249165554779n
> t = 6941189895179004434540483659899441803715011564437546499587142614761695797379n

> q.multiply(s * t).equals(q.multiply(s).multiply(t))
false
> var equal = require('deep-equal');
> equal(q.multiply(s * t).toRistrettoBytes(), q.multiply(s).multiply(t).toRistrettoBytes())
true

Then the points are not equal. Something may be wrong, or not wrong, with Ristretto encoding. Are you sure ristretto cannot produce equal result for different points?

I've multiplied both points by 8, so they correspond to the same point in different subgroups:

Point {
  x: 36023053447185773466247172769271652063838456434736402144253643561480906177666n,
  y: 18647976618046270374890936834663882185017422022216761137078734275872740439402n
}

Ristretto's main purpose is to use prime-order subgroup. So i'm not sure you can say those are the same point.

@paulmillr
I'm confused
Shouldn't the .multiply operator be associative? I would think
> q.multiply(s * t).equals(q.multiply(s).multiply(t))
should always return true regardless of what q, s, and t are

@davidspies s * t is higher than curve order which makes it kinda invalid scalar. I'll see if I can add a check for this behavior. In secp256k1 I check for it, not sure why ed25519 was different.