github.com/google/trillian-examples@v0.0.0-20240520080811-0d40d35cef0e/formats/checkpoints/combine_signatures_test.go (about)

     1  // Copyright 2021 Google LLC. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package checkpoints
    16  
    17  import (
    18  	"testing"
    19  
    20  	"golang.org/x/mod/sumdb/note"
    21  )
    22  
    23  func TestCombine(t *testing.T) {
    24  	logS, logV := genKeyPair(t, "log")
    25  	wit1S, wit1V := genKeyPair(t, "w1")
    26  	wit2S, wit2V := genKeyPair(t, "w2")
    27  	wit3S, wit3V := genKeyPair(t, "w3")
    28  
    29  	for _, test := range []struct {
    30  		desc         string
    31  		logSigV      note.Verifier
    32  		witnessSigVs note.Verifiers
    33  		cps          [][]byte
    34  		wantSigVs    []note.Verifier
    35  		wantErr      bool
    36  	}{
    37  		{
    38  			desc:         "works - first CP has all the signatures",
    39  			logSigV:      logV,
    40  			witnessSigVs: note.VerifierList(wit1V, wit2V, wit3V),
    41  			cps: [][]byte{
    42  				newCP(t, "body", logS, wit1S, wit2S, wit3S),
    43  				newCP(t, "body", logS),
    44  			},
    45  			wantSigVs: []note.Verifier{logV, wit1V, wit2V, wit3V},
    46  		}, {
    47  			desc:         "works",
    48  			logSigV:      logV,
    49  			witnessSigVs: note.VerifierList(wit1V, wit2V, wit3V),
    50  			cps: [][]byte{
    51  				newCP(t, "body", logS),
    52  				newCP(t, "body", logS, wit1S),
    53  				newCP(t, "body", logS, wit2S),
    54  				newCP(t, "body", logS, wit3S),
    55  			},
    56  			wantSigVs: []note.Verifier{logV, wit1V, wit2V, wit3V},
    57  		}, {
    58  			desc:         "many dupes",
    59  			logSigV:      logV,
    60  			witnessSigVs: note.VerifierList(wit1V, wit2V, wit3V),
    61  			cps: [][]byte{
    62  				newCP(t, "body", logS, wit1S, wit2S, wit3S),
    63  				newCP(t, "body", logS, wit1S, wit2S, wit3S),
    64  				newCP(t, "body", logS, wit1S, wit2S, wit3S),
    65  				newCP(t, "body", logS, wit1S, wit2S, wit3S),
    66  			},
    67  			wantSigVs: []note.Verifier{logV, wit1V, wit2V, wit3V},
    68  		}, {
    69  			desc:         "no witness sigs",
    70  			logSigV:      logV,
    71  			witnessSigVs: note.VerifierList(wit1V, wit2V, wit3V),
    72  			cps: [][]byte{
    73  				newCP(t, "body", logS),
    74  				newCP(t, "body", logS),
    75  				newCP(t, "body", logS),
    76  				newCP(t, "body", logS),
    77  			},
    78  			wantSigVs: []note.Verifier{logV},
    79  		}, {
    80  			desc:         "drop unknown witness",
    81  			logSigV:      logV,
    82  			witnessSigVs: note.VerifierList(wit1V, wit3V),
    83  			cps: [][]byte{
    84  				newCP(t, "body", logS, wit1S),
    85  				// This one should get ignored
    86  				newCP(t, "body", logS, wit2S),
    87  				newCP(t, "body", logS, wit3S),
    88  			},
    89  			wantSigVs: []note.Verifier{logV, wit1V, wit3V},
    90  		}, {
    91  			desc:         "no known witness sigs",
    92  			logSigV:      logV,
    93  			witnessSigVs: note.VerifierList(wit2V, wit3V),
    94  			cps: [][]byte{
    95  				newCP(t, "body", logS, wit1S),
    96  				newCP(t, "body", logS),
    97  				newCP(t, "body", logS),
    98  				newCP(t, "body", logS, wit1S),
    99  			},
   100  			wantSigVs: []note.Verifier{logV},
   101  		}, {
   102  			desc:         "combine already witnessed CP",
   103  			logSigV:      logV,
   104  			witnessSigVs: note.VerifierList(wit1V, wit2V, wit3V),
   105  			cps: [][]byte{
   106  				// This CP's already been witnessed
   107  				newCP(t, "body", logS, wit1S, wit2S),
   108  				// Now wit3 has signed it
   109  				newCP(t, "body", logS, wit3S),
   110  			},
   111  			wantSigVs: []note.Verifier{logV, wit1V, wit2V, wit3V},
   112  		}, {
   113  			desc:         "no log sig on witnessed",
   114  			logSigV:      logV,
   115  			witnessSigVs: note.VerifierList(wit1V, wit2V, wit3V),
   116  			cps: [][]byte{
   117  				newCP(t, "body", wit1S, wit2S),
   118  				newCP(t, "body", logS),
   119  			},
   120  			wantErr: true,
   121  		}, {
   122  			desc:         "no log sig on any",
   123  			logSigV:      logV,
   124  			witnessSigVs: note.VerifierList(wit1V, wit2V, wit3V),
   125  			cps: [][]byte{
   126  				newCP(t, "body", wit1S, wit2S),
   127  				newCP(t, "body", wit3S),
   128  			},
   129  			wantErr: true,
   130  		}, {
   131  			desc:         "differing body",
   132  			logSigV:      logV,
   133  			witnessSigVs: note.VerifierList(wit1V, wit2V, wit3V),
   134  			cps: [][]byte{
   135  				newCP(t, "body", logS, wit1S, wit2S),
   136  				newCP(t, "legs", wit3S),
   137  			},
   138  			wantErr: true,
   139  		},
   140  	} {
   141  		t.Run(test.desc, func(t *testing.T) {
   142  			cp, err := Combine(test.cps, test.logSigV, test.witnessSigVs)
   143  			gotErr := err != nil
   144  			if test.wantErr && gotErr {
   145  				return
   146  			} else if gotErr != test.wantErr {
   147  				t.Fatalf("Got err %v, want err? %t", err, test.wantErr)
   148  			}
   149  
   150  			n, err := note.Open(cp, note.VerifierList(test.wantSigVs...))
   151  			if err != nil {
   152  				t.Fatalf("Failed to re-open note: %v", err)
   153  			}
   154  
   155  			if l := len(n.UnverifiedSigs); l != 0 {
   156  				for _, s := range n.UnverifiedSigs {
   157  					t.Errorf("Unexpected sig: %v", s.Name)
   158  				}
   159  				t.Fatalf("Got %d unexpected signatures", l)
   160  			}
   161  			if got, want := len(n.Sigs), len(test.wantSigVs); got != want {
   162  				for _, s := range n.Sigs {
   163  					t.Errorf("Got sig: %v", s.Name)
   164  				}
   165  				t.Fatalf("Got %d signatures, want %d", got, want)
   166  			}
   167  			if n.Sigs[0].Hash != test.logSigV.KeyHash() {
   168  				t.Fatal("First signature was not from log")
   169  			}
   170  
   171  		})
   172  	}
   173  }
   174  
   175  func TestCombineReturnsStableOrdering(t *testing.T) {
   176  	logS, logV := genKeyPair(t, "log")
   177  	wit1S, wit1V := genKeyPair(t, "w1")
   178  	wit2S, wit2V := genKeyPair(t, "w2")
   179  	wit3S, wit3V := genKeyPair(t, "w3")
   180  	witnessSigVs := note.VerifierList(wit1V, wit2V, wit3V)
   181  
   182  	cps := [][]byte{
   183  		newCP(t, "body", logS, wit1S, wit2S, wit3S),
   184  		newCP(t, "body", logS),
   185  	}
   186  	cp, err := Combine(cps, logV, witnessSigVs)
   187  	if err != nil {
   188  		t.Fatalf("Failed to combine sigs: %v", err)
   189  	}
   190  	n, err := note.Open(cp, note.VerifierList(logV, wit1V, wit2V, wit3V))
   191  	if err != nil {
   192  		t.Fatalf("Failed to re-open note: %v", err)
   193  	}
   194  
   195  	if n.Sigs[0].Name != logV.Name() {
   196  		t.Fatalf("Got signature from %q at 0, want %q", n.Sigs[0].Name, logV.Name())
   197  	}
   198  	// Start at index 1 since index 0 should be the log signature
   199  	for i := 1; i < len(n.Sigs)-1; i++ {
   200  		if ih, jh := n.Sigs[i].Hash, n.Sigs[i+1].Hash; ih > jh {
   201  			t.Fatalf("Found out-of-order signature: index %d (%x) > index %d (%x)", i, ih, i+1, jh)
   202  		}
   203  	}
   204  }
   205  
   206  func newCP(t *testing.T, body string, sigs ...note.Signer) []byte {
   207  	ret, err := note.Sign(&note.Note{Text: body + "\n"}, sigs...)
   208  	if err != nil {
   209  		t.Fatalf("Failed to sign note %q: %v", body, err)
   210  	}
   211  	return ret
   212  }
   213  
   214  func genKeyPair(t *testing.T, name string) (note.Signer, note.Verifier) {
   215  	sKey, vKey, err := note.GenerateKey(nil, name)
   216  	if err != nil {
   217  		t.Fatalf("Failed to generate key %q: %v", name, err)
   218  	}
   219  	s, err := note.NewSigner(sKey)
   220  	if err != nil {
   221  		t.Fatalf("Failed to create signer %q: %v", name, err)
   222  	}
   223  	v, err := note.NewVerifier(vKey)
   224  	if err != nil {
   225  		t.Fatalf("Failed to create verifier %q: %v", name, err)
   226  	}
   227  	return s, v
   228  }