Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Commit

Permalink
Ensure VRF uniqueness
Browse files Browse the repository at this point in the history
Fixes #567

VRF uniqueness could be violated because the VRF output itself was not
included in the the computation of `s`, the commitment to the VRF and
zero knowledge proof.
  • Loading branch information
gdbelvin committed Apr 26, 2017
1 parent a7e44aa commit f6c1246
Showing 1 changed file with 11 additions and 7 deletions.
18 changes: 11 additions & 7 deletions core/crypto/vrf/p256/p256.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,18 @@ func (k PrivateKey) Evaluate(m []byte) (vrf, proof []byte) {
// H = H1(m)
hx, hy := H1(m)

// VRF_k(m) = [k]H
vrfx, vrfy := params.ScalarMult(hx, hy, k.D.Bytes())

// G is the base point
// s = H2(m, [r]G, [r]H)
// s = H2(m, [r]G, [r]H, [k]H)
gRx, gRy := params.ScalarBaseMult(r)
hRx, hRy := params.ScalarMult(hx, hy, r)
var b bytes.Buffer
b.Write(m)
b.Write(elliptic.Marshal(curve, gRx, gRy))
b.Write(elliptic.Marshal(curve, hRx, hRy))
b.Write(elliptic.Marshal(curve, vrfx, vrfy))
s := H2(b.Bytes())

// t = r−s*k mod N
Expand All @@ -145,14 +149,13 @@ func (k PrivateKey) Evaluate(m []byte) (vrf, proof []byte) {
buf.Write(make([]byte, 32-len(t.Bytes())))
buf.Write(t.Bytes())

// VRF_k(m) = [k]H
vrfx, vrfy := params.ScalarMult(hx, hy, k.D.Bytes())
return elliptic.Marshal(curve, vrfx, vrfy), buf.Bytes()
}

// Verify asserts that vrf is the hash of proof and the proof is correct
func (pk *PublicKey) Verify(m, vrf, proof []byte) error {
// verifier checks that s == H2(m, [t]G + [s]([k]G), [t]H1(m) + [s]VRF_k(m))
// verifier checks that
// s == H2(m, [t]G + [s]([k]G), [t]H1(m) + [s]VRF_k(m), VRF_k(m))
vrfx, vrfy := elliptic.Unmarshal(curve, vrf)
if vrfx == nil {
return ErrInvalidVRF
Expand All @@ -177,13 +180,14 @@ func (pk *PublicKey) Verify(m, vrf, proof []byte) error {
vSx, vSy := params.ScalarMult(vrfx, vrfy, s)
h1TKSx, h1TKSy := params.Add(hTx, hTy, vSx, vSy)

// H2(m, [t]G + [s]([k]G), [t]H + [s]VRF)
// = H2(m, [t+ks]G, [t+ks]H)
// = H2(m, [r]G, [r]H)
// H2(m, [t]G + [s]([k]G), [t]H + [s]VRF, VRF)
// = H2(m, [t+ks]G, [t+ks]H, VRF)
// = H2(m, [r]G, [r]H, VRF)
var b bytes.Buffer
b.Write(m)
b.Write(elliptic.Marshal(curve, gTKSx, gTKSy))
b.Write(elliptic.Marshal(curve, h1TKSx, h1TKSy))
b.Write(elliptic.Marshal(curve, vrfx, vrfy))
h2 := H2(b.Bytes())

// Left pad h2 with zeros if needed. This will ensure that h2 is padded
Expand Down

0 comments on commit f6c1246

Please sign in to comment.