1 package dleq_test
2
3 import (
4 "bytes"
5 "crypto"
6 "crypto/rand"
7 "fmt"
8 "testing"
9
10 "github.com/cloudflare/circl/group"
11 "github.com/cloudflare/circl/internal/test"
12 "github.com/cloudflare/circl/zk/dleq"
13 )
14
15 func TestDLEQ(t *testing.T) {
16 for _, g := range []group.Group{
17 group.P256,
18 group.P384,
19 group.P521,
20 group.Ristretto255,
21 } {
22 t.Run(g.(fmt.Stringer).String(), func(t *testing.T) {
23 params := dleq.Params{g, crypto.SHA256, []byte("domain_sep_string")}
24 Peggy := dleq.Prover{params}
25 Victor := dleq.Verifier{params}
26
27 k := g.RandomScalar(rand.Reader)
28 A := g.RandomElement(rand.Reader)
29 kA := g.NewElement().Mul(A, k)
30
31 B := g.RandomElement(rand.Reader)
32 kB := g.NewElement().Mul(B, k)
33
34 proof, err := Peggy.Prove(k, A, kA, B, kB, rand.Reader)
35 test.CheckNoErr(t, err, "wrong proof generation")
36 test.CheckOk(Victor.Verify(A, kA, B, kB, proof), "proof must verify", t)
37
38 rr := g.RandomScalar(rand.Reader)
39 proof, err = Peggy.ProveWithRandomness(k, A, kA, B, kB, rr)
40 test.CheckNoErr(t, err, "wrong proof generation")
41 test.CheckOk(Victor.Verify(A, kA, B, kB, proof), "proof must verify", t)
42
43 const N = 4
44 C := make([]group.Element, N)
45 kC := make([]group.Element, N)
46 for i := 0; i < N; i++ {
47 C[i] = g.RandomElement(rand.Reader)
48 kC[i] = g.NewElement().Mul(C[i], k)
49 }
50 proof, err = Peggy.ProveBatch(k, A, kA, C, kC, rand.Reader)
51 test.CheckNoErr(t, err, "wrong proof generation")
52 test.CheckOk(Victor.VerifyBatch(A, kA, C, kC, proof), "proof must verify", t)
53
54 testMarshal(t, g, proof)
55 testErrors(t, &Peggy, &Victor, g, k, A, kA, B, kB)
56 })
57 }
58 }
59
60 func testMarshal(t *testing.T, g group.Group, proof *dleq.Proof) {
61 t.Helper()
62
63 wantProofBytes, err := proof.MarshalBinary()
64 test.CheckNoErr(t, err, "error on marshaling proof")
65
66 gotProof := new(dleq.Proof)
67 err = gotProof.UnmarshalBinary(g, wantProofBytes)
68 test.CheckNoErr(t, err, "error on unmarshaling proof")
69
70 gotProofBytes, err := gotProof.MarshalBinary()
71 test.CheckNoErr(t, err, "error on marshaling proof")
72
73 if !bytes.Equal(gotProofBytes, wantProofBytes) {
74 test.ReportError(t, gotProofBytes, wantProofBytes)
75 }
76 }
77
78 func testErrors(
79 t *testing.T,
80 Peggy *dleq.Prover,
81 Victor *dleq.Verifier,
82 g group.Group,
83 k group.Scalar, a, ka, b, kb group.Element,
84 ) {
85 goodProof, err := Peggy.Prove(k, a, ka, b, kb, rand.Reader)
86 test.CheckNoErr(t, err, "wrong proof generation")
87
88 proofBytes, err := goodProof.MarshalBinary()
89 test.CheckNoErr(t, err, "error on marshaling proof")
90
91
92 _, _ = rand.Read(proofBytes)
93
94 tamperedProof := new(dleq.Proof)
95 err = tamperedProof.UnmarshalBinary(g, proofBytes[:5])
96 test.CheckIsErr(t, err, "unmarshal must fail")
97
98 err = tamperedProof.UnmarshalBinary(g, proofBytes)
99 test.CheckNoErr(t, err, "proof must be unmarshaled")
100 test.CheckOk(false == Victor.Verify(a, ka, b, kb, tamperedProof), "proof must not verify", t)
101
102
103 bada := g.NewElement().Neg(a)
104 test.CheckOk(false == Victor.Verify(bada, ka, b, kb, goodProof), "proof must not verify", t)
105 badka := g.NewElement().Neg(ka)
106 test.CheckOk(false == Victor.Verify(a, badka, b, kb, goodProof), "proof must not verify", t)
107 badb := g.NewElement().Neg(b)
108 test.CheckOk(false == Victor.Verify(a, ka, badb, kb, goodProof), "proof must not verify", t)
109 badkb := g.NewElement().Neg(kb)
110 test.CheckOk(false == Victor.Verify(a, ka, b, badkb, goodProof), "proof must not verify", t)
111 }
112
113 func BenchmarkDLEQ(b *testing.B) {
114 g := group.P256
115 params := dleq.Params{g, crypto.SHA256, []byte("domain_sep_string")}
116 Peggy := dleq.Prover{params}
117 Victor := dleq.Verifier{params}
118
119 k := g.RandomScalar(rand.Reader)
120 A := g.Generator()
121 kA := g.NewElement().MulGen(k)
122
123 B := g.RandomElement(rand.Reader)
124 kB := g.NewElement().Mul(B, k)
125 rr := g.RandomScalar(rand.Reader)
126
127 proof, _ := Peggy.ProveWithRandomness(k, A, kA, B, kB, rr)
128
129 const N = 4
130 C := make([]group.Element, N)
131 kC := make([]group.Element, N)
132 for i := 0; i < N; i++ {
133 C[i] = g.RandomElement(rand.Reader)
134 kC[i] = g.NewElement().Mul(C[i], k)
135 }
136
137 proofBatched, _ := Peggy.ProveBatchWithRandomness(k, A, kA, C, kC, rr)
138
139 b.Run("Prove", func(b *testing.B) {
140 for i := 0; i < b.N; i++ {
141 _, _ = Peggy.ProveWithRandomness(k, A, kA, B, kB, rr)
142 }
143 })
144 b.Run("Verify", func(b *testing.B) {
145 for i := 0; i < b.N; i++ {
146 _ = Victor.Verify(A, kA, B, kB, proof)
147 }
148 })
149 b.Run(fmt.Sprint("ProveBatch=", N), func(b *testing.B) {
150 for i := 0; i < b.N; i++ {
151 _, _ = Peggy.ProveBatchWithRandomness(k, A, kA, C, kC, rr)
152 }
153 })
154 b.Run(fmt.Sprint("VerifyBatch=", N), func(b *testing.B) {
155 for i := 0; i < b.N; i++ {
156 _ = Victor.VerifyBatch(A, kA, C, kC, proofBatched)
157 }
158 })
159 }
160
View as plain text