Skip to content

Commit e9c8209

Browse files
liamsimasomel
authored andcommitted
Fix VRF uniqueness violation
* renamed c, cH, ... with s, sH it is called s in the CONIKS paper/in KT (in the cfrg draft and other literature it is called c, though) * Adopt VRF to update in CONIKS paper - add unique identifier: also hash h=H1(m), g^x and h^x (the VRF output) and not only with random nonce r (g^r, h^r); additionally hash m into H2 (as before) - like in the paper add the base-point and public-key - skip outdated test-vectors - unrelated: remove formatting version of test-output where no placeholder is used fixes #175
1 parent 77350b6 commit e9c8209

File tree

3 files changed

+66
-36
lines changed

3 files changed

+66
-36
lines changed

crypto/internal/ed25519/edwards25519/const.go

+14
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@ var A = FieldElement{
2323
486662, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2424
}
2525

26+
var extendedBaseEl = ExtendedGroupElement{
27+
FieldElement{25485296, 5318399, 8791791, -8299916, -14349720, 6939349, -3324311, -7717049, 7287234, -6577708},
28+
FieldElement{-758052, -1832720, 13046421, -4857925, 6576754, 14371947, -13139572, 6845540, -2198883, -4003719},
29+
FieldElement{-947565, 6097708, -469190, 10704810, -8556274, -15589498, -16424464, -16608899, 14028613, -5004649},
30+
FieldElement{6966464, -2456167, 7033433, 6781840, 28785542, 12262365, -2659449, 13959020, -21013759, -5262166},
31+
}
32+
33+
// BaseBytes can be used to hash the base point if necessary
34+
var BaseBytes [32]byte
35+
36+
func init() {
37+
extendedBaseEl.ToBytes(&BaseBytes)
38+
}
39+
2640
var bi = [8]PreComputedGroupElement{
2741
{
2842
FieldElement{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626, -11754271, -6079156, 2047605},

crypto/vrf/vrf.go

+44-28
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,16 @@ func hashToCurve(m []byte) *edwards25519.ExtendedGroupElement {
120120
// same as returned by Compute(m).
121121
func (sk PrivateKey) Prove(m []byte) (vrf, proof []byte) {
122122
x, skhr := sk.expandSecret()
123-
var cH, rH [64]byte
124-
var r, c, minusC, t, grB, hrB, iiB [32]byte
123+
var sH, rH [64]byte
124+
var r, s, minusS, t, gB, grB, hrB, hxB, hB [32]byte
125125
var ii, gr, hr edwards25519.ExtendedGroupElement
126126

127-
hm := hashToCurve(m)
128-
edwards25519.GeScalarMult(&ii, x, hm)
129-
ii.ToBytes(&iiB)
127+
h := hashToCurve(m)
128+
h.ToBytes(&hB)
129+
edwards25519.GeScalarMult(&ii, x, h)
130+
ii.ToBytes(&hxB)
130131

132+
// use hash of private-, public-key and msg as randomness source:
131133
hash := sha3.NewShake256()
132134
hash.Write(skhr[:])
133135
hash.Write(sk[32:]) // public key, as in ed25519
@@ -137,26 +139,32 @@ func (sk PrivateKey) Prove(m []byte) (vrf, proof []byte) {
137139
edwards25519.ScReduce(&r, &rH)
138140

139141
edwards25519.GeScalarMultBase(&gr, &r)
140-
edwards25519.GeScalarMult(&hr, &r, hm)
142+
edwards25519.GeScalarMult(&hr, &r, h)
141143
gr.ToBytes(&grB)
142144
hr.ToBytes(&hrB)
145+
gB = edwards25519.BaseBytes
143146

147+
// H2(g, h, g^x, h^x, g^r, h^r, m)
148+
hash.Write(gB[:])
149+
hash.Write(hB[:])
150+
hash.Write(sk[32:]) // ed25519 public-key
151+
hash.Write(hxB[:])
144152
hash.Write(grB[:])
145153
hash.Write(hrB[:])
146154
hash.Write(m)
147-
hash.Read(cH[:])
155+
hash.Read(sH[:])
148156
hash.Reset()
149-
edwards25519.ScReduce(&c, &cH)
157+
edwards25519.ScReduce(&s, &sH)
150158

151-
edwards25519.ScNeg(&minusC, &c)
152-
edwards25519.ScMulAdd(&t, x, &minusC, &r)
159+
edwards25519.ScNeg(&minusS, &s)
160+
edwards25519.ScMulAdd(&t, x, &minusS, &r)
153161

154162
proof = make([]byte, ProofSize)
155-
copy(proof[:32], c[:])
163+
copy(proof[:32], s[:])
156164
copy(proof[32:64], t[:])
157-
copy(proof[64:96], iiB[:])
165+
copy(proof[64:96], hxB[:])
158166

159-
hash.Write(iiB[:]) // const length: Size
167+
hash.Write(hxB[:])
160168
hash.Write(m)
161169
vrf = make([]byte, Size)
162170
hash.Read(vrf[:])
@@ -169,15 +177,15 @@ func (pkBytes PublicKey) Verify(m, vrfBytes, proof []byte) bool {
169177
if len(proof) != ProofSize || len(vrfBytes) != Size || len(pkBytes) != PublicKeySize {
170178
return false
171179
}
172-
var pk, c, cRef, t, vrf, iiB, ABytes, BBytes [32]byte
180+
var pk, s, sRef, t, vrf, hxB, hB, gB, ABytes, BBytes [32]byte
173181
copy(vrf[:], vrfBytes)
174182
copy(pk[:], pkBytes[:])
175-
copy(c[:32], proof[:32])
183+
copy(s[:32], proof[:32])
176184
copy(t[:32], proof[32:64])
177-
copy(iiB[:], proof[64:96])
185+
copy(hxB[:], proof[64:96])
178186

179187
hash := sha3.NewShake256()
180-
hash.Write(iiB[:]) // const length
188+
hash.Write(hxB[:]) // const length
181189
hash.Write(m)
182190
var hCheck [Size]byte
183191
hash.Read(hCheck[:])
@@ -191,25 +199,33 @@ func (pkBytes PublicKey) Verify(m, vrfBytes, proof []byte) bool {
191199
if !P.FromBytesBaseGroup(&pk) {
192200
return false
193201
}
194-
if !ii.FromBytesBaseGroup(&iiB) {
202+
if !ii.FromBytesBaseGroup(&hxB) {
195203
return false
196204
}
197-
edwards25519.GeDoubleScalarMultVartime(&A, &c, &P, &t)
205+
edwards25519.GeDoubleScalarMultVartime(&A, &s, &P, &t)
198206
A.ToBytes(&ABytes)
207+
gB = edwards25519.BaseBytes
199208

200-
hm := hashToCurve(m)
201-
edwards25519.GeDoubleScalarMultVartime(&hmtP, &t, hm, &[32]byte{})
202-
edwards25519.GeDoubleScalarMultVartime(&iicP, &c, &ii, &[32]byte{})
209+
h := hashToCurve(m) // h = H1(m)
210+
h.ToBytes(&hB)
211+
edwards25519.GeDoubleScalarMultVartime(&hmtP, &t, h, &[32]byte{})
212+
edwards25519.GeDoubleScalarMultVartime(&iicP, &s, &ii, &[32]byte{})
203213
iicP.ToExtended(&iic)
204214
hmtP.ToExtended(&B)
205215
edwards25519.GeAdd(&B, &B, &iic)
206216
B.ToBytes(&BBytes)
207217

208-
var cH [64]byte
209-
hash.Write(ABytes[:]) // const length
210-
hash.Write(BBytes[:]) // const length
218+
var sH [64]byte
219+
// sRef = H2(g, h, g^x, v, g^t·G^s,H1(m)^t·v^s, m), with v=H1(m)^x=h^x
220+
hash.Write(gB[:])
221+
hash.Write(hB[:])
222+
hash.Write(pkBytes)
223+
hash.Write(hxB[:])
224+
hash.Write(ABytes[:]) // const length (g^t*G^s)
225+
hash.Write(BBytes[:]) // const length (H1(m)^t*v^s)
211226
hash.Write(m)
212-
hash.Read(cH[:])
213-
edwards25519.ScReduce(&cRef, &cH)
214-
return cRef == c
227+
hash.Read(sH[:])
228+
229+
edwards25519.ScReduce(&sRef, &sH)
230+
return sRef == s
215231
}

crypto/vrf/vrf_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ func TestHonestComplete(t *testing.T) {
2323
// fmt.Printf("aliceProof: %X\n", aliceProof)
2424

2525
if !pk.Verify(alice, aliceVRF, aliceProof) {
26-
t.Errorf("Gen -> Compute -> Prove -> Verify -> FALSE")
26+
t.Error("Gen -> Compute -> Prove -> Verify -> FALSE")
2727
}
2828
if !bytes.Equal(aliceVRF, aliceVRFFromProof) {
29-
t.Errorf("Compute != Prove")
29+
t.Error("Compute != Prove")
3030
}
3131
}
3232

@@ -69,37 +69,37 @@ func sampleVectorTest(pk PublicKey, aliceVRF, aliceProof []byte, t *testing.T) {
6969

7070
// Positive test case
7171
if !pk.Verify(alice, aliceVRF, aliceProof) {
72-
t.Errorf("TestSampleVectors HonestVector Failed")
72+
t.Error("TestSampleVectors HonestVector Failed")
7373
}
7474

7575
// Negative test cases - try increment the first byte of every vector
7676
pk[0]++
7777
if pk.Verify(alice, aliceVRF, aliceProof) {
78-
t.Errorf("TestSampleVectors ForgedVector (pk modified) Passed")
78+
t.Error("TestSampleVectors ForgedVector (pk modified) Passed")
7979
}
8080
pk[0]--
8181

8282
alice[0]++
8383
if pk.Verify(alice, aliceVRF, aliceProof) {
84-
t.Errorf("TestSampleVectors ForgedVector (alice modified) Passed")
84+
t.Error("TestSampleVectors ForgedVector (alice modified) Passed")
8585
}
8686
alice[0]--
8787

8888
aliceVRF[0]++
8989
if pk.Verify(alice, aliceVRF, aliceProof) {
90-
t.Errorf("TestSampleVectors ForgedVector (aliceVRF modified) Passed")
90+
t.Error("TestSampleVectors ForgedVector (aliceVRF modified) Passed")
9191
}
9292
aliceVRF[0]--
9393

9494
aliceProof[0]++
9595
if pk.Verify(alice, aliceVRF, aliceProof) {
96-
t.Errorf("TestSampleVectors ForgedVector (aliceProof modified) Passed")
96+
t.Error("TestSampleVectors ForgedVector (aliceProof modified) Passed")
9797
}
9898
aliceProof[0]--
9999
}
100100

101101
func TestSampleVectorSets(t *testing.T) {
102-
102+
t.Skip("TODO: generate new test vectors or remove test")
103103
var aliceVRF, aliceProof []byte
104104
var pk []byte
105105

0 commit comments

Comments
 (0)