func getPubKeys(cs signed.CryptoService, s *data.Signed, role string) ([]data.PublicKey, error) { var pubKeys []data.PublicKey if role == data.CanonicalRootRole { // if this is root metadata, we have to get the keys from the root because they // are certs root := &data.Root{} if err := json.Unmarshal(*s.Signed, root); err != nil { return nil, err } rootRole, ok := root.Roles[data.CanonicalRootRole] if !ok || rootRole == nil { return nil, tuf.ErrNotLoaded{} } for _, pubKeyID := range rootRole.KeyIDs { pubKeys = append(pubKeys, root.Keys[pubKeyID]) } } else { pubKeyIDs := cs.ListKeys(role) for _, pubKeyID := range pubKeyIDs { pubKey := cs.GetKey(pubKeyID) if pubKey != nil { pubKeys = append(pubKeys, pubKey) } } } return pubKeys, nil }
// GetOrCreateSnapshotKey either creates a new snapshot key, or returns // the existing one. Only the PublicKey is returned. The private part // is held by the CryptoService. func GetOrCreateSnapshotKey(gun string, store storage.MetaStore, crypto signed.CryptoService, createAlgorithm string) (data.PublicKey, error) { _, rootJSON, err := store.GetCurrent(gun, data.CanonicalRootRole) if err != nil { // If the error indicates we couldn't find the root, create a new key if _, ok := err.(storage.ErrNotFound); !ok { logrus.Errorf("Error when retrieving root role for GUN %s: %v", gun, err) return nil, err } return crypto.Create(data.CanonicalSnapshotRole, gun, createAlgorithm) } // If we have a current root, parse out the public key for the snapshot role, and return it repoSignedRoot := new(data.SignedRoot) if err := json.Unmarshal(rootJSON, repoSignedRoot); err != nil { logrus.Errorf("Failed to unmarshal existing root for GUN %s to retrieve snapshot key ID", gun) return nil, err } snapshotRole, err := repoSignedRoot.BuildBaseRole(data.CanonicalSnapshotRole) if err != nil { logrus.Errorf("Failed to extract snapshot role from root for GUN %s", gun) return nil, err } // We currently only support single keys for snapshot and timestamp, so we can return the first and only key in the map if the signer has it for keyID := range snapshotRole.Keys { if pubKey := crypto.GetKey(keyID); pubKey != nil { return pubKey, nil } } logrus.Debugf("Failed to find any snapshot keys in cryptosigner from root for GUN %s, generating new key", gun) return crypto.Create(data.CanonicalSnapshotRole, gun, createAlgorithm) }
// EmptyCryptoServiceInterfaceBehaviorTests tests expected behavior for // an empty signed.CryptoService: // 1. Getting the public key of a key that doesn't exist should fail // 2. Listing an empty cryptoservice returns no keys // 3. Removing a non-existent key succeeds (no-op) func EmptyCryptoServiceInterfaceBehaviorTests(t *testing.T, empty signed.CryptoService) { for _, role := range append(data.BaseRoles, "targets/delegation", "invalid") { keys := empty.ListKeys(role) require.Len(t, keys, 0) } keys := empty.ListAllKeys() require.Len(t, keys, 0) require.NoError(t, empty.RemoveKey("nonexistent")) require.Nil(t, empty.GetKey("nonexistent")) k, role, err := empty.GetPrivateKey("nonexistent") require.Error(t, err) require.Nil(t, k) require.Equal(t, "", role) }
func testGetKey(t *testing.T, cs signed.CryptoService, expectedRolesToKeys map[string]string, algo string) { for role, keyID := range expectedRolesToKeys { pubKey := cs.GetKey(keyID) require.NotNil(t, pubKey) require.Equal(t, keyID, pubKey.ID()) require.Equal(t, algo, pubKey.Algorithm()) privKey, gotRole, err := cs.GetPrivateKey(keyID) require.NoError(t, err) require.NotNil(t, privKey) require.Equal(t, keyID, privKey.ID()) require.Equal(t, algo, privKey.Algorithm()) require.Equal(t, role, gotRole) require.NoError(t, cs.RemoveKey(keyID)) require.Nil(t, cs.GetKey(keyID)) } }