Skip to content

Commit

Permalink
Adds prefixed labels and updates nomenclature.
Browse files Browse the repository at this point in the history
  • Loading branch information
armfazh committed Feb 14, 2023
1 parent 7a181da commit 2481411
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 63 deletions.
110 changes: 55 additions & 55 deletions zk/dl/dl.go
@@ -1,86 +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 provides a Schnorr NIZK discrete-log proof.
//
// This package implements a Schnorr NIZK discrete-log proof obtained from the
// interactive Schnorr identification scheme through a Fiat-Shamir transformation.
//
// Given (k,G,kG) the Prove function returns a Proof struct attesting that
// kG = [k]G, which can be validated using the Verify function.
//
// The userID label is a unique identifier for the prover.
//
// The otherInfo label is defined to allow flexible inclusion of contextual
// information in the Schnorr NIZK proof.
// The otherInfo is also used as a domain separation tag (dst) for the hash
// to scalar function.
//
// Reference: https://datatracker.ietf.org/doc/html/rfc8235
package dl

import (
"encoding/binary"
"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)
type Proof struct {
V group.Element
R group.Scalar
}

// Hash transcript (D_B | V | R | proverLabel | verifierLabel) to get the random coin
DBByte, errByte := DB.MarshalBinary()
func calcChallenge(myGroup group.Group, G, V, A group.Element, userID, otherInfo []byte) group.Scalar {
// Hash transcript (G | V | A | UserID | OtherInfo) to get the random coin.
GByte, errByte := G.MarshalBinary()
if errByte != nil {
panic(errByte)
}
VByte, errByte := V.MarshalBinary()
if errByte != nil {
panic(errByte)
}

RByte, errByte := R.MarshalBinary()
AByte, errByte := A.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)
uPrefix := [4]byte{}
binary.BigEndian.PutUint32(uPrefix[:], uint32(len(userID)))
oPrefix := [4]byte{}
binary.BigEndian.PutUint32(oPrefix[:], uint32(len(otherInfo)))

kAc := myGroup.NewScalar()
kAc.Mul(c, kA)
r := v.Copy()
r.Sub(r, kAc)
hashByte := append(append(append(append(append(append(
GByte, VByte...), AByte...),
uPrefix[:]...), userID...),
oPrefix[:]...), otherInfo...)

return V, r
return myGroup.HashToScalar(hashByte, otherInfo)
}

// 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)
}
// Prove returns a proof attesting that kG = [k]G.
func Prove(myGroup group.Group, G, kG group.Element, k group.Scalar, userID, otherInfo []byte, rnd io.Reader) Proof {
v := myGroup.RandomNonZeroScalar(rnd)
V := myGroup.NewElement()
V.Mul(G, v)

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 := calcChallenge(myGroup, G, V, kG, userID, otherInfo)

r := myGroup.NewScalar()
r.Sub(v, myGroup.NewScalar().Mul(k, c))

return Proof{V, r}
}

c := myGroup.HashToScalar(hashByte, dst)
// Verify checks whether the proof attests that kG = [k]G.
func Verify(myGroup group.Group, G, kG group.Element, p Proof, userID, otherInfo []byte) bool {
c := calcChallenge(myGroup, G, p.V, kG, userID, otherInfo)

rDB := myGroup.NewElement()
rDB.Mul(DB, r)
rG := myGroup.NewElement()
rG.Mul(G, p.R)

cR := myGroup.NewElement()
cR.Mul(R, c)
ckG := myGroup.NewElement()
ckG.Mul(kG, c)

rDB.Add(rDB, cR)
rG.Add(rG, ckG)

return V.IsEqual(rDB)
return p.V.IsEqual(rG)
}
17 changes: 9 additions & 8 deletions zk/dl/dl_test.go
@@ -1,13 +1,14 @@
package dl
package dl_test

import (
"crypto/rand"
"testing"

"github.com/cloudflare/circl/group"
"github.com/cloudflare/circl/zk/dl"
)

const testzkDLCount = 10
const testzkDLCount = 1 << 8

func testzkDL(t *testing.T, myGroup group.Group) {
kA := myGroup.RandomNonZeroScalar(rand.Reader)
Expand All @@ -18,11 +19,11 @@ func testzkDL(t *testing.T, myGroup group.Group) {

dst := "zeroknowledge"
rnd := rand.Reader
V, r := ProveGen(myGroup, DB, R, kA, []byte("Prover"), []byte("Verifier"), []byte(dst), rnd)
proof := dl.Prove(myGroup, DB, R, kA, []byte("Prover"), []byte(dst), rnd)

verify := Verify(myGroup, DB, R, V, r, []byte("Prover"), []byte("Verifier"), []byte(dst))
verify := dl.Verify(myGroup, DB, R, proof, []byte("Prover"), []byte(dst))
if verify == false {
t.Error("zkRDL verification failed")
t.Error("zk/dl verification failed")
}
}

Expand All @@ -34,11 +35,11 @@ func testzkDLNegative(t *testing.T, myGroup group.Group) {

dst := "zeroknowledge"
rnd := rand.Reader
V, r := ProveGen(myGroup, DB, R, kA, []byte("Prover"), []byte("Verifier"), []byte(dst), rnd)
proof := dl.Prove(myGroup, DB, R, kA, []byte("Prover"), []byte(dst), rnd)

verify := Verify(myGroup, DB, R, V, r, []byte("Prover"), []byte("Verifier"), []byte(dst))
verify := dl.Verify(myGroup, DB, R, proof, []byte("Prover"), []byte(dst))
if verify == true {
t.Error("zkRDL verification should fail")
t.Error("zk/dl verification should fail")
}
}

Expand Down

0 comments on commit 2481411

Please sign in to comment.