package verify import ( "testing" "github.com/stretchr/testify/assert" "github.com/theupdateframework/go-tuf/data" "github.com/theupdateframework/go-tuf/pkg/keys" ) func TestDelegationsDB(t *testing.T) { key, err := keys.GenerateEd25519Key() assert.Nil(t, err, "generating key failed") var dbTests = []struct { testName string delegations *data.Delegations initErr error unmarshalErr error }{ { testName: "empty state", delegations: &data.Delegations{}, unmarshalErr: ErrNoSignatures, }, { testName: "top level role", delegations: &data.Delegations{Roles: []data.DelegatedRole{ {Name: "root"}, }}, initErr: ErrInvalidDelegatedRole, }, { testName: "invalid role", delegations: &data.Delegations{Roles: []data.DelegatedRole{ {Threshold: 0}, }}, initErr: ErrInvalidThreshold, }, { testName: "standard (SHA256) key IDs supported", delegations: &data.Delegations{ Keys: map[string]*data.PublicKey{ key.PublicData().IDs()[0]: key.PublicData(), }, Roles: []data.DelegatedRole{{ Name: "rolename", KeyIDs: key.PublicData().IDs(), Threshold: 1, }, }, }, // If we get to ErrNoSignatures, we've passed key loading; see // delegations_test.go to see tests that delegation DB *fully* works // with valid signatures set up. unmarshalErr: ErrNoSignatures, }, { testName: "arbitrary (non-SHA256, per TAP-12) key IDs supported", delegations: &data.Delegations{ Keys: map[string]*data.PublicKey{ "a": key.PublicData(), }, Roles: []data.DelegatedRole{{ Name: "rolename", KeyIDs: []string{"a"}, Threshold: 1, }, }, }, // If we get to ErrNoSignatures, we've passed key loading; see // delegations_test.go to see tests that delegation DB *fully* works // with valid signatures set up. unmarshalErr: ErrNoSignatures, }, } for _, tt := range dbTests { t.Run(tt.testName, func(t *testing.T) { db, err := NewDBFromDelegations(tt.delegations) assert.Equal(t, tt.initErr, err) if err == nil { assert.NotNil(t, db) var targets data.Targets err = db.Unmarshal([]byte(`{"a":"b"}`), targets, "tree", 0) assert.Equal(t, tt.unmarshalErr, err) } }) } } // Test key database for compliance with TAP-12. // // Previously, every key's key ID was the SHA256 of the public key. TAP-12 // allows arbitrary key IDs, with no loss in security. // // TAP-12: https://github.com/theupdateframework/taps/blob/master/tap12.md func TestTAP12(t *testing.T) { db := NewDB() // Need to use a signer type that supports random signatures. key1, _ := keys.GenerateRsaKey() key2, _ := keys.GenerateRsaKey() msg := []byte("{}") sig1, _ := key1.SignMessage(msg) sig1Duplicate, _ := key1.SignMessage(msg) assert.NotEqual(t, sig1, sig1Duplicate, "Signatures should be random") sig2, _ := key2.SignMessage(msg) // Idempotent: adding the same key with the same ID is okay. assert.Nil(t, db.AddKey("key1", key1.PublicData()), "initial add") assert.Nil(t, db.AddKey("key1", key1.PublicData()), "re-add") // Adding a different key is allowed, unless the key ID is the same. assert.Nil(t, db.AddKey("key2", key2.PublicData()), "different key with different ID") assert.ErrorIs(t, db.AddKey("key1", key2.PublicData()), ErrRepeatID{"key1"}, "different key with same key ID") assert.Nil(t, db.AddKey("key1-duplicate", key1.PublicData()), "same key with different ID should succeed") assert.Nil(t, db.AddRole("diffkeys", &data.Role{ KeyIDs: []string{"key1", "key2"}, Threshold: 2, }), "adding role") assert.Nil(t, db.AddRole("samekeys", &data.Role{ KeyIDs: []string{"key1", "key1-alt"}, Threshold: 2, }), "adding role") assert.Nil(t, db.VerifySignatures(&data.Signed{ Signed: msg, Signatures: []data.Signature{{KeyID: "key1", Signature: sig1}, {KeyID: "key2", Signature: sig2}}, }, "diffkeys"), "Signature with different keys: ") assert.ErrorIs(t, db.VerifySignatures(&data.Signed{ Signed: msg, Signatures: []data.Signature{{KeyID: "key1", Signature: sig1}, {KeyID: "key1-alt", Signature: sig1Duplicate}}, }, "samekeys"), ErrRoleThreshold{2, 1}, "Threshold signing with repeat key") }