// ExpireMetadata expires the metadata, which would make it invalid - don't do anything if // we don't have the timestamp key func (m *MetadataSwizzler) ExpireMetadata(role string) error { signedThing, err := signedFromStore(m.MetadataCache, role) if err != nil { return err } var unmarshalled map[string]interface{} if err := json.Unmarshal(*signedThing.Signed, &unmarshalled); err != nil { return err } unmarshalled["expires"] = time.Now().AddDate(-1, -1, -1) metaBytes, err := json.MarshalCanonical(unmarshalled) if err != nil { return err } signedThing.Signed = (*json.RawMessage)(&metaBytes) pubKeys, err := getPubKeys(m.CryptoService, signedThing, role) if err == nil { metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role, pubKeys...) } if err != nil { return err } return m.MetadataCache.Set(role, metaBytes) }
func TestMoreThanEnoughSigs(t *testing.T) { cs := NewEd25519() k1, err := cs.Create("root", data.ED25519Key) assert.NoError(t, err) k2, err := cs.Create("root", data.ED25519Key) assert.NoError(t, err) r, err := data.NewRole( "root", 1, []string{k1.ID(), k2.ID()}, nil, nil, ) assert.NoError(t, err) db := keys.NewDB() assert.NoError(t, err) db.AddKey(k1) db.AddKey(k2) err = db.AddRole(r) assert.NoError(t, err) meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) assert.NoError(t, err) s := &data.Signed{Signed: b} Sign(cs, s, k1, k2) assert.Equal(t, 2, len(s.Signatures)) err = Verify(s, "root", 1, db) assert.NoError(t, err) }
// SetInvalidMetadataType unmarshallable, but has the wrong metadata type (not // actually a metadata type) func (m *MetadataSwizzler) SetInvalidMetadataType(role string) error { signedThing, err := signedFromStore(m.MetadataCache, role) if err != nil { return err } var unmarshalled map[string]interface{} if err := json.Unmarshal(*signedThing.Signed, &unmarshalled); err != nil { return err } unmarshalled["_type"] = "not_real" metaBytes, err := json.MarshalCanonical(unmarshalled) if err != nil { return err } signedThing.Signed = (*json.RawMessage)(&metaBytes) pubKeys, err := getPubKeys(m.CryptoService, signedThing, role) if err == nil { metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role, pubKeys...) } if err != nil { return err } return m.MetadataCache.Set(role, metaBytes) }
// OffsetMetadataVersion updates the metadata version func (m *MetadataSwizzler) OffsetMetadataVersion(role string, offset int) error { signedThing, err := signedFromStore(m.MetadataCache, role) if err != nil { return err } var unmarshalled map[string]interface{} if err := json.Unmarshal(*signedThing.Signed, &unmarshalled); err != nil { return err } oldVersion, ok := unmarshalled["version"].(float64) if !ok { oldVersion = float64(0) // just ignore the error and set it to 0 } unmarshalled["version"] = int(oldVersion) + offset metaBytes, err := json.MarshalCanonical(unmarshalled) if err != nil { return err } signedThing.Signed = (*json.RawMessage)(&metaBytes) pubKeys, err := getPubKeys(m.CryptoService, signedThing, role) if err == nil { metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role, pubKeys...) } if err != nil { return err } return m.MetadataCache.Set(role, metaBytes) }
// CreateTimestamp creates a new timestamp. If a prev timestamp is provided, it // is assumed this is the immediately previous one, and the new one will have a // version number one higher than prev. The store is used to lookup the current // snapshot, this function does not save the newly generated timestamp. func CreateTimestamp(gun string, prev *data.SignedTimestamp, snapshot []byte, store storage.MetaStore, cryptoService signed.CryptoService) (*data.Signed, int, error) { algorithm, public, err := store.GetKey(gun, data.CanonicalTimestampRole) if err != nil { // owner of gun must have generated a timestamp key otherwise // we won't proceed with generating everything. return nil, 0, err } key := data.NewPublicKey(algorithm, public) sn := &data.Signed{} err = json.Unmarshal(snapshot, sn) if err != nil { // couldn't parse snapshot return nil, 0, err } ts, err := data.NewTimestamp(sn) if err != nil { return nil, 0, err } if prev != nil { ts.Signed.Version = prev.Signed.Version + 1 } sgndTs, err := json.MarshalCanonical(ts.Signed) if err != nil { return nil, 0, err } out := &data.Signed{ Signatures: ts.Signatures, Signed: sgndTs, } err = signed.Sign(cryptoService, out, key) if err != nil { return nil, 0, err } return out, ts.Signed.Version, nil }
// SetInvalidSignedMeta corrupts the metadata into something that is unmarshallable // as a Signed object, but not unmarshallable into a SignedMeta object func (m *MetadataSwizzler) SetInvalidSignedMeta(role string) error { signedThing, err := signedFromStore(m.MetadataCache, role) if err != nil { return err } pubKeys, err := getPubKeys(m.CryptoService, signedThing, role) if err != nil { return err } var unmarshalled map[string]interface{} if err := json.Unmarshal(*signedThing.Signed, &unmarshalled); err != nil { return err } unmarshalled["_type"] = []string{"not a string"} unmarshalled["version"] = "string not int" unmarshalled["expires"] = "cannot be parsed as time" metaBytes, err := json.MarshalCanonical(unmarshalled) if err != nil { return err } signedThing.Signed = (*json.RawMessage)(&metaBytes) metaBytes, err = serializeMetadata(m.CryptoService, signedThing, role, pubKeys...) if err != nil { return err } return m.MetadataCache.Set(role, metaBytes) }
func TestUnknownKeyBelowThreshold(t *testing.T) { cs := NewEd25519() k, err := cs.Create("root", "", data.ED25519Key) require.NoError(t, err) unknown, err := cs.Create("root", "", data.ED25519Key) require.NoError(t, err) roleWithKeys := data.BaseRole{Name: "root", Keys: data.Keys{k.ID(): k}, Threshold: 2} meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) require.NoError(t, err) s := &data.Signed{Signed: (*json.RawMessage)(&b)} require.NoError(t, Sign(cs, s, []data.PublicKey{k, unknown}, 2, nil)) s.Signatures = append(s.Signatures) err = VerifySignatures(s, roleWithKeys) require.IsType(t, ErrRoleThreshold{}, err) require.Len(t, s.Signatures, 2) for _, signature := range s.Signatures { if signature.KeyID == k.ID() { require.True(t, signature.IsValid) } else { require.False(t, signature.IsValid) } } }
// initialize a repo with keys, so they can be rotated func setUpRepo(t *testing.T, tempBaseDir, gun string, ret passphrase.Retriever) ( *httptest.Server, map[string]string) { // server that always returns 200 (and a key) key, err := trustmanager.GenerateECDSAKey(rand.Reader) assert.NoError(t, err) pubKey := data.PublicKeyFromPrivate(key) jsonBytes, err := json.MarshalCanonical(&pubKey) assert.NoError(t, err) keyJSON := string(jsonBytes) ts := httptest.NewServer(http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, keyJSON) })) repo, err := client.NewNotaryRepository( tempBaseDir, gun, ts.URL, http.DefaultTransport, ret) assert.NoError(t, err, "error creating repo: %s", err) rootPubKey, err := repo.CryptoService.Create("root", data.ECDSAKey) assert.NoError(t, err, "error generating root key: %s", err) err = repo.Initialize(rootPubKey.ID()) assert.NoError(t, err) return ts, repo.CryptoService.ListAllKeys() }
func TestDuplicateSigs(t *testing.T) { cs := NewEd25519() k, err := cs.Create("root", data.ED25519Key) assert.NoError(t, err) r, err := data.NewRole( "root", 2, []string{k.ID()}, nil, nil, ) assert.NoError(t, err) db := keys.NewDB() assert.NoError(t, err) db.AddKey(k) err = db.AddRole(r) assert.NoError(t, err) meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) assert.NoError(t, err) s := &data.Signed{Signed: b} Sign(cs, s, k) s.Signatures = append(s.Signatures, s.Signatures[0]) err = Verify(s, "root", 1, db) assert.IsType(t, ErrRoleThreshold{}, err) }
// VerifySignatures checks the we have sufficient valid signatures for the given role func VerifySignatures(s *data.Signed, role string, db *keys.KeyDB) error { if len(s.Signatures) == 0 { return ErrNoSignatures } roleData := db.GetRole(role) if roleData == nil { return ErrUnknownRole } if roleData.Threshold < 1 { return ErrRoleThreshold{} } logrus.Debugf("%s role has key IDs: %s", role, strings.Join(roleData.KeyIDs, ",")) var decoded map[string]interface{} if err := json.Unmarshal(s.Signed, &decoded); err != nil { return err } msg, err := json.MarshalCanonical(decoded) if err != nil { return err } valid := make(map[string]struct{}) for _, sig := range s.Signatures { logrus.Debug("verifying signature for key ID: ", sig.KeyID) if !roleData.ValidKey(sig.KeyID) { logrus.Debugf("continuing b/c keyid was invalid: %s for roledata %s\n", sig.KeyID, roleData) continue } key := db.GetKey(sig.KeyID) if key == nil { logrus.Debugf("continuing b/c keyid lookup was nil: %s\n", sig.KeyID) continue } // method lookup is consistent due to Unmarshal JSON doing lower case for us. method := sig.Method verifier, ok := Verifiers[method] if !ok { logrus.Debugf("continuing b/c signing method is not supported: %s\n", sig.Method) continue } if err := verifier.Verify(key, sig.Signature, msg); err != nil { logrus.Debugf("continuing b/c signature was invalid\n") continue } valid[sig.KeyID] = struct{}{} } if len(valid) < roleData.Threshold { return ErrRoleThreshold{} } return nil }
func TestIsValidNotExported(t *testing.T) { cs := NewEd25519() k, err := cs.Create(data.CanonicalRootRole, "", data.ED25519Key) require.NoError(t, err) meta := &data.SignedCommon{Type: data.TUFTypes[data.CanonicalRootRole], Version: 1, Expires: data.DefaultExpires(data.CanonicalRootRole)} b, err := json.MarshalCanonical(meta) require.NoError(t, err) s := &data.Signed{Signed: (*json.RawMessage)(&b)} require.NoError(t, Sign(cs, s, []data.PublicKey{k}, 1, nil)) require.Equal(t, 1, len(s.Signatures)) before, err := json.MarshalCanonical(s.Signatures[0]) require.NoError(t, err) require.False(t, s.Signatures[0].IsValid) require.NoError(t, VerifySignature(b, &(s.Signatures[0]), k)) // the IsValid field changed require.True(t, s.Signatures[0].IsValid) after, err := json.MarshalCanonical(s.Signatures[0]) require.NoError(t, err) // but the marshalled byte strings stay the same since IsValid is not exported require.Equal(t, before, after) }
// SetInvalidSigned corrupts the metadata into something that is valid JSON, // but not unmarshallable into signed JSON func (m *MetadataSwizzler) SetInvalidSigned(role string) error { signedThing, err := signedFromStore(m.MetadataCache, role) if err != nil { return err } metaBytes, err := json.MarshalCanonical(map[string]interface{}{ "signed": signedThing.Signed, "signatures": "not list", }) if err != nil { return err } return m.MetadataCache.Set(role, metaBytes) }
func TestNoSigs(t *testing.T) { cs := NewEd25519() k, err := cs.Create("root", "", data.ED25519Key) require.NoError(t, err) require.NoError(t, err) roleWithKeys := data.BaseRole{Name: "root", Keys: data.Keys{k.ID(): k}, Threshold: 2} meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) require.NoError(t, err) s := &data.Signed{Signed: (*json.RawMessage)(&b)} require.Equal(t, ErrNoSignatures, VerifySignatures(s, roleWithKeys)) }
// VerifySignatures checks the we have sufficient valid signatures for the given role func VerifySignatures(s *data.Signed, roleData data.BaseRole) error { if len(s.Signatures) == 0 { return ErrNoSignatures } if roleData.Threshold < 1 { return ErrRoleThreshold{} } logrus.Debugf("%s role has key IDs: %s", roleData.Name, strings.Join(roleData.ListKeyIDs(), ",")) // remarshal the signed part so we can verify the signature, since the signature has // to be of a canonically marshalled signed object var decoded map[string]interface{} if err := json.Unmarshal(s.Signed, &decoded); err != nil { return err } msg, err := json.MarshalCanonical(decoded) if err != nil { return err } valid := make(map[string]struct{}) for _, sig := range s.Signatures { logrus.Debug("verifying signature for key ID: ", sig.KeyID) key, ok := roleData.Keys[sig.KeyID] if !ok { logrus.Debugf("continuing b/c keyid lookup was nil: %s\n", sig.KeyID) continue } // method lookup is consistent due to Unmarshal JSON doing lower case for us. method := sig.Method verifier, ok := Verifiers[method] if !ok { logrus.Debugf("continuing b/c signing method is not supported: %s\n", sig.Method) continue } if err := verifier.Verify(key, sig.Signature, msg); err != nil { logrus.Debugf("continuing b/c signature was invalid\n") continue } valid[sig.KeyID] = struct{}{} } if len(valid) < roleData.Threshold { return ErrRoleThreshold{} } return nil }
func TestRootToSignedMarshalsSignedPortionWithCanonicalJSON(t *testing.T) { r := SignedRoot{Signed: Root{Type: "root", Version: 2, Expires: time.Now()}} signedCanonical, err := r.ToSigned() require.NoError(t, err) canonicalSignedPortion, err := cjson.MarshalCanonical(r.Signed) require.NoError(t, err) castedCanonical := rjson.RawMessage(canonicalSignedPortion) // don't bother testing regular JSON because it might not be different require.True(t, bytes.Equal(signedCanonical.Signed, castedCanonical), "expected %v == %v", signedCanonical.Signed, castedCanonical) }
func TestTargetsToSignedMarshalsSignedPortionWithCanonicalJSON(t *testing.T) { tg := SignedTargets{Signed: Targets{SignedCommon: SignedCommon{Type: "Targets", Version: 1, Expires: time.Now()}}} signedCanonical, err := tg.ToSigned() require.NoError(t, err) canonicalSignedPortion, err := cjson.MarshalCanonical(tg.Signed) require.NoError(t, err) castedCanonical := rjson.RawMessage(canonicalSignedPortion) // don't bother testing regular JSON because it might not be different require.True(t, bytes.Equal(signedCanonical.Signed, castedCanonical), "expected %v == %v", signedCanonical.Signed, castedCanonical) }
// VerifySignatures checks the we have sufficient valid signatures for the given role func VerifySignatures(s *data.Signed, roleData data.BaseRole) error { if len(s.Signatures) == 0 { return ErrNoSignatures } if roleData.Threshold < 1 { return ErrRoleThreshold{} } logrus.Debugf("%s role has key IDs: %s", roleData.Name, strings.Join(roleData.ListKeyIDs(), ",")) // remarshal the signed part so we can verify the signature, since the signature has // to be of a canonically marshalled signed object var decoded map[string]interface{} if err := json.Unmarshal(*s.Signed, &decoded); err != nil { return err } msg, err := json.MarshalCanonical(decoded) if err != nil { return err } valid := make(map[string]struct{}) for i := range s.Signatures { sig := &(s.Signatures[i]) logrus.Debug("verifying signature for key ID: ", sig.KeyID) key, ok := roleData.Keys[sig.KeyID] if !ok { logrus.Debugf("continuing b/c keyid lookup was nil: %s\n", sig.KeyID) continue } // Check that the signature key ID actually matches the content ID of the key if key.ID() != sig.KeyID { return ErrInvalidKeyID{} } if err := VerifySignature(msg, sig, key); err != nil { logrus.Debugf("continuing b/c %s", err.Error()) continue } valid[sig.KeyID] = struct{}{} } if len(valid) < roleData.Threshold { return ErrRoleThreshold{ Msg: fmt.Sprintf("valid signatures did not meet threshold for %s", roleData.Name), } } return nil }
func TestHTTPStoreGetMeta(t *testing.T) { handler := func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(testRoot)) } server := httptest.NewServer(http.HandlerFunc(handler)) defer server.Close() store, err := NewHTTPStore( server.URL, "metadata", "txt", "key", &http.Transport{}, ) if err != nil { t.Fatal(err) } j, err := store.GetMeta("root", 4801) if err != nil { t.Fatal(err) } p := &data.Signed{} err = json.Unmarshal(j, p) if err != nil { t.Fatal(err) } rootKey, err := base64.StdEncoding.DecodeString(testRootKey) require.NoError(t, err) k := data.NewPublicKey("ecdsa-x509", rootKey) sigBytes := p.Signatures[0].Signature if err != nil { t.Fatal(err) } var decoded map[string]interface{} if err := json.Unmarshal(*p.Signed, &decoded); err != nil { t.Fatal(err) } msg, err := json.MarshalCanonical(decoded) if err != nil { t.Fatal(err) } method := p.Signatures[0].Method err = signed.Verifiers[method].Verify(k, sigBytes, msg) if err != nil { t.Fatal(err) } }
func TestDuplicateSigs(t *testing.T) { cs := NewEd25519() k, err := cs.Create("root", data.ED25519Key) assert.NoError(t, err) roleWithKeys := data.BaseRole{Name: "root", Keys: data.Keys{k.ID(): k}, Threshold: 2} meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) assert.NoError(t, err) s := &data.Signed{Signed: b} Sign(cs, s, k) s.Signatures = append(s.Signatures, s.Signatures[0]) err = Verify(s, roleWithKeys, 1) assert.IsType(t, ErrRoleThreshold{}, err) }
func TestSnapshotToSignedMarshalsSignedPortionWithCanonicalJSON(t *testing.T) { sn := SignedSnapshot{Signed: Snapshot{SignedCommon: SignedCommon{ Type: TUFTypes[CanonicalSnapshotRole], Version: 1, Expires: time.Now()}}} signedCanonical, err := sn.ToSigned() require.NoError(t, err) canonicalSignedPortion, err := cjson.MarshalCanonical(sn.Signed) require.NoError(t, err) castedCanonical := rjson.RawMessage(canonicalSignedPortion) // don't bother testing regular JSON because it might not be different require.True(t, bytes.Equal(*signedCanonical.Signed, castedCanonical), "expected %v == %v", signedCanonical.Signed, castedCanonical) }
func TestNotEnoughSigs(t *testing.T) { cs := NewEd25519() k, err := cs.Create("root", "", data.ED25519Key) require.NoError(t, err) require.NoError(t, err) roleWithKeys := data.BaseRole{Name: "root", Keys: data.Keys{k.ID(): k}, Threshold: 2} meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) require.NoError(t, err) s := &data.Signed{Signed: (*json.RawMessage)(&b)} require.NoError(t, Sign(cs, s, []data.PublicKey{k}, 1, nil)) err = VerifySignatures(s, roleWithKeys) require.IsType(t, ErrRoleThreshold{}, err) }
// ToSigned partially serializes a SignedTargets for further signing func (t SignedTargets) ToSigned() (*Signed, error) { s, err := json.MarshalCanonical(t.Signed) if err != nil { return nil, err } signed := json.RawMessage{} err = signed.UnmarshalJSON(s) if err != nil { return nil, err } sigs := make([]Signature, len(t.Signatures)) copy(sigs, t.Signatures) return &Signed{ Signatures: sigs, Signed: signed, }, nil }
func TestMoreThanEnoughSigs(t *testing.T) { cs := NewEd25519() k1, err := cs.Create("root", data.ED25519Key) assert.NoError(t, err) k2, err := cs.Create("root", data.ED25519Key) assert.NoError(t, err) roleWithKeys := data.BaseRole{Name: "root", Keys: data.Keys{k1.ID(): k1, k2.ID(): k2}, Threshold: 1} meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) assert.NoError(t, err) s := &data.Signed{Signed: b} Sign(cs, s, k1, k2) assert.Equal(t, 2, len(s.Signatures)) err = Verify(s, roleWithKeys, 1) assert.NoError(t, err) }
// ID efficiently generates if necessary, and caches the ID of the key func (k *TUFKey) ID() string { if k.id == "" { pubK := TUFKey{ Type: k.Algorithm(), Value: KeyPair{ Public: k.Public(), Private: nil, }, } data, err := json.MarshalCanonical(&pubK) if err != nil { logrus.Error("Error generating key ID:", err) } digest := sha256.Sum256(data) k.id = hex.EncodeToString(digest[:]) } return k.id }
func TestExactlyEnoughSigs(t *testing.T) { cs := NewEd25519() k, err := cs.Create(data.CanonicalRootRole, "", data.ED25519Key) require.NoError(t, err) roleWithKeys := data.BaseRole{ Name: data.CanonicalRootRole, Keys: data.Keys{k.ID(): k}, Threshold: 1} meta := &data.SignedCommon{Type: data.TUFTypes[data.CanonicalRootRole], Version: 1, Expires: data.DefaultExpires(data.CanonicalRootRole)} b, err := json.MarshalCanonical(meta) require.NoError(t, err) s := &data.Signed{Signed: (*json.RawMessage)(&b)} require.NoError(t, Sign(cs, s, []data.PublicKey{k}, 1, nil)) require.Equal(t, 1, len(s.Signatures)) require.NoError(t, VerifySignatures(s, roleWithKeys)) }
func TestValidSigWithIncorrectKeyID(t *testing.T) { cs := NewEd25519() k1, err := cs.Create("root", "", data.ED25519Key) require.NoError(t, err) roleWithKeys := data.BaseRole{Name: "root", Keys: data.Keys{"invalidIDA": k1}, Threshold: 1} meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) require.NoError(t, err) s := &data.Signed{Signed: (*json.RawMessage)(&b)} require.NoError(t, Sign(cs, s, []data.PublicKey{k1}, 1, nil)) require.Equal(t, 1, len(s.Signatures)) s.Signatures[0].KeyID = "invalidIDA" err = VerifySignatures(s, roleWithKeys) require.Error(t, err) require.IsType(t, ErrInvalidKeyID{}, err) }
func TestDuplicateSigs(t *testing.T) { cs := NewEd25519() k, err := cs.Create("root", "", data.ED25519Key) require.NoError(t, err) roleWithKeys := data.BaseRole{Name: "root", Keys: data.Keys{k.ID(): k}, Threshold: 2} meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) require.NoError(t, err) s := &data.Signed{Signed: (*json.RawMessage)(&b)} require.NoError(t, Sign(cs, s, []data.PublicKey{k}, 1, nil)) s.Signatures = append(s.Signatures, s.Signatures[0]) err = VerifySignatures(s, roleWithKeys) require.IsType(t, ErrRoleThreshold{}, err) // both (instances of the same signature) are valid but we still don't hit our threshold require.True(t, s.Signatures[0].IsValid) require.True(t, s.Signatures[1].IsValid) }
func TestMoreThanEnoughSigs(t *testing.T) { cs := NewEd25519() k1, err := cs.Create("root", "", data.ED25519Key) require.NoError(t, err) k2, err := cs.Create("root", "", data.ED25519Key) require.NoError(t, err) roleWithKeys := data.BaseRole{Name: "root", Keys: data.Keys{k1.ID(): k1, k2.ID(): k2}, Threshold: 1} meta := &data.SignedCommon{Type: "Root", Version: 1, Expires: data.DefaultExpires("root")} b, err := json.MarshalCanonical(meta) require.NoError(t, err) s := &data.Signed{Signed: (*json.RawMessage)(&b)} require.NoError(t, Sign(cs, s, []data.PublicKey{k1, k2}, 2, nil)) require.Equal(t, 2, len(s.Signatures)) err = VerifySignatures(s, roleWithKeys) require.NoError(t, err) }
// NewRepoMetadata creates a TUF repo and returns the metadata func NewRepoMetadata(gun string, delegationRoles ...string) (map[string][]byte, signed.CryptoService, error) { _, tufRepo, cs, err := EmptyRepo(gun, delegationRoles...) if err != nil { return nil, nil, err } meta := make(map[string][]byte) for _, delgName := range delegationRoles { // is there metadata yet? if empty, it may not be created if _, ok := tufRepo.Targets[delgName]; ok { signedThing, err := tufRepo.SignTargets(delgName, data.DefaultExpires("targets")) if err != nil { return nil, nil, err } metaBytes, err := json.MarshalCanonical(signedThing) if err != nil { return nil, nil, err } meta[delgName] = metaBytes } } // these need to be generated after the delegations are created and signed so // the snapshot will have the delegation metadata rs, tgs, ss, ts, err := Sign(tufRepo) if err != nil { return nil, nil, err } rf, tgf, sf, tf, err := Serialize(rs, tgs, ss, ts) if err != nil { return nil, nil, err } meta[data.CanonicalRootRole] = rf meta[data.CanonicalSnapshotRole] = sf meta[data.CanonicalTargetsRole] = tgf meta[data.CanonicalTimestampRole] = tf return meta, cs, nil }
// SignAndSerialize calls Sign and then Serialize to get the repo metadata out func SignAndSerialize(tufRepo *tuf.Repo) (map[string][]byte, error) { meta := make(map[string][]byte) for delgName := range tufRepo.Targets { // we'll sign targets later if delgName == data.CanonicalTargetsRole { continue } signedThing, err := tufRepo.SignTargets(delgName, data.DefaultExpires("targets")) if err != nil { return nil, err } metaBytes, err := json.MarshalCanonical(signedThing) if err != nil { return nil, err } meta[delgName] = metaBytes } // these need to be generated after the delegations are created and signed so // the snapshot will have the delegation metadata rs, tgs, ss, ts, err := Sign(tufRepo) if err != nil { return nil, err } rf, tgf, sf, tf, err := Serialize(rs, tgs, ss, ts) if err != nil { return nil, err } meta[data.CanonicalRootRole] = rf meta[data.CanonicalSnapshotRole] = sf meta[data.CanonicalTargetsRole] = tgf meta[data.CanonicalTimestampRole] = tf return meta, nil }