github.com/cloudflare/circl@v1.5.0/secretsharing/ss_test.go (about)

     1  package secretsharing_test
     2  
     3  import (
     4  	"crypto/rand"
     5  	"testing"
     6  
     7  	"github.com/cloudflare/circl/group"
     8  	"github.com/cloudflare/circl/internal/test"
     9  	"github.com/cloudflare/circl/secretsharing"
    10  )
    11  
    12  func TestSecretSharing(tt *testing.T) {
    13  	g := group.P256
    14  	t := uint(2)
    15  	n := uint(5)
    16  
    17  	secret := g.RandomScalar(rand.Reader)
    18  	ss := secretsharing.New(rand.Reader, t, secret)
    19  	shares := ss.Share(n)
    20  	test.CheckOk(len(shares) == int(n), "bad num shares", tt)
    21  	coms := ss.CommitSecret()
    22  
    23  	tt.Run("subsetSize", func(ttt *testing.T) {
    24  		// Test any possible subset size.
    25  		for k := 0; k <= int(n); k++ {
    26  			got, err := secretsharing.Recover(t, shares[:k])
    27  			if !(int(t) < k && k <= int(n)) {
    28  				test.CheckIsErr(ttt, err, "should not recover secret")
    29  				test.CheckOk(got == nil, "not nil secret", ttt)
    30  			} else {
    31  				test.CheckNoErr(ttt, err, "should recover secret")
    32  				want := secret
    33  				if !got.IsEqual(want) {
    34  					test.ReportError(ttt, got, want, t, k, n)
    35  				}
    36  			}
    37  		}
    38  	})
    39  
    40  	tt.Run("verifyShares", func(ttt *testing.T) {
    41  		for i := range shares {
    42  			test.CheckOk(secretsharing.Verify(t, shares[i], coms) == true, "failed one share", ttt)
    43  		}
    44  	})
    45  
    46  	tt.Run("badShares", func(ttt *testing.T) {
    47  		badShares := make([]secretsharing.Share, len(shares))
    48  		for i := range shares {
    49  			badShares[i].ID = shares[i].ID.Copy()
    50  			badShares[i].Value = shares[i].Value.Copy()
    51  			badShares[i].Value.SetUint64(9)
    52  		}
    53  
    54  		for i := range badShares {
    55  			test.CheckOk(secretsharing.Verify(t, badShares[i], coms) == false, "verify must fail due to bad shares", ttt)
    56  		}
    57  	})
    58  
    59  	tt.Run("badCommitments", func(ttt *testing.T) {
    60  		badComs := make(secretsharing.SecretCommitment, len(coms))
    61  		for i := range coms {
    62  			badComs[i] = coms[i].Copy()
    63  			badComs[i].Dbl(badComs[i])
    64  		}
    65  
    66  		for i := range shares {
    67  			test.CheckOk(secretsharing.Verify(t, shares[i], badComs) == false, "verify must fail due to bad commitment", ttt)
    68  		}
    69  	})
    70  }
    71  
    72  func TestShareWithID(tt *testing.T) {
    73  	g := group.P256
    74  	t := uint(2)
    75  	n := uint(5)
    76  	secret := g.RandomScalar(rand.Reader)
    77  	ss := secretsharing.New(rand.Reader, t, secret)
    78  
    79  	tt.Run("recoverOk", func(ttt *testing.T) {
    80  		// SecretSharing can create shares at will, not exactly n many.
    81  		shares := []secretsharing.Share{
    82  			ss.ShareWithID(g.RandomScalar(rand.Reader)),
    83  			ss.ShareWithID(g.RandomScalar(rand.Reader)),
    84  			ss.ShareWithID(g.RandomScalar(rand.Reader)),
    85  		}
    86  		got, err := secretsharing.Recover(t, shares)
    87  		test.CheckNoErr(tt, err, "failed to recover the secret")
    88  		want := secret
    89  		if !got.IsEqual(want) {
    90  			test.ReportError(tt, got, want, t, n)
    91  		}
    92  	})
    93  
    94  	tt.Run("duplicatedFail", func(ttt *testing.T) {
    95  		// Panics if trying to recover duplicated shares.
    96  		share := ss.ShareWithID(g.RandomScalar(rand.Reader))
    97  		sameShares := []secretsharing.Share{share, share, share}
    98  		err := test.CheckPanic(func() {
    99  			got, err := secretsharing.Recover(t, sameShares)
   100  			test.CheckIsErr(tt, err, "must fail to recover the secret")
   101  			test.CheckOk(got == nil, "must not recover", tt)
   102  		})
   103  		test.CheckOk(err == nil, "must panic", tt)
   104  	})
   105  }
   106  
   107  func BenchmarkSecretSharing(b *testing.B) {
   108  	g := group.P256
   109  	t := uint(3)
   110  	n := uint(5)
   111  
   112  	secret := g.RandomScalar(rand.Reader)
   113  	ss := secretsharing.New(rand.Reader, t, secret)
   114  	shares := ss.Share(n)
   115  	coms := ss.CommitSecret()
   116  
   117  	b.Run("New", func(b *testing.B) {
   118  		for i := 0; i < b.N; i++ {
   119  			secretsharing.New(rand.Reader, t, secret)
   120  		}
   121  	})
   122  
   123  	b.Run("Share", func(b *testing.B) {
   124  		for i := 0; i < b.N; i++ {
   125  			ss.Share(n)
   126  		}
   127  	})
   128  
   129  	b.Run("Recover", func(b *testing.B) {
   130  		for i := 0; i < b.N; i++ {
   131  			_, _ = secretsharing.Recover(t, shares)
   132  		}
   133  	})
   134  
   135  	b.Run("CommitSecret", func(b *testing.B) {
   136  		for i := 0; i < b.N; i++ {
   137  			ss.CommitSecret()
   138  		}
   139  	})
   140  
   141  	b.Run("Verify", func(b *testing.B) {
   142  		for i := 0; i < b.N; i++ {
   143  			secretsharing.Verify(t, shares[0], coms)
   144  		}
   145  	})
   146  }