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  }