diff --git a/driver/gurvy/bls12381/bls12-381.go b/driver/gurvy/bls12381/bls12-381.go index b2b0b93..90d5865 100644 --- a/driver/gurvy/bls12381/bls12-381.go +++ b/driver/gurvy/bls12381/bls12-381.go @@ -625,13 +625,12 @@ func (c *Curve) NewZrFromBigInt(i *big.Int) driver.Zr { } func (c *Curve) NewRandomZr(rng io.Reader) driver.Zr { - res := &Zr{} - _, err := res.val.SetRandom() + bi, err := rand.Int(rng, &c.Modulus) if err != nil { panic(err) } - return res + return &Zr{val: *new(fr.Element).SetBigInt(bi)} } func (c *Curve) HashToZr(data []byte) driver.Zr { diff --git a/math_test.go b/math_test.go index aa300c8..3969070 100644 --- a/math_test.go +++ b/math_test.go @@ -949,3 +949,22 @@ func Test381BBSCompat(t *testing.T) { hk = canonical.HashToG1WithDomain([]byte("CD"), []byte("EF")) assert.Equal(t, hg.Bytes(), hk.Bytes()) } + +// TestNewRandomZrHonorsReader verifies that NewRandomZr draws from the +// caller-supplied io.Reader on every curve, so a deterministic reader yields +// deterministic scalars (a driver that ignores rng fails the same-seed check). +func TestNewRandomZrHonorsReader(t *testing.T) { + for _, curve := range Curves { + name := CurveIDToString(curve.curveID) + + a := curve.NewRandomZr(mathrand.New(mathrand.NewSource(0x5eed))) + b := curve.NewRandomZr(mathrand.New(mathrand.NewSource(0x5eed))) + assert.True(t, a.Equals(b), + "curve %s: NewRandomZr ignores the caller's io.Reader "+ + "(identical seed produced different scalars)", name) + + d := curve.NewRandomZr(mathrand.New(mathrand.NewSource(0xd1ff))) + assert.False(t, a.Equals(d), + "curve %s: NewRandomZr gave identical scalars for different seeds", name) + } +}