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(¬e.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 }