github.com/MetalBlockchain/metalgo@v1.11.9/utils/crypto/bls/bls_test.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  package bls
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/MetalBlockchain/metalgo/utils"
    12  )
    13  
    14  func TestAggregation(t *testing.T) {
    15  	type test struct {
    16  		name                   string
    17  		setup                  func(require *require.Assertions) ([]*PublicKey, []*Signature, []byte)
    18  		expectedSigAggError    error
    19  		expectedPubKeyAggError error
    20  		expectedValid          bool
    21  	}
    22  
    23  	tests := []test{
    24  		{
    25  			name: "valid",
    26  			setup: func(require *require.Assertions) ([]*PublicKey, []*Signature, []byte) {
    27  				sk0, err := NewSecretKey()
    28  				require.NoError(err)
    29  				sk1, err := NewSecretKey()
    30  				require.NoError(err)
    31  				sk2, err := NewSecretKey()
    32  				require.NoError(err)
    33  
    34  				pks := []*PublicKey{
    35  					PublicFromSecretKey(sk0),
    36  					PublicFromSecretKey(sk1),
    37  					PublicFromSecretKey(sk2),
    38  				}
    39  
    40  				msg := utils.RandomBytes(1234)
    41  
    42  				sigs := []*Signature{
    43  					Sign(sk0, msg),
    44  					Sign(sk1, msg),
    45  					Sign(sk2, msg),
    46  				}
    47  
    48  				return pks, sigs, msg
    49  			},
    50  			expectedValid: true,
    51  		},
    52  		{
    53  			name: "valid single key",
    54  			setup: func(require *require.Assertions) ([]*PublicKey, []*Signature, []byte) {
    55  				sk, err := NewSecretKey()
    56  				require.NoError(err)
    57  
    58  				pks := []*PublicKey{
    59  					PublicFromSecretKey(sk),
    60  				}
    61  
    62  				msg := utils.RandomBytes(1234)
    63  
    64  				sigs := []*Signature{
    65  					Sign(sk, msg),
    66  				}
    67  
    68  				return pks, sigs, msg
    69  			},
    70  			expectedValid: true,
    71  		},
    72  		{
    73  			name: "wrong message",
    74  			setup: func(require *require.Assertions) ([]*PublicKey, []*Signature, []byte) {
    75  				sk0, err := NewSecretKey()
    76  				require.NoError(err)
    77  				sk1, err := NewSecretKey()
    78  				require.NoError(err)
    79  				sk2, err := NewSecretKey()
    80  				require.NoError(err)
    81  
    82  				pks := []*PublicKey{
    83  					PublicFromSecretKey(sk0),
    84  					PublicFromSecretKey(sk1),
    85  					PublicFromSecretKey(sk2),
    86  				}
    87  
    88  				msg := utils.RandomBytes(1234)
    89  
    90  				sigs := []*Signature{
    91  					Sign(sk0, msg),
    92  					Sign(sk1, msg),
    93  					Sign(sk2, msg),
    94  				}
    95  
    96  				msg[0]++
    97  
    98  				return pks, sigs, msg
    99  			},
   100  			expectedValid: false,
   101  		},
   102  		{
   103  			name: "one sig over different message",
   104  			setup: func(require *require.Assertions) ([]*PublicKey, []*Signature, []byte) {
   105  				sk0, err := NewSecretKey()
   106  				require.NoError(err)
   107  				sk1, err := NewSecretKey()
   108  				require.NoError(err)
   109  				sk2, err := NewSecretKey()
   110  				require.NoError(err)
   111  
   112  				pks := []*PublicKey{
   113  					PublicFromSecretKey(sk0),
   114  					PublicFromSecretKey(sk1),
   115  					PublicFromSecretKey(sk2),
   116  				}
   117  
   118  				msg := utils.RandomBytes(1234)
   119  				msg2 := utils.RandomBytes(1234)
   120  
   121  				sigs := []*Signature{
   122  					Sign(sk0, msg),
   123  					Sign(sk1, msg),
   124  					Sign(sk2, msg2),
   125  				}
   126  
   127  				return pks, sigs, msg
   128  			},
   129  			expectedValid: false,
   130  		},
   131  		{
   132  			name: "one incorrect pubkey",
   133  			setup: func(require *require.Assertions) ([]*PublicKey, []*Signature, []byte) {
   134  				sk0, err := NewSecretKey()
   135  				require.NoError(err)
   136  				sk1, err := NewSecretKey()
   137  				require.NoError(err)
   138  				sk2, err := NewSecretKey()
   139  				require.NoError(err)
   140  				sk3, err := NewSecretKey()
   141  				require.NoError(err)
   142  
   143  				pks := []*PublicKey{
   144  					PublicFromSecretKey(sk0),
   145  					PublicFromSecretKey(sk1),
   146  					PublicFromSecretKey(sk3),
   147  				}
   148  
   149  				msg := utils.RandomBytes(1234)
   150  
   151  				sigs := []*Signature{
   152  					Sign(sk0, msg),
   153  					Sign(sk1, msg),
   154  					Sign(sk2, msg),
   155  				}
   156  
   157  				return pks, sigs, msg
   158  			},
   159  			expectedValid: false,
   160  		},
   161  		{
   162  			name: "num pubkeys > num sigs",
   163  			setup: func(require *require.Assertions) ([]*PublicKey, []*Signature, []byte) {
   164  				sk0, err := NewSecretKey()
   165  				require.NoError(err)
   166  				sk1, err := NewSecretKey()
   167  				require.NoError(err)
   168  				sk2, err := NewSecretKey()
   169  				require.NoError(err)
   170  
   171  				pks := []*PublicKey{
   172  					PublicFromSecretKey(sk0),
   173  					PublicFromSecretKey(sk1),
   174  					PublicFromSecretKey(sk2),
   175  				}
   176  
   177  				msg := utils.RandomBytes(1234)
   178  
   179  				sigs := []*Signature{
   180  					Sign(sk0, msg),
   181  					Sign(sk1, msg),
   182  				}
   183  
   184  				return pks, sigs, msg
   185  			},
   186  			expectedValid: false,
   187  		},
   188  		{
   189  			name: "num pubkeys < num sigs",
   190  			setup: func(require *require.Assertions) ([]*PublicKey, []*Signature, []byte) {
   191  				sk0, err := NewSecretKey()
   192  				require.NoError(err)
   193  				sk1, err := NewSecretKey()
   194  				require.NoError(err)
   195  				sk2, err := NewSecretKey()
   196  				require.NoError(err)
   197  
   198  				pks := []*PublicKey{
   199  					PublicFromSecretKey(sk0),
   200  					PublicFromSecretKey(sk1),
   201  				}
   202  
   203  				msg := utils.RandomBytes(1234)
   204  
   205  				sigs := []*Signature{
   206  					Sign(sk0, msg),
   207  					Sign(sk1, msg),
   208  					Sign(sk2, msg),
   209  				}
   210  
   211  				return pks, sigs, msg
   212  			},
   213  			expectedValid: false,
   214  		},
   215  		{
   216  			name: "no pub keys",
   217  			setup: func(require *require.Assertions) ([]*PublicKey, []*Signature, []byte) {
   218  				sk0, err := NewSecretKey()
   219  				require.NoError(err)
   220  				sk1, err := NewSecretKey()
   221  				require.NoError(err)
   222  				sk2, err := NewSecretKey()
   223  				require.NoError(err)
   224  
   225  				msg := utils.RandomBytes(1234)
   226  
   227  				sigs := []*Signature{
   228  					Sign(sk0, msg),
   229  					Sign(sk1, msg),
   230  					Sign(sk2, msg),
   231  				}
   232  
   233  				return nil, sigs, msg
   234  			},
   235  			expectedPubKeyAggError: ErrNoPublicKeys,
   236  			expectedValid:          false,
   237  		},
   238  		{
   239  			name: "no sigs",
   240  			setup: func(require *require.Assertions) ([]*PublicKey, []*Signature, []byte) {
   241  				sk0, err := NewSecretKey()
   242  				require.NoError(err)
   243  				sk1, err := NewSecretKey()
   244  				require.NoError(err)
   245  				sk2, err := NewSecretKey()
   246  				require.NoError(err)
   247  
   248  				pks := []*PublicKey{
   249  					PublicFromSecretKey(sk0),
   250  					PublicFromSecretKey(sk1),
   251  					PublicFromSecretKey(sk2),
   252  				}
   253  
   254  				msg := utils.RandomBytes(1234)
   255  				return pks, nil, msg
   256  			},
   257  			expectedSigAggError: errNoSignatures,
   258  			expectedValid:       false,
   259  		},
   260  	}
   261  
   262  	for _, tt := range tests {
   263  		t.Run(tt.name, func(t *testing.T) {
   264  			require := require.New(t)
   265  
   266  			pks, sigs, msg := tt.setup(require)
   267  
   268  			aggSig, err := AggregateSignatures(sigs)
   269  			require.ErrorIs(err, tt.expectedSigAggError)
   270  
   271  			aggPK, err := AggregatePublicKeys(pks)
   272  			require.ErrorIs(err, tt.expectedPubKeyAggError)
   273  
   274  			valid := Verify(aggPK, aggSig, msg)
   275  			require.Equal(tt.expectedValid, valid)
   276  		})
   277  	}
   278  }
   279  
   280  func TestAggregationThreshold(t *testing.T) {
   281  	require := require.New(t)
   282  
   283  	// People in the network would privately generate their secret keys
   284  	sk0, err := NewSecretKey()
   285  	require.NoError(err)
   286  	sk1, err := NewSecretKey()
   287  	require.NoError(err)
   288  	sk2, err := NewSecretKey()
   289  	require.NoError(err)
   290  
   291  	// All the public keys would be registered on chain
   292  	pks := []*PublicKey{
   293  		PublicFromSecretKey(sk0),
   294  		PublicFromSecretKey(sk1),
   295  		PublicFromSecretKey(sk2),
   296  	}
   297  
   298  	// The transaction's unsigned bytes are publicly known.
   299  	msg := utils.RandomBytes(1234)
   300  
   301  	// People may attempt time sign the transaction.
   302  	sigs := []*Signature{
   303  		Sign(sk0, msg),
   304  		Sign(sk1, msg),
   305  		Sign(sk2, msg),
   306  	}
   307  
   308  	// The signed transaction would specify which of the public keys have been
   309  	// used to sign it. The aggregator should verify each individual signature,
   310  	// until it has found a sufficient threshold of valid signatures.
   311  	var (
   312  		indices      = []int{0, 2}
   313  		filteredPKs  = make([]*PublicKey, len(indices))
   314  		filteredSigs = make([]*Signature, len(indices))
   315  	)
   316  	for i, index := range indices {
   317  		pk := pks[index]
   318  		filteredPKs[i] = pk
   319  		sig := sigs[index]
   320  		filteredSigs[i] = sig
   321  
   322  		valid := Verify(pk, sig, msg)
   323  		require.True(valid)
   324  	}
   325  
   326  	// Once the aggregator has the required threshold of signatures, it can
   327  	// aggregate the signatures.
   328  	aggregatedSig, err := AggregateSignatures(filteredSigs)
   329  	require.NoError(err)
   330  
   331  	// For anyone looking for a proof of the aggregated signature's correctness,
   332  	// they can aggregate the public keys and verify the aggregated signature.
   333  	aggregatedPK, err := AggregatePublicKeys(filteredPKs)
   334  	require.NoError(err)
   335  
   336  	valid := Verify(aggregatedPK, aggregatedSig, msg)
   337  	require.True(valid)
   338  }
   339  
   340  func TestVerify(t *testing.T) {
   341  	type test struct {
   342  		name          string
   343  		setup         func(*require.Assertions) (pk *PublicKey, sig *Signature, msg []byte)
   344  		expectedValid bool
   345  	}
   346  
   347  	tests := []test{
   348  		{
   349  			name: "valid",
   350  			setup: func(require *require.Assertions) (*PublicKey, *Signature, []byte) {
   351  				sk, err := NewSecretKey()
   352  				require.NoError(err)
   353  				pk := PublicFromSecretKey(sk)
   354  				msg := utils.RandomBytes(1234)
   355  				sig := Sign(sk, msg)
   356  				return pk, sig, msg
   357  			},
   358  			expectedValid: true,
   359  		},
   360  		{
   361  			name: "wrong message",
   362  			setup: func(require *require.Assertions) (*PublicKey, *Signature, []byte) {
   363  				sk, err := NewSecretKey()
   364  				require.NoError(err)
   365  				pk := PublicFromSecretKey(sk)
   366  				msg := utils.RandomBytes(1234)
   367  				sig := Sign(sk, msg)
   368  				msg[0]++
   369  				return pk, sig, msg
   370  			},
   371  			expectedValid: false,
   372  		},
   373  		{
   374  			name: "wrong pub key",
   375  			setup: func(require *require.Assertions) (*PublicKey, *Signature, []byte) {
   376  				sk, err := NewSecretKey()
   377  				require.NoError(err)
   378  				msg := utils.RandomBytes(1234)
   379  				sig := Sign(sk, msg)
   380  
   381  				sk2, err := NewSecretKey()
   382  				require.NoError(err)
   383  				pk := PublicFromSecretKey(sk2)
   384  				return pk, sig, msg
   385  			},
   386  			expectedValid: false,
   387  		},
   388  		{
   389  			name: "wrong sig",
   390  			setup: func(require *require.Assertions) (*PublicKey, *Signature, []byte) {
   391  				sk, err := NewSecretKey()
   392  				require.NoError(err)
   393  				pk := PublicFromSecretKey(sk)
   394  				msg := utils.RandomBytes(1234)
   395  
   396  				msg2 := utils.RandomBytes(1234)
   397  				sig2 := Sign(sk, msg2)
   398  				return pk, sig2, msg
   399  			},
   400  			expectedValid: false,
   401  		},
   402  	}
   403  
   404  	for _, tt := range tests {
   405  		t.Run(tt.name, func(t *testing.T) {
   406  			require := require.New(t)
   407  			pk, sig, msg := tt.setup(require)
   408  			valid := Verify(pk, sig, msg)
   409  			require.Equal(tt.expectedValid, valid)
   410  			valid = VerifyProofOfPossession(pk, sig, msg)
   411  			require.False(valid)
   412  		})
   413  	}
   414  }
   415  
   416  func TestVerifyProofOfPossession(t *testing.T) {
   417  	type test struct {
   418  		name          string
   419  		setup         func(*require.Assertions) (pk *PublicKey, sig *Signature, msg []byte)
   420  		expectedValid bool
   421  	}
   422  
   423  	tests := []test{
   424  		{
   425  			name: "valid",
   426  			setup: func(require *require.Assertions) (*PublicKey, *Signature, []byte) {
   427  				sk, err := NewSecretKey()
   428  				require.NoError(err)
   429  				pk := PublicFromSecretKey(sk)
   430  				msg := utils.RandomBytes(1234)
   431  				sig := SignProofOfPossession(sk, msg)
   432  				return pk, sig, msg
   433  			},
   434  			expectedValid: true,
   435  		},
   436  		{
   437  			name: "wrong message",
   438  			setup: func(require *require.Assertions) (*PublicKey, *Signature, []byte) {
   439  				sk, err := NewSecretKey()
   440  				require.NoError(err)
   441  				pk := PublicFromSecretKey(sk)
   442  				msg := utils.RandomBytes(1234)
   443  				sig := SignProofOfPossession(sk, msg)
   444  				msg[0]++
   445  				return pk, sig, msg
   446  			},
   447  			expectedValid: false,
   448  		},
   449  		{
   450  			name: "wrong pub key",
   451  			setup: func(require *require.Assertions) (*PublicKey, *Signature, []byte) {
   452  				sk, err := NewSecretKey()
   453  				require.NoError(err)
   454  				msg := utils.RandomBytes(1234)
   455  				sig := SignProofOfPossession(sk, msg)
   456  
   457  				sk2, err := NewSecretKey()
   458  				require.NoError(err)
   459  				pk := PublicFromSecretKey(sk2)
   460  				return pk, sig, msg
   461  			},
   462  			expectedValid: false,
   463  		},
   464  		{
   465  			name: "wrong sig",
   466  			setup: func(require *require.Assertions) (*PublicKey, *Signature, []byte) {
   467  				sk, err := NewSecretKey()
   468  				require.NoError(err)
   469  				pk := PublicFromSecretKey(sk)
   470  				msg := utils.RandomBytes(1234)
   471  
   472  				msg2 := utils.RandomBytes(1234)
   473  				sig2 := SignProofOfPossession(sk, msg2)
   474  				return pk, sig2, msg
   475  			},
   476  			expectedValid: false,
   477  		},
   478  	}
   479  
   480  	for _, tt := range tests {
   481  		t.Run(tt.name, func(t *testing.T) {
   482  			require := require.New(t)
   483  			pk, sig, msg := tt.setup(require)
   484  			valid := VerifyProofOfPossession(pk, sig, msg)
   485  			require.Equal(tt.expectedValid, valid)
   486  			valid = Verify(pk, sig, msg)
   487  			require.False(valid)
   488  		})
   489  	}
   490  }