blob: 01d7a308171f05da27565e373cd1dabe4865875d [file] [log] [blame]
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")
}