-
Notifications
You must be signed in to change notification settings - Fork 145
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
145 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// Reference: https://datatracker.ietf.org/doc/html/rfc8235#page-6 | ||
// Prove the knowledge of [k] given [k]G, G and the curve where the points reside | ||
package dl | ||
|
||
import ( | ||
"io" | ||
|
||
"github.com/cloudflare/circl/group" | ||
) | ||
|
||
// Input: myGroup, the group we operate in | ||
// Input: R = [kA]DB | ||
// Input: proverLabel, verifierLabel labels of prover and verifier | ||
// Ouptput: (V,r), the prove such that we know kA without revealing kA | ||
func ProveGen(myGroup group.Group, DB, R group.Element, kA group.Scalar, proverLabel, verifierLabel, dst []byte, rnd io.Reader) (group.Element, group.Scalar) { | ||
v := myGroup.RandomNonZeroScalar(rnd) | ||
V := myGroup.NewElement() | ||
V.Mul(DB, v) | ||
|
||
// Hash transcript (D_B | V | R | proverLabel | verifierLabel) to get the random coin | ||
DBByte, errByte := DB.MarshalBinary() | ||
if errByte != nil { | ||
panic(errByte) | ||
} | ||
VByte, errByte := V.MarshalBinary() | ||
if errByte != nil { | ||
panic(errByte) | ||
} | ||
|
||
RByte, errByte := R.MarshalBinary() | ||
if errByte != nil { | ||
panic(errByte) | ||
} | ||
|
||
hashByte := append(DBByte, VByte...) | ||
hashByte = append(hashByte, RByte...) | ||
hashByte = append(hashByte, proverLabel...) | ||
hashByte = append(hashByte, verifierLabel...) | ||
|
||
c := myGroup.HashToScalar(hashByte, dst) | ||
|
||
kAc := myGroup.NewScalar() | ||
kAc.Mul(c, kA) | ||
r := v.Copy() | ||
r.Sub(r, kAc) | ||
|
||
return V, r | ||
} | ||
|
||
// Input: myGroup, the group we operate in | ||
// Input: R = [kA]DB | ||
// Input: (V,r), the prove such that the prover knows kA | ||
// Input: proverLabel, verifierLabel labels of prover and verifier | ||
// Output: V ?= [r]D_B +[c]R | ||
func Verify(myGroup group.Group, DB, R group.Element, V group.Element, r group.Scalar, proverLabel, verifierLabel, dst []byte) bool { | ||
// Hash the transcript (D_B | V | R | proverLabel | verifierLabel) to get the random coin | ||
DBByte, errByte := DB.MarshalBinary() | ||
if errByte != nil { | ||
panic(errByte) | ||
} | ||
VByte, errByte := V.MarshalBinary() | ||
if errByte != nil { | ||
panic(errByte) | ||
} | ||
|
||
RByte, errByte := R.MarshalBinary() | ||
if errByte != nil { | ||
panic(errByte) | ||
} | ||
hashByte := append(DBByte, VByte...) | ||
hashByte = append(hashByte, RByte...) | ||
hashByte = append(hashByte, proverLabel...) | ||
hashByte = append(hashByte, verifierLabel...) | ||
|
||
c := myGroup.HashToScalar(hashByte, dst) | ||
|
||
rDB := myGroup.NewElement() | ||
rDB.Mul(DB, r) | ||
|
||
cR := myGroup.NewElement() | ||
cR.Mul(R, c) | ||
|
||
rDB.Add(rDB, cR) | ||
|
||
return V.IsEqual(rDB) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package dl | ||
|
||
import ( | ||
"crypto/rand" | ||
"testing" | ||
|
||
"github.com/cloudflare/circl/group" | ||
) | ||
|
||
const testzkDLCount = 10 | ||
|
||
func testzkDL(t *testing.T, myGroup group.Group) { | ||
kA := myGroup.RandomNonZeroScalar(rand.Reader) | ||
DB := myGroup.RandomElement(rand.Reader) | ||
|
||
R := myGroup.NewElement() | ||
R.Mul(DB, kA) | ||
|
||
dst := "zeroknowledge" | ||
rnd := rand.Reader | ||
V, r := ProveGen(myGroup, DB, R, kA, []byte("Prover"), []byte("Verifier"), []byte(dst), rnd) | ||
|
||
verify := Verify(myGroup, DB, R, V, r, []byte("Prover"), []byte("Verifier"), []byte(dst)) | ||
if verify == false { | ||
t.Error("zkRDL verification failed") | ||
} | ||
} | ||
|
||
func testzkDLNegative(t *testing.T, myGroup group.Group) { | ||
kA := myGroup.RandomNonZeroScalar(rand.Reader) | ||
DB := myGroup.RandomElement(rand.Reader) | ||
|
||
R := myGroup.RandomElement(rand.Reader) | ||
|
||
dst := "zeroknowledge" | ||
rnd := rand.Reader | ||
V, r := ProveGen(myGroup, DB, R, kA, []byte("Prover"), []byte("Verifier"), []byte(dst), rnd) | ||
|
||
verify := Verify(myGroup, DB, R, V, r, []byte("Prover"), []byte("Verifier"), []byte(dst)) | ||
if verify == true { | ||
t.Error("zkRDL verification should fail") | ||
} | ||
} | ||
|
||
func TestZKDL(t *testing.T) { | ||
t.Run("zkDL", func(t *testing.T) { | ||
for i := 0; i < testzkDLCount; i++ { | ||
currGroup := group.P256 | ||
testzkDL(t, currGroup) | ||
} | ||
}) | ||
|
||
t.Run("zkDLNegative", func(t *testing.T) { | ||
for i := 0; i < testzkDLCount; i++ { | ||
currGroup := group.P256 | ||
testzkDLNegative(t, currGroup) | ||
} | ||
}) | ||
} |