github.com/cloudflare/circl@v1.5.0/zk/dleq/dleq_test.go (about) 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 // Tamper proof (in transit) 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 // Tamper elements 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 }