Repository: theupdateframework/go-tuf
Pull request #253 (2022-03-30 13:41:13)

chore(deps): bump actions/checkout from 2 to 3
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p>
<blockquote>
<h2>v3.0.0</h2>
<ul>
<li>Updated to the node16 runtime by default
<ul>
<li>This requires a minimum <a href="https://github.com/actions/runner/releases/tag/v2.285.0">Actions Runner</a> version of v2.285.0 to run, which is by default available in GHES 3.4 or later.</li>
</ul>
</li>
</ul>
<h2>v2.4.0</h2>
<ul>
<li>Convert SSH URLs like <code>org-&lt;ORG_ID&gt;@github.com:</code> to <code>https://github.com/</code> - <a href="https://github-redirect.dependabot.com/actions/checkout/pull/621">pr</a></li>
</ul>
<h2>v2.3.5</h2>
<p>Update dependencies</p>
<h2>v2.3.4</h2>
<ul>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/379">Add missing <code>await</code>s</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/360">Swap to Environment Files</a></li>
</ul>
<h2>v2.3.3</h2>
<ul>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/345">Remove Unneeded commit information from build logs</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/326">Add Licensed to verify third party dependencies</a></li>
</ul>
<h2>v2.3.2</h2>
<p><a href="https://github-redirect.dependabot.com/actions/checkout/pull/320">Add Third Party License Information to Dist Files</a></p>
<h2>v2.3.1</h2>
<p><a href="https://github-redirect.dependabot.com/actions/checkout/pull/284">Fix default branch resolution for .wiki and when using SSH</a></p>
<h2>v2.3.0</h2>
<p><a href="https://github-redirect.dependabot.com/actions/checkout/pull/278">Fallback to the default branch</a></p>
<h2>v2.2.0</h2>
<p><a href="https://github-redirect.dependabot.com/actions/checkout/pull/258">Fetch all history for all tags and branches when fetch-depth=0</a></p>
<h2>v2.1.1</h2>
<p>Changes to support GHES (<a href="https://github-redirect.dependabot.com/actions/checkout/pull/236">here</a> and <a href="https://github-redirect.dependabot.com/actions/checkout/pull/248">here</a>)</p>
<h2>v2.1.0</h2>
<ul>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/191">Group output</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/199">Changes to support GHES alpha release</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/184">Persist core.sshCommand for submodules</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/163">Add support ssh</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/179">Convert submodule SSH URL to HTTPS, when not using SSH</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/157">Add submodule support</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/144">Follow proxy settings</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/141">Fix ref for pr closed event when a pr is merged</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/128">Fix issue checking detached when git less than 2.22</a></li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<h2>v3.0.0</h2>
<ul>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/689">Update to node 16</a></li>
</ul>
<h2>v2.3.1</h2>
<ul>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/284">Fix default branch resolution for .wiki and when using SSH</a></li>
</ul>
<h2>v2.3.0</h2>
<ul>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/278">Fallback to the default branch</a></li>
</ul>
<h2>v2.2.0</h2>
<ul>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/258">Fetch all history for all tags and branches when fetch-depth=0</a></li>
</ul>
<h2>v2.1.1</h2>
<ul>
<li>Changes to support GHES (<a href="https://github-redirect.dependabot.com/actions/checkout/pull/236">here</a> and <a href="https://github-redirect.dependabot.com/actions/checkout/pull/248">here</a>)</li>
</ul>
<h2>v2.1.0</h2>
<ul>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/191">Group output</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/199">Changes to support GHES alpha release</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/184">Persist core.sshCommand for submodules</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/163">Add support ssh</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/179">Convert submodule SSH URL to HTTPS, when not using SSH</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/157">Add submodule support</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/144">Follow proxy settings</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/141">Fix ref for pr closed event when a pr is merged</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/128">Fix issue checking detached when git less than 2.22</a></li>
</ul>
<h2>v2.0.0</h2>
<ul>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/108">Do not pass cred on command line</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/107">Add input persist-credentials</a></li>
<li><a href="https://github-redirect.dependabot.com/actions/checkout/pull/104">Fallback to REST API to download repo</a></li>
</ul>
<h2>v2 (beta)</h2>
<ul>
<li>Improved fetch performance
<ul>
<li>The default behavior now fetches only the SHA being checked-out</li>
</ul>
</li>
<li>Script authenticated git commands
<ul>
<li>Persists <code>with.token</code> in the local git config</li>
<li>Enables your scripts to run authenticated git commands</li>
<li>Post-job cleanup removes the token</li>
<li>Coming soon: Opt out by setting <code>with.persist-credentials</code> to <code>false</code></li>
</ul>
</li>
<li>Creates a local branch</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/actions/checkout/commit/a12a3943b4bdde767164f792f33f40b04645d846"><code>a12a394</code></a> update readme for v3 (<a href="https://github-redirect.dependabot.com/actions/checkout/issues/708">#708</a>)</li>
<li><a href="https://github.com/actions/checkout/commit/8f9e05e482293f862823fcca12d9eddfb3723131"><code>8f9e05e</code></a> Update to node 16 (<a href="https://github-redirect.dependabot.com/actions/checkout/issues/689">#689</a>)</li>
<li><a href="https://github.com/actions/checkout/commit/230611dbd0eb52da1e1f4f7bc8bb0c3a339fc8b7"><code>230611d</code></a> Change secret name for PAT to not start with GITHUB_ (<a href="https://github-redirect.dependabot.com/actions/checkout/issues/623">#623</a>)</li>
<li>See full diff in <a href="https://github.com/actions/checkout/compare/v2...v3">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=2&new-version=3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

asraa: @theupdateframework/go-tuf-maintainers this is an easy one, PTAL

Patch:
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 212efcd..72466fc 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -38,7 +38,7 @@ jobs:
 
     steps:
     - name: Checkout repository
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ac54755..a6950dc 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -12,7 +12,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout
-        uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
+        uses: actions/checkout@v3
         with:
           fetch-depth: 0
       - name: Get Go version
diff --git a/MAINTAINERS b/MAINTAINERS
index d3443b1..4d0cfe7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3,4 +3,6 @@ Trishank Karthik Kuppusamy <trishank.kuppusamy@datadoghq.com> (github: trishanka
 Joshua Lock <jlock@vmware.com> (github: joshuagl)
 Ethan Lownman <ethan.lowman@datadoghq.com> (github: ethan-lowman-dd)
 Marina Moore <mm9693@nyu.edu> (github: mnm678)
+Zack Newman <zjn@chainguard.dev> (github: znewman01)
 Hossein Siadati <hossein.siadati@datadoghq.com> (github: hosseinsia)
+Radoslav Dimitrov <dimitrovr@vmware.com> (github: rdimitrov)
\ No newline at end of file
diff --git a/client/errors.go b/client/errors.go
index 44a36d2..0edd957 100644
--- a/client/errors.go
+++ b/client/errors.go
@@ -3,8 +3,6 @@ package client
 import (
 	"errors"
 	"fmt"
-
-	"github.com/theupdateframework/go-tuf/verify"
 )
 
 var (
@@ -49,20 +47,6 @@ func (e ErrMaxDelegations) Error() string {
 	return fmt.Sprintf("tuf: max delegation of %d reached searching for %s with snapshot version %d", e.MaxDelegations, e.Target, e.SnapshotVersion)
 }
 
-//lint:ignore U1000 unused
-func isDecodeFailedWithErrRoleThreshold(err error) bool {
-	e, ok := err.(ErrDecodeFailed)
-	if !ok {
-		return false
-	}
-	return isErrRoleThreshold(e.Err)
-}
-
-func isErrRoleThreshold(err error) bool {
-	_, ok := err.(verify.ErrRoleThreshold)
-	return ok
-}
-
 type ErrNotFound struct {
 	File string
 }
diff --git a/errors.go b/errors.go
index 1a8ab9f..09df039 100644
--- a/errors.go
+++ b/errors.go
@@ -88,3 +88,11 @@ type ErrPassphraseRequired struct {
 func (e ErrPassphraseRequired) Error() string {
 	return fmt.Sprintf("tuf: a passphrase is required to access the encrypted %s keys file", e.Role)
 }
+
+type ErrNoDelegatedTarget struct {
+	Path string
+}
+
+func (e ErrNoDelegatedTarget) Error() string {
+	return fmt.Sprintf("tuf: no delegated target for path %s", e.Path)
+}
diff --git a/local_store.go b/local_store.go
index 9456016..375a1ef 100644
--- a/local_store.go
+++ b/local_store.go
@@ -14,7 +14,6 @@ import (
 
 	"github.com/theupdateframework/go-tuf/data"
 	"github.com/theupdateframework/go-tuf/encrypted"
-	"github.com/theupdateframework/go-tuf/internal/roles"
 	"github.com/theupdateframework/go-tuf/internal/sets"
 	"github.com/theupdateframework/go-tuf/pkg/keys"
 	"github.com/theupdateframework/go-tuf/util"
@@ -43,6 +42,8 @@ type LocalStore interface {
 	Commit(bool, map[string]int64, map[string]data.Hashes) error
 
 	// GetSigners return a list of signers for a role.
+	// This may include revoked keys, so the signers should not
+	// be used without filtering.
 	GetSigners(role string) ([]keys.Signer, error)
 
 	// SaveSigner adds a signer to a role.
@@ -222,8 +223,7 @@ func (f *fileSystemStore) stagedDir() string {
 }
 
 func isMetaFile(e os.DirEntry) (bool, error) {
-	name := e.Name()
-	if e.IsDir() || !(filepath.Ext(name) == ".json" && roles.IsTopLevelManifest(name)) {
+	if e.IsDir() || filepath.Ext(e.Name()) != ".json" {
 		return false, nil
 	}
 
diff --git a/repo.go b/repo.go
index 1f513ec..0553fd6 100644
--- a/repo.go
+++ b/repo.go
@@ -11,16 +11,22 @@ import (
 	"strings"
 	"time"
 
-	"github.com/secure-systems-lab/go-securesystemslib/cjson"
 	"github.com/theupdateframework/go-tuf/data"
 	"github.com/theupdateframework/go-tuf/internal/roles"
+	"github.com/theupdateframework/go-tuf/internal/sets"
 	"github.com/theupdateframework/go-tuf/internal/signer"
 	"github.com/theupdateframework/go-tuf/pkg/keys"
+	"github.com/theupdateframework/go-tuf/pkg/targets"
 	"github.com/theupdateframework/go-tuf/sign"
 	"github.com/theupdateframework/go-tuf/util"
 	"github.com/theupdateframework/go-tuf/verify"
 )
 
+const (
+	// The maximum number of delegations to visit while traversing the delegations graph.
+	defaultMaxDelegations = 32
+)
+
 // topLevelMetadata determines the order signatures are verified when committing.
 var topLevelMetadata = []string{
 	"root.json",
@@ -74,12 +80,15 @@ func (r *Repo) Init(consistentSnapshot bool) error {
 	root.ConsistentSnapshot = consistentSnapshot
 	// Set root version to 1 for a new root.
 	root.Version = 1
-	if err = r.setTopLevelMeta("root.json", root); err != nil {
+	if err = r.setMeta("root.json", root); err != nil {
 		return err
 	}
-	if err = r.writeTargetWithExpires(t, data.DefaultExpires("targets")); err != nil {
+
+	t.Version = 1
+	if err = r.setMeta("targets.json", t); err != nil {
 		return err
 	}
+
 	fmt.Println("Repository initialized")
 	return nil
 }
@@ -152,9 +161,9 @@ func (r *Repo) RootVersion() (int64, error) {
 }
 
 func (r *Repo) GetThreshold(keyRole string) (int, error) {
-	if !roles.IsTopLevelRole(keyRole) {
-		// Delegations are not currently supported, so return an error if this is not a
-		// top-level metadata file.
+	if roles.IsDelegatedTargetsRole(keyRole) {
+		// The signature threshold for a delegated targets role
+		// depends on the incoming delegation edge.
 		return -1, ErrInvalidRole{keyRole, "only thresholds for top-level roles supported"}
 	}
 	root, err := r.root()
@@ -170,9 +179,9 @@ func (r *Repo) GetThreshold(keyRole string) (int, error) {
 }
 
 func (r *Repo) SetThreshold(keyRole string, t int) error {
-	if !roles.IsTopLevelRole(keyRole) {
-		// Delegations are not currently supported, so return an error if this is not a
-		// top-level metadata file.
+	if roles.IsDelegatedTargetsRole(keyRole) {
+		// The signature threshold for a delegated targets role
+		// depends on the incoming delegation edge.
 		return ErrInvalidRole{keyRole, "only thresholds for top-level roles supported"}
 	}
 	root, err := r.root()
@@ -191,7 +200,7 @@ func (r *Repo) SetThreshold(keyRole string, t int) error {
 	if !r.local.FileIsStaged("root.json") {
 		root.Version++
 	}
-	return r.setTopLevelMeta("root.json", root)
+	return r.setMeta("root.json", root)
 }
 
 func (r *Repo) Targets() (data.TargetFiles, error) {
@@ -208,7 +217,7 @@ func (r *Repo) SetTargetsVersion(v int64) error {
 		return err
 	}
 	t.Version = v
-	return r.setTopLevelMeta("targets.json", t)
+	return r.setMeta("targets.json", t)
 }
 
 func (r *Repo) TargetsVersion() (int64, error) {
@@ -225,7 +234,7 @@ func (r *Repo) SetTimestampVersion(v int64) error {
 		return err
 	}
 	ts.Version = v
-	return r.setTopLevelMeta("timestamp.json", ts)
+	return r.setMeta("timestamp.json", ts)
 }
 
 func (r *Repo) TimestampVersion() (int64, error) {
@@ -243,7 +252,7 @@ func (r *Repo) SetSnapshotVersion(v int64) error {
 	}
 
 	s.Version = v
-	return r.setTopLevelMeta("snapshot.json", s)
+	return r.setMeta("snapshot.json", s)
 }
 
 func (r *Repo) SnapshotVersion() (int64, error) {
@@ -255,17 +264,21 @@ func (r *Repo) SnapshotVersion() (int64, error) {
 }
 
 func (r *Repo) topLevelTargets() (*data.Targets, error) {
-	targetsJSON, ok := r.meta["targets.json"]
+	return r.targets("targets")
+}
+
+func (r *Repo) targets(metaName string) (*data.Targets, error) {
+	targetsJSON, ok := r.meta[metaName+".json"]
 	if !ok {
 		return data.NewTargets(), nil
 	}
 	s := &data.Signed{}
 	if err := json.Unmarshal(targetsJSON, s); err != nil {
-		return nil, err
+		return nil, fmt.Errorf("error unmarshalling for targets %q: %w", metaName, err)
 	}
 	targets := &data.Targets{}
 	if err := json.Unmarshal(s.Signed, targets); err != nil {
-		return nil, err
+		return nil, fmt.Errorf("error unmarshalling signed data for targets %q: %w", metaName, err)
 	}
 	return targets, nil
 }
@@ -287,10 +300,6 @@ func (r *Repo) timestamp() (*data.Timestamp, error) {
 }
 
 func (r *Repo) ChangePassphrase(keyRole string) error {
-	if !roles.IsTopLevelRole(keyRole) {
-		return ErrInvalidRole{keyRole, "only support passphrases for top-level roles"}
-	}
-
 	if p, ok := r.local.(PassphraseChanger); ok {
 		return p.ChangePassphrase(keyRole)
 	}
@@ -299,10 +308,16 @@ func (r *Repo) ChangePassphrase(keyRole string) error {
 }
 
 func (r *Repo) GenKey(role string) ([]string, error) {
+	// Not compatible with delegated targets roles, since delegated targets keys
+	// are associated with a delegation (edge), not a role (node).
+
 	return r.GenKeyWithExpires(role, data.DefaultExpires(role))
 }
 
 func (r *Repo) GenKeyWithExpires(keyRole string, expires time.Time) (keyids []string, err error) {
+	// Not compatible with delegated targets roles, since delegated targets keys
+	// are associated with a delegation (edge), not a role (node).
+
 	signer, err := keys.GenerateEd25519Key()
 	if err != nil {
 		return []string{}, err
@@ -316,11 +331,17 @@ func (r *Repo) GenKeyWithExpires(keyRole string, expires time.Time) (keyids []st
 }
 
 func (r *Repo) AddPrivateKey(role string, signer keys.Signer) error {
+	// Not compatible with delegated targets roles, since delegated targets keys
+	// are associated with a delegation (edge), not a role (node).
+
 	return r.AddPrivateKeyWithExpires(role, signer, data.DefaultExpires(role))
 }
 
 func (r *Repo) AddPrivateKeyWithExpires(keyRole string, signer keys.Signer, expires time.Time) error {
-	if !roles.IsTopLevelRole(keyRole) {
+	// Not compatible with delegated targets roles, since delegated targets keys
+	// are associated with a delegation (edge), not a role (node).
+
+	if roles.IsDelegatedTargetsRole(keyRole) {
 		return ErrInvalidRole{keyRole, "only support adding keys for top-level roles"}
 	}
 
@@ -328,6 +349,8 @@ func (r *Repo) AddPrivateKeyWithExpires(keyRole string, signer keys.Signer, expi
 		return ErrInvalidExpires{expires}
 	}
 
+	// Must add signer before adding verification key, so
+	// root.json can be signed when a new root key is added.
 	if err := r.local.SaveSigner(keyRole, signer); err != nil {
 		return err
 	}
@@ -340,10 +363,27 @@ func (r *Repo) AddPrivateKeyWithExpires(keyRole string, signer keys.Signer, expi
 }
 
 func (r *Repo) AddVerificationKey(keyRole string, pk *data.PublicKey) error {
+	// Not compatible with delegated targets roles, since delegated targets keys
+	// are associated with a delegation (edge), not a role (node).
+
 	return r.AddVerificationKeyWithExpiration(keyRole, pk, data.DefaultExpires(keyRole))
 }
 
 func (r *Repo) AddVerificationKeyWithExpiration(keyRole string, pk *data.PublicKey, expires time.Time) error {
+	// Not compatible with delegated targets roles, since delegated targets keys
+	// are associated with a delegation (edge), not a role (node).
+
+	if roles.IsDelegatedTargetsRole(keyRole) {
+		return ErrInvalidRole{
+			Role:   keyRole,
+			Reason: "only top-level targets roles are supported",
+		}
+	}
+
+	if !validExpires(expires) {
+		return ErrInvalidExpires{expires}
+	}
+
 	root, err := r.root()
 	if err != nil {
 		return err
@@ -372,7 +412,7 @@ func (r *Repo) AddVerificationKeyWithExpiration(keyRole string, pk *data.PublicK
 		root.Version++
 	}
 
-	return r.setTopLevelMeta("root.json", root)
+	return r.setMeta("root.json", root)
 }
 
 func validExpires(expires time.Time) bool {
@@ -414,11 +454,17 @@ func (r *Repo) RootKeys() ([]*data.PublicKey, error) {
 }
 
 func (r *Repo) RevokeKey(role, id string) error {
+	// Not compatible with delegated targets roles, since delegated targets keys
+	// are associated with a delegation (edge), not a role (node).
+
 	return r.RevokeKeyWithExpires(role, id, data.DefaultExpires("root"))
 }
 
 func (r *Repo) RevokeKeyWithExpires(keyRole, id string, expires time.Time) error {
-	if !roles.IsTopLevelRole(keyRole) {
+	// Not compatible with delegated targets roles, since delegated targets keys
+	// are associated with a delegation (edge), not a role (node).
+
+	if roles.IsDelegatedTargetsRole(keyRole) {
 		return ErrInvalidRole{keyRole, "only revocations for top-level roles supported"}
 	}
 
@@ -477,37 +523,206 @@ func (r *Repo) RevokeKeyWithExpires(keyRole, id string, expires time.Time) error
 		root.Version++
 	}
 
-	err = r.setTopLevelMeta("root.json", root)
+	err = r.setMeta("root.json", root)
 	if err == nil {
 		fmt.Println("Revoked", keyRole, "key with ID", id, "in root metadata")
 	}
 	return err
 }
 
-func (r *Repo) jsonMarshal(v interface{}) ([]byte, error) {
-	b, err := cjson.EncodeCanonical(v)
+// AddDelegatedRole is equivalent to AddDelegatedRoleWithExpires, but
+// with a default expiration time.
+func (r *Repo) AddDelegatedRole(delegator string, delegatedRole data.DelegatedRole, keys []*data.PublicKey) error {
+	return r.AddDelegatedRoleWithExpires(delegator, delegatedRole, keys, data.DefaultExpires("targets"))
+}
+
+// AddDelegatedRoleWithExpires adds a delegation from the delegator to the
+// role specified in the role argument. Key IDs referenced in role.KeyIDs
+// should have corresponding Key entries in the keys argument. New metadata is
+// written with the given expiration time.
+func (r *Repo) AddDelegatedRoleWithExpires(delegator string, delegatedRole data.DelegatedRole, keys []*data.PublicKey, expires time.Time) error {
+	expires = expires.Round(time.Second)
+
+	t, err := r.targets(delegator)
+	if err != nil {
+		return fmt.Errorf("error getting delegator (%q) metadata: %w", delegator, err)
+	}
+
+	if t.Delegations == nil {
+		t.Delegations = &data.Delegations{}
+		t.Delegations.Keys = make(map[string]*data.PublicKey)
+	}
+
+	for _, keyID := range delegatedRole.KeyIDs {
+		for _, key := range keys {
+			if key.ContainsID(keyID) {
+				t.Delegations.Keys[keyID] = key
+				break
+			}
+		}
+	}
+
+	for _, r := range t.Delegations.Roles {
+		if r.Name == delegatedRole.Name {
+			return fmt.Errorf("role: %s is already delegated to by %s", delegatedRole.Name, r.Name)
+		}
+	}
+	t.Delegations.Roles = append(t.Delegations.Roles, delegatedRole)
+	t.Expires = expires
+
+	delegatorFile := delegator + ".json"
+	if !r.local.FileIsStaged(delegatorFile) {
+		t.Version++
+	}
+
+	err = r.setMeta(delegatorFile, t)
+	if err != nil {
+		return fmt.Errorf("error setting metadata for %q: %w", delegatorFile, err)
+	}
+
+	delegatee := delegatedRole.Name
+	dt, err := r.targets(delegatee)
+	if err != nil {
+		return fmt.Errorf("error getting delegatee (%q) metadata: %w", delegatee, err)
+	}
+	dt.Expires = expires
+
+	delegateeFile := delegatee + ".json"
+	if !r.local.FileIsStaged(delegateeFile) {
+		dt.Version++
+	}
+
+	err = r.setMeta(delegateeFile, dt)
+	if err != nil {
+		return fmt.Errorf("error setting metadata for %q: %w", delegateeFile, err)
+	}
+
+	return nil
+}
+
+// AddDelegatedRolesForPathHashBins is equivalent to
+// AddDelegatedRolesForPathHashBinsWithExpires, but with a default
+// expiration time.
+func (r *Repo) AddDelegatedRolesForPathHashBins(delegator string, bins *targets.HashBins, keys []*data.PublicKey, threshold int) error {
+	return r.AddDelegatedRolesForPathHashBinsWithExpires(delegator, bins, keys, threshold, data.DefaultExpires("targets"))
+}
+
+// AddDelegatedRolesForPathHashBinsWithExpires adds delegations to the
+// delegator role for the given hash bins configuration. New metadata is
+// written with the given expiration time.
+func (r *Repo) AddDelegatedRolesForPathHashBinsWithExpires(delegator string, bins *targets.HashBins, keys []*data.PublicKey, threshold int, expires time.Time) error {
+	keyIDs := []string{}
+	for _, key := range keys {
+		keyIDs = append(keyIDs, key.IDs()...)
+	}
+
+	n := bins.NumBins()
+	for i := uint64(0); i < n; i += 1 {
+		bin := bins.GetBin(i)
+		name := bin.RoleName()
+		err := r.AddDelegatedRoleWithExpires(delegator, data.DelegatedRole{
+			Name:             name,
+			KeyIDs:           sets.DeduplicateStrings(keyIDs),
+			PathHashPrefixes: bin.HashPrefixes(),
+			Threshold:        threshold,
+		}, keys, expires)
+		if err != nil {
+			return fmt.Errorf("error adding delegation from %v to %v: %w", delegator, name, err)
+		}
+	}
+
+	return nil
+}
+
+// ResetTargetsDelegation is equivalent to ResetTargetsDelegationsWithExpires
+// with a default expiry time.
+func (r *Repo) ResetTargetsDelegations(delegator string) error {
+	return r.ResetTargetsDelegationsWithExpires(delegator, data.DefaultExpires("targets"))
+}
+
+// ResetTargetsDelegationsWithExpires removes all targets delegations from the
+// given delegator role. New metadata is written with the given expiration
+// time.
+func (r *Repo) ResetTargetsDelegationsWithExpires(delegator string, expires time.Time) error {
+	t, err := r.targets(delegator)
+	if err != nil {
+		return fmt.Errorf("error getting delegator (%q) metadata: %w", delegator, err)
+	}
+
+	t.Delegations = &data.Delegations{}
+	t.Delegations.Keys = make(map[string]*data.PublicKey)
+
+	t.Expires = expires.Round(time.Second)
+
+	delegatorFile := delegator + ".json"
+	if !r.local.FileIsStaged(delegatorFile) {
+		t.Version++
+	}
+
+	err = r.setMeta(delegatorFile, t)
 	if err != nil {
-		return []byte{}, err
+		return fmt.Errorf("error setting metadata for %q: %w", delegatorFile, err)
 	}
 
+	return nil
+}
+
+func (r *Repo) jsonMarshal(v interface{}) ([]byte, error) {
 	if r.prefix == "" && r.indent == "" {
-		return b, nil
+		return json.Marshal(v)
 	}
+	return json.MarshalIndent(v, r.prefix, r.indent)
+}
+
+func (r *Repo) dbsForRole(role string) ([]*verify.DB, error) {
+	dbs := []*verify.DB{}
+
+	if roles.IsTopLevelRole(role) {
+		db, err := r.topLevelKeysDB()
+		if err != nil {
+			return nil, err
+		}
+		dbs = append(dbs, db)
+	} else {
+		ddbs, err := r.delegatorDBs(role)
+		if err != nil {
+			return nil, err
+		}
 
-	var out bytes.Buffer
-	if err := json.Indent(&out, b, r.prefix, r.indent); err != nil {
-		return []byte{}, err
+		dbs = append(dbs, ddbs...)
 	}
 
-	return out.Bytes(), nil
+	return dbs, nil
 }
 
-func (r *Repo) setTopLevelMeta(roleFilename string, meta interface{}) error {
-	keys, err := r.getSortedSigningKeys(strings.TrimSuffix(roleFilename, ".json"))
+func (r *Repo) signersForRole(role string) ([]keys.Signer, error) {
+	dbs, err := r.dbsForRole(role)
+	if err != nil {
+		return nil, err
+	}
+
+	signers := []keys.Signer{}
+	for _, db := range dbs {
+		ss, err := r.getSignersInDB(role, db)
+		if err != nil {
+			return nil, err
+		}
+
+		signers = append(signers, ss...)
+	}
+
+	return signers, nil
+}
+
+func (r *Repo) setMeta(roleFilename string, meta interface{}) error {
+	role := strings.TrimSuffix(roleFilename, ".json")
+
+	signers, err := r.signersForRole(role)
 	if err != nil {
 		return err
 	}
-	s, err := sign.Marshal(meta, keys...)
+
+	s, err := sign.Marshal(meta, signers...)
 	if err != nil {
 		return err
 	}
@@ -521,16 +736,13 @@ func (r *Repo) setTopLevelMeta(roleFilename string, meta interface{}) error {
 
 func (r *Repo) Sign(roleFilename string) error {
 	role := strings.TrimSuffix(roleFilename, ".json")
-	if !roles.IsTopLevelRole(role) {
-		return ErrInvalidRole{role, "only signing top-level metadata supported"}
-	}
 
 	s, err := r.SignedMeta(roleFilename)
 	if err != nil {
 		return err
 	}
 
-	keys, err := r.getSortedSigningKeys(role)
+	keys, err := r.signersForRole(role)
 	if err != nil {
 		return err
 	}
@@ -557,20 +769,28 @@ func (r *Repo) Sign(roleFilename string) error {
 // The name must be a valid metadata file name, like root.json.
 func (r *Repo) AddOrUpdateSignature(roleFilename string, signature data.Signature) error {
 	role := strings.TrimSuffix(roleFilename, ".json")
-	if !roles.IsTopLevelRole(role) {
-		return ErrInvalidRole{role, "only signing top-level metadata supported"}
-	}
 
 	// Check key ID is in valid for the role.
-	db, err := r.topLevelKeysDB()
+	dbs, err := r.dbsForRole(role)
 	if err != nil {
 		return err
 	}
-	roleData := db.GetRole(role)
-	if roleData == nil {
-		return ErrInvalidRole{role, "role missing from top-level keys"}
+
+	if len(dbs) == 0 {
+		return ErrInvalidRole{role, "no trusted keys for role"}
 	}
-	if !roleData.ValidKey(signature.KeyID) {
+
+	keyInDB := false
+	for _, db := range dbs {
+		roleData := db.GetRole(role)
+		if roleData == nil {
+			return ErrInvalidRole{role, "role is not in verifier DB"}
+		}
+		if roleData.ValidKey(signature.KeyID) {
+			keyInDB = true
+		}
+	}
+	if !keyInDB {
 		return verify.ErrInvalidKey
 	}
 
@@ -591,9 +811,11 @@ func (r *Repo) AddOrUpdateSignature(roleFilename string, signature data.Signatur
 
 	// Check signature on signed meta. Ignore threshold errors as this may not be fully
 	// signed.
-	if err := db.VerifySignatures(s, role); err != nil {
-		if _, ok := err.(verify.ErrRoleThreshold); !ok {
-			return err
+	for _, db := range dbs {
+		if err := db.VerifySignatures(s, role); err != nil {
+			if _, ok := err.(verify.ErrRoleThreshold); !ok {
+				return err
+			}
 		}
 	}
 
@@ -606,46 +828,45 @@ func (r *Repo) AddOrUpdateSignature(roleFilename string, signature data.Signatur
 	return r.local.SetMeta(roleFilename, b)
 }
 
-// getSortedSigningKeys returns available signing keys, sorted by key ID.
+// getSignersInDB returns available signing interfaces, sorted by key ID.
 //
 // Only keys contained in the keys db are returned (i.e. local keys which have
 // been revoked are omitted), except for the root role in which case all local
 // keys are returned (revoked root keys still need to sign new root metadata so
 // clients can verify the new root.json and update their keys db accordingly).
-func (r *Repo) getSortedSigningKeys(name string) ([]keys.Signer, error) {
-	signingKeys, err := r.local.GetSigners(name)
+func (r *Repo) getSignersInDB(roleName string, db *verify.DB) ([]keys.Signer, error) {
+	signers, err := r.local.GetSigners(roleName)
 	if err != nil {
 		return nil, err
 	}
-	if name == "root" {
-		sorted := make([]keys.Signer, len(signingKeys))
-		copy(sorted, signingKeys)
+
+	if roleName == "root" {
+		sorted := make([]keys.Signer, len(signers))
+		copy(sorted, signers)
 		sort.Sort(signer.ByIDs(sorted))
 		return sorted, nil
 	}
-	db, err := r.topLevelKeysDB()
-	if err != nil {
-		return nil, err
-	}
-	role := db.GetRole(name)
+
+	role := db.GetRole(roleName)
 	if role == nil {
 		return nil, nil
 	}
 	if len(role.KeyIDs) == 0 {
 		return nil, nil
 	}
-	keys := make([]keys.Signer, 0, len(role.KeyIDs))
-	for _, key := range signingKeys {
-		for _, id := range key.PublicData().IDs() {
+
+	signersInDB := []keys.Signer{}
+	for _, s := range signers {
+		for _, id := range s.PublicData().IDs() {
 			if _, ok := role.KeyIDs[id]; ok {
-				keys = append(keys, key)
+				signersInDB = append(signersInDB, s)
 			}
 		}
 	}
 
-	sort.Sort(signer.ByIDs(keys))
+	sort.Sort(signer.ByIDs(signersInDB))
 
-	return keys, nil
+	return signersInDB, nil
 }
 
 // Used to retrieve the signable portion of the metadata when using an external signing tool.
@@ -661,22 +882,141 @@ func (r *Repo) SignedMeta(roleFilename string) (*data.Signed, error) {
 	return s, nil
 }
 
+// delegatorDBs returns a list of key DBs for all incoming delegations.
+func (r *Repo) delegatorDBs(delegateeRole string) ([]*verify.DB, error) {
+	delegatorDBs := []*verify.DB{}
+	for metaName := range r.meta {
+		if roles.IsTopLevelManifest(metaName) && metaName != "targets.json" {
+			continue
+		}
+		roleName := strings.TrimSuffix(metaName, ".json")
+
+		t, err := r.targets(roleName)
+		if err != nil {
+			return nil, err
+		}
+
+		if t.Delegations == nil {
+			continue
+		}
+
+		delegatesToRole := false
+		for _, d := range t.Delegations.Roles {
+			if d.Name == delegateeRole {
+				delegatesToRole = true
+				break
+			}
+		}
+		if !delegatesToRole {
+			continue
+		}
+
+		db, err := verify.NewDBFromDelegations(t.Delegations)
+		if err != nil {
+			return nil, err
+		}
+
+		delegatorDBs = append(delegatorDBs, db)
+	}
+
+	return delegatorDBs, nil
+}
+
+// targetDelegationForPath finds the targets metadata for the role that should
+// sign the given path. The final delegation that led to the returned target
+// metadata is also returned.
+//
+// Since there may be multiple targets roles that are able to sign a specific
+// path, we must choose which roles's metadata to return. If preferredRole is
+// specified (non-empty string) and eligible to sign the given path by way of
+// some delegation chain, targets metadata for that role is returned. If
+// preferredRole is not specified (""), we return targets metadata for the
+// final role visited in the depth-first delegation traversal.
+func (r *Repo) targetDelegationForPath(path string, preferredRole string) (*data.Targets, *targets.Delegation, error) {
+	topLevelKeysDB, err := r.topLevelKeysDB()
+	if err != nil {
+		return nil, nil, err
+	}
+
+	iterator, err := targets.NewDelegationsIterator(path, topLevelKeysDB)
+	if err != nil {
+		return nil, nil, err
+	}
+	d, ok := iterator.Next()
+	if !ok {
+		return nil, nil, ErrNoDelegatedTarget{Path: path}
+	}
+
+	for i := 0; i < defaultMaxDelegations; i++ {
+		targetsMeta, err := r.targets(d.Delegatee.Name)
+		if err != nil {
+			return nil, nil, err
+		}
+
+		if preferredRole != "" && d.Delegatee.Name == preferredRole {
+			// The preferredRole is eligible to sign for the given path, and we've
+			// found its metadata. Return it.
+			return targetsMeta, &d, nil
+		}
+
+		if targetsMeta.Delegations != nil && len(targetsMeta.Delegations.Roles) > 0 {
+			db, err := verify.NewDBFromDelegations(targetsMeta.Delegations)
+			if err != nil {
+				return nil, nil, err
+			}
+
+			// Add delegations to the iterator that are eligible to sign for the
+			// given path (there may be none).
+			iterator.Add(targetsMeta.Delegations.Roles, d.Delegatee.Name, db)
+		}
+
+		next, ok := iterator.Next()
+		if !ok { // No more roles to traverse.
+			if preferredRole == "" {
+				// No preferredRole was given, so return metadata for the final role in the traversal.
+				return targetsMeta, &d, nil
+			} else {
+				// There are no more roles to traverse, so preferredRole is either an
+				// invalid role, or not eligible to sign the given path.
+				return nil, nil, ErrNoDelegatedTarget{Path: path}
+			}
+		}
+
+		d = next
+	}
+
+	return nil, nil, ErrNoDelegatedTarget{Path: path}
+}
+
 func (r *Repo) AddTarget(path string, custom json.RawMessage) error {
 	return r.AddTargets([]string{path}, custom)
 }
 
+func (r *Repo) AddTargetToPreferredRole(path string, custom json.RawMessage, preferredRole string) error {
+	return r.AddTargetsToPreferredRole([]string{path}, custom, preferredRole)
+}
+
 func (r *Repo) AddTargets(paths []string, custom json.RawMessage) error {
-	return r.AddTargetsWithExpires(paths, custom, data.DefaultExpires("targets"))
+	return r.AddTargetsToPreferredRole(paths, custom, "")
+}
+
+func (r *Repo) AddTargetsToPreferredRole(paths []string, custom json.RawMessage, preferredRole string) error {
+	return r.AddTargetsWithExpiresToPreferredRole(paths, custom, data.DefaultExpires("targets"), preferredRole)
 }
 
 func (r *Repo) AddTargetsWithDigest(digest string, digestAlg string, length int64, path string, custom json.RawMessage) error {
+	// TODO: Rename this to AddTargetWithDigest
+	// https://github.com/theupdateframework/go-tuf/issues/242
+
 	expires := data.DefaultExpires("targets")
+	path = util.NormalizeTarget(path)
 
-	// TODO: support delegated targets
-	t, err := r.topLevelTargets()
+	targetsMeta, delegation, err := r.targetDelegationForPath(path, "")
 	if err != nil {
 		return err
 	}
+	// This is the targets role that needs to sign the target file.
+	targetsRoleName := delegation.Delegatee.Name
 
 	meta := data.FileMeta{Length: length, Hashes: make(data.Hashes, 1)}
 	meta.Hashes[digestAlg], err = hex.DecodeString(digest)
@@ -688,13 +1028,28 @@ func (r *Repo) AddTargetsWithDigest(digest string, digestAlg string, length int6
 	// metadata
 	if len(custom) > 0 {
 		meta.Custom = &custom
-	} else if t, ok := t.Targets[path]; ok {
+	} else if t, ok := targetsMeta.Targets[path]; ok {
 		meta.Custom = t.Custom
 	}
 
-	t.Targets[path] = data.TargetFileMeta{FileMeta: meta}
+	// What does G2 mean? Copying and pasting this comment from elsewhere in this file.
+	// G2 -> we no longer desire any readers to ever observe non-prefix targets.
+	delete(targetsMeta.Targets, "/"+path)
+	targetsMeta.Targets[path] = data.TargetFileMeta{FileMeta: meta}
 
-	return r.writeTargetWithExpires(t, expires)
+	targetsMeta.Expires = expires.Round(time.Second)
+
+	manifestName := targetsRoleName + ".json"
+	if !r.local.FileIsStaged(manifestName) {
+		targetsMeta.Version++
+	}
+
+	err = r.setMeta(manifestName, targetsMeta)
+	if err != nil {
+		return fmt.Errorf("error setting metadata for %q: %w", manifestName, err)
+	}
+
+	return nil
 }
 
 func (r *Repo) AddTargetWithExpires(path string, custom json.RawMessage, expires time.Time) error {
@@ -702,57 +1057,98 @@ func (r *Repo) AddTargetWithExpires(path string, custom json.RawMessage, expires
 }
 
 func (r *Repo) AddTargetsWithExpires(paths []string, custom json.RawMessage, expires time.Time) error {
+	return r.AddTargetsWithExpiresToPreferredRole(paths, custom, expires, "")
+}
+
+func (r *Repo) AddTargetWithExpiresToPreferredRole(path string, custom json.RawMessage, expires time.Time, preferredRole string) error {
+	return r.AddTargetsWithExpiresToPreferredRole([]string{path}, custom, expires, preferredRole)
+}
+
+// AddTargetsWithExpiresToPreferredRole signs the staged targets at `paths`.
+//
+// If preferredRole is not the empty string, the target is added to the given
+// role's manifest if delegations allow it. If delegations do not allow the
+// preferredRole to sign the given path, an error is returned.
+func (r *Repo) AddTargetsWithExpiresToPreferredRole(paths []string, custom json.RawMessage, expires time.Time, preferredRole string) error {
 	if !validExpires(expires) {
 		return ErrInvalidExpires{expires}
 	}
 
-	t, err := r.topLevelTargets()
-	if err != nil {
-		return err
-	}
 	normalizedPaths := make([]string, len(paths))
 	for i, path := range paths {
 		normalizedPaths[i] = util.NormalizeTarget(path)
 	}
+
+	// As we iterate through staged targets files, we accumulate changes to their
+	// corresponding targets metadata.
+	updatedTargetsMeta := map[string]*data.Targets{}
+
 	if err := r.local.WalkStagedTargets(normalizedPaths, func(path string, target io.Reader) (err error) {
-		meta, err := util.GenerateTargetFileMeta(target, r.hashAlgorithms...)
+		originalMeta, delegation, err := r.targetDelegationForPath(path, preferredRole)
 		if err != nil {
 			return err
 		}
-		path = util.NormalizeTarget(path)
 
-		// if we have custom metadata, set it, otherwise maintain
+		// This is the targets role that needs to sign the target file.
+		targetsRoleName := delegation.Delegatee.Name
+
+		targetsMeta := originalMeta
+		if tm, ok := updatedTargetsMeta[targetsRoleName]; ok {
+			// Metadata in updatedTargetsMeta overrides staged/commited metadata.
+			targetsMeta = tm
+		}
+
+		fileMeta, err := util.GenerateTargetFileMeta(target, r.hashAlgorithms...)
+		if err != nil {
+			return err
+		}
+
+		// If we have custom metadata, set it, otherwise maintain
 		// existing metadata if present
 		if len(custom) > 0 {
-			meta.Custom = &custom
-		} else if t, ok := t.Targets[path]; ok {
-			meta.Custom = t.Custom
+			fileMeta.Custom = &custom
+		} else if tf, ok := targetsMeta.Targets[path]; ok {
+			fileMeta.Custom = tf.Custom
 		}
 
 		// G2 -> we no longer desire any readers to ever observe non-prefix targets.
-		delete(t.Targets, "/"+path)
-		t.Targets[path] = meta
+		delete(targetsMeta.Targets, "/"+path)
+		targetsMeta.Targets[path] = fileMeta
+
+		updatedTargetsMeta[targetsRoleName] = targetsMeta
+
 		return nil
 	}); err != nil {
 		return err
 	}
-	return r.writeTargetWithExpires(t, expires)
-}
 
-func (r *Repo) writeTargetWithExpires(t *data.Targets, expires time.Time) error {
-	t.Expires = expires.Round(time.Second)
-	if !r.local.FileIsStaged("targets.json") {
-		t.Version++
+	if len(updatedTargetsMeta) == 0 {
+		// This is potentially unexpected behavior kept for backwards compatibility.
+		// See https://github.com/theupdateframework/go-tuf/issues/243
+		t, err := r.topLevelTargets()
+		if err != nil {
+			return err
+		}
+
+		updatedTargetsMeta["targets"] = t
 	}
 
-	err := r.setTopLevelMeta("targets.json", t)
-	if err == nil && len(t.Targets) > 0 {
-		fmt.Println("Added/staged targets:")
-		for k := range t.Targets {
-			fmt.Println("*", k)
+	exp := expires.Round(time.Second)
+	for roleName, targetsMeta := range updatedTargetsMeta {
+		targetsMeta.Expires = exp
+
+		manifestName := roleName + ".json"
+		if !r.local.FileIsStaged(manifestName) {
+			targetsMeta.Version++
+		}
+
+		err := r.setMeta(manifestName, targetsMeta)
+		if err != nil {
+			return fmt.Errorf("error setting metadata for %q: %w", manifestName, err)
 		}
 	}
-	return err
+
+	return nil
 }
 
 func (r *Repo) RemoveTarget(path string) error {
@@ -773,7 +1169,23 @@ func (r *Repo) RemoveTargetsWithExpires(paths []string, expires time.Time) error
 		return ErrInvalidExpires{expires}
 	}
 
-	t, err := r.topLevelTargets()
+	for metaName := range r.meta {
+		if metaName != "targets.json" && !roles.IsDelegatedTargetsManifest(metaName) {
+			continue
+		}
+
+		err := r.removeTargetsWithExpiresFromMeta(metaName, paths, expires)
+		if err != nil {
+			return fmt.Errorf("could not remove %v from %v: %w", paths, metaName, err)
+		}
+	}
+
+	return nil
+}
+
+func (r *Repo) removeTargetsWithExpiresFromMeta(metaName string, paths []string, expires time.Time) error {
+	roleName := strings.TrimSuffix(metaName, ".json")
+	t, err := r.targets(roleName)
 	if err != nil {
 		return err
 	}
@@ -788,7 +1200,7 @@ func (r *Repo) RemoveTargetsWithExpires(paths []string, expires time.Time) error
 		for _, path := range paths {
 			path = util.NormalizeTarget(path)
 			if _, ok := t.Targets[path]; !ok {
-				fmt.Println("The following target is not present:", path)
+				fmt.Printf("[%v] The following target is not present: %v\n", metaName, path)
 				continue
 			}
 			removed = true
@@ -802,23 +1214,23 @@ func (r *Repo) RemoveTargetsWithExpires(paths []string, expires time.Time) error
 		}
 	}
 	t.Expires = expires.Round(time.Second)
-	if !r.local.FileIsStaged("targets.json") {
+	if !r.local.FileIsStaged(metaName) {
 		t.Version++
 	}
 
-	err = r.setTopLevelMeta("targets.json", t)
+	err = r.setMeta(metaName, t)
 	if err == nil {
-		fmt.Println("Removed targets:")
+		fmt.Printf("[%v] Removed targets:\n", metaName)
 		for _, v := range removed_targets {
 			fmt.Println("*", v)
 		}
 		if len(t.Targets) != 0 {
-			fmt.Println("Added/staged targets:")
+			fmt.Printf("[%v] Added/staged targets:\n", metaName)
 			for k := range t.Targets {
 				fmt.Println("*", k)
 			}
 		} else {
-			fmt.Println("There are no added/staged targets")
+			fmt.Printf("[%v] There are no added/staged targets\n", metaName)
 		}
 	}
 	return err
@@ -829,7 +1241,16 @@ func (r *Repo) Snapshot() error {
 }
 
 func (r *Repo) snapshotMetadata() []string {
-	return []string{"targets.json"}
+	ret := []string{"targets.json"}
+
+	for name := range r.meta {
+		if !roles.IsVersionedManifest(name) &&
+			roles.IsDelegatedTargetsManifest(name) {
+			ret = append(ret, name)
+		}
+	}
+
+	return ret
 }
 
 func (r *Repo) SnapshotWithExpires(expires time.Time) error {
@@ -841,13 +1262,9 @@ func (r *Repo) SnapshotWithExpires(expires time.Time) error {
 	if err != nil {
 		return err
 	}
-	db, err := r.topLevelKeysDB()
-	if err != nil {
-		return err
-	}
 
 	for _, metaName := range r.snapshotMetadata() {
-		if err := r.verifySignature(metaName, db); err != nil {
+		if err := r.verifySignatures(metaName); err != nil {
 			return err
 		}
 		var err error
@@ -860,7 +1277,7 @@ func (r *Repo) SnapshotWithExpires(expires time.Time) error {
 	if !r.local.FileIsStaged("snapshot.json") {
 		snapshot.Version++
 	}
-	err = r.setTopLevelMeta("snapshot.json", snapshot)
+	err = r.setMeta("snapshot.json", snapshot)
 	if err == nil {
 		fmt.Println("Staged snapshot.json metadata with expiration date:", snapshot.Expires)
 	}
@@ -876,11 +1293,7 @@ func (r *Repo) TimestampWithExpires(expires time.Time) error {
 		return ErrInvalidExpires{expires}
 	}
 
-	db, err := r.topLevelKeysDB()
-	if err != nil {
-		return err
-	}
-	if err := r.verifySignature("snapshot.json", db); err != nil {
+	if err := r.verifySignatures("snapshot.json"); err != nil {
 		return err
 	}
 	timestamp, err := r.timestamp()
@@ -896,7 +1309,7 @@ func (r *Repo) TimestampWithExpires(expires time.Time) error {
 		timestamp.Version++
 	}
 
-	err = r.setTopLevelMeta("timestamp.json", timestamp)
+	err = r.setMeta("timestamp.json", timestamp)
 	if err == nil {
 		fmt.Println("Staged timestamp.json metadata with expiration date:", timestamp.Expires)
 	}
@@ -904,48 +1317,95 @@ func (r *Repo) TimestampWithExpires(expires time.Time) error {
 }
 
 func (r *Repo) fileVersions() (map[string]int64, error) {
-	root, err := r.root()
-	if err != nil {
-		return nil, err
-	}
-	targets, err := r.topLevelTargets()
-	if err != nil {
-		return nil, err
-	}
-	snapshot, err := r.snapshot()
-	if err != nil {
-		return nil, err
-	}
 	versions := make(map[string]int64)
-	versions["root.json"] = root.Version
-	versions["targets.json"] = targets.Version
-	versions["snapshot.json"] = snapshot.Version
+
+	for fileName := range r.meta {
+		if roles.IsVersionedManifest(fileName) {
+			continue
+		}
+
+		roleName := strings.TrimSuffix(fileName, ".json")
+
+		var version int64
+
+		switch roleName {
+		case "root":
+			root, err := r.root()
+			if err != nil {
+				return nil, err
+			}
+			version = root.Version
+		case "snapshot":
+			snapshot, err := r.snapshot()
+			if err != nil {
+				return nil, err
+			}
+			version = snapshot.Version
+		case "timestamp":
+			continue
+		default:
+			// Targets or delegated targets manifest.
+			targets, err := r.targets(roleName)
+			if err != nil {
+				return nil, err
+			}
+
+			version = targets.Version
+		}
+
+		versions[fileName] = version
+	}
+
 	return versions, nil
 }
 
 func (r *Repo) fileHashes() (map[string]data.Hashes, error) {
 	hashes := make(map[string]data.Hashes)
-	timestamp, err := r.timestamp()
-	if err != nil {
-		return nil, err
-	}
-	snapshot, err := r.snapshot()
-	if err != nil {
-		return nil, err
-	}
-	if m, ok := snapshot.Meta["targets.json"]; ok {
-		hashes["targets.json"] = m.Hashes
-	}
-	if m, ok := timestamp.Meta["snapshot.json"]; ok {
-		hashes["snapshot.json"] = m.Hashes
-	}
-	t, err := r.topLevelTargets()
-	if err != nil {
-		return nil, err
-	}
-	for name, meta := range t.Targets {
-		hashes[path.Join("targets", name)] = meta.Hashes
+
+	for fileName := range r.meta {
+		if roles.IsVersionedManifest(fileName) {
+			continue
+		}
+
+		roleName := strings.TrimSuffix(fileName, ".json")
+
+		switch roleName {
+		case "snapshot":
+			timestamp, err := r.timestamp()
+			if err != nil {
+				return nil, err
+			}
+
+			if m, ok := timestamp.Meta[fileName]; ok {
+				hashes[fileName] = m.Hashes
+			}
+		case "timestamp":
+			continue
+		default:
+			snapshot, err := r.snapshot()
+			if err != nil {
+				return nil, err
+			}
+			if m, ok := snapshot.Meta[fileName]; ok {
+				hashes[fileName] = m.Hashes
+			}
+
+			if roleName != "root" {
+				// Scalability issue: Commit/fileHashes loads all targets metadata into memory
+				// https://github.com/theupdateframework/go-tuf/issues/245
+				t, err := r.targets(roleName)
+				if err != nil {
+					return nil, err
+				}
+				for name, m := range t.Targets {
+					hashes[path.Join("targets", name)] = m.Hashes
+				}
+			}
+
+		}
+
 	}
+
 	return hashes, nil
 }
 
@@ -1000,13 +1460,8 @@ func (r *Repo) Commit() error {
 		return fmt.Errorf("tuf: invalid snapshot.json in timestamp.json: %s", err)
 	}
 
-	// verify all signatures are correct
-	db, err := r.topLevelKeysDB()
-	if err != nil {
-		return err
-	}
 	for _, name := range topLevelMetadata {
-		if err := r.verifySignature(name, db); err != nil {
+		if err := r.verifySignatures(name); err != nil {
 			return err
 		}
 	}
@@ -1035,15 +1490,25 @@ func (r *Repo) Clean() error {
 	return err
 }
 
-func (r *Repo) verifySignature(roleFilename string, db *verify.DB) error {
-	s, err := r.SignedMeta(roleFilename)
+func (r *Repo) verifySignatures(metaFilename string) error {
+	s, err := r.SignedMeta(metaFilename)
 	if err != nil {
 		return err
 	}
-	role := strings.TrimSuffix(roleFilename, ".json")
-	if err := db.Verify(s, role, 0); err != nil {
-		return ErrInsufficientSignatures{roleFilename, err}
+
+	role := strings.TrimSuffix(metaFilename, ".json")
+
+	dbs, err := r.dbsForRole(role)
+	if err != nil {
+		return err
 	}
+
+	for _, db := range dbs {
+		if err := db.Verify(s, role, 0); err != nil {
+			return ErrInsufficientSignatures{metaFilename, err}
+		}
+	}
+
 	return nil
 }
 
diff --git a/sign/sign.go b/sign/sign.go
index 06886b5..6b15b6b 100644
--- a/sign/sign.go
+++ b/sign/sign.go
@@ -1,6 +1,8 @@
 package sign
 
 import (
+	"encoding/json"
+
 	"github.com/secure-systems-lab/go-securesystemslib/cjson"
 	"github.com/theupdateframework/go-tuf/data"
 	"github.com/theupdateframework/go-tuf/pkg/keys"
@@ -22,7 +24,12 @@ func Sign(s *data.Signed, k keys.Signer) error {
 		}
 	}
 
-	sig, err := k.SignMessage(s.Signed)
+	canonical, err := cjson.EncodeCanonical(s.Signed)
+	if err != nil {
+		return err
+	}
+
+	sig, err := k.SignMessage(canonical)
 	if err != nil {
 		return err
 	}
@@ -39,7 +46,7 @@ func Sign(s *data.Signed, k keys.Signer) error {
 }
 
 func Marshal(v interface{}, keys ...keys.Signer) (*data.Signed, error) {
-	b, err := cjson.EncodeCanonical(v)
+	b, err := json.Marshal(v)
 	if err != nil {
 		return nil, err
 	}
diff --git a/verify/db.go b/verify/db.go
index a14a514..657c2c5 100644
--- a/verify/db.go
+++ b/verify/db.go
@@ -40,7 +40,7 @@ func NewDBFromDelegations(d *data.Delegations) (*DB, error) {
 			return nil, ErrInvalidDelegatedRole
 		}
 		role := &data.Role{Threshold: r.Threshold, KeyIDs: r.KeyIDs}
-		if err := db.addRole(r.Name, role); err != nil {
+		if err := db.AddRole(r.Name, role); err != nil {
 			return nil, err
 		}
 	}
@@ -65,13 +65,6 @@ func (db *DB) AddKey(id string, k *data.PublicKey) error {
 }
 
 func (db *DB) AddRole(name string, r *data.Role) error {
-	if !roles.IsTopLevelRole(name) {
-		return ErrInvalidRole
-	}
-	return db.addRole(name, r)
-}
-
-func (db *DB) addRole(name string, r *data.Role) error {
 	if r.Threshold < 1 {
 		return ErrInvalidThreshold
 	}


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 033fd6a..d2599f5 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -8,7 +8,7 @@ jobs:
     outputs:
       matrix: ${{ steps.versions.outputs.matrix }}
     steps:
-      - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
+      - uses: actions/checkout@v3
       - uses: arnested/go-version-action@d44f8fbecf1ac5ea61d81603e99dfec9833f592f
         id: versions
         env:
@@ -23,7 +23,7 @@ jobs:
     needs: get-go-versions
     steps:
       - name: Checkout code
-        uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
+        uses: actions/checkout@v3
 
       - name: Setup - Go ${{ matrix.go-version }}
         uses: actions/setup-go@f6164bd8c8acb4a71fb2791a8b6c4024ff038dab
@@ -61,7 +61,7 @@ jobs:
     needs: get-go-versions
     steps:
       - uses: actions/setup-go@f6164bd8c8acb4a71fb2791a8b6c4024ff038dab
-      - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
+      - uses: actions/checkout@v3
       - name: golangci-lint
         uses: golangci/golangci-lint-action@5c56cd6c9dc07901af25baab6f2b0d9f3b7c3018
         with:
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/0/repository/1.root.json b/client/testdata/go-tuf/consistent-snapshot-false/0/repository/1.root.json
index f31da23..a9ac50a 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/0/repository/1.root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/0/repository/1.root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
-			"sig": "afab8b34f93c99e200505cc6f0d6a9c4e757a7229f96bd31ab618f8bc4c3abe491b372bfec9d231136de46c1e183df194d372360ee9d32652f8c04d7574e2608"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": false,
+		"spec_version": "1.0",
+		"version": 1,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "62f71f99c788f16bcdc8bb252455e3a690350e4ddea5a6aab1f9a3aaabcf369a"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "bca152214dbfd3e7a1b7a7b3e2cc179fb00520fd7212c8a60ba99f14dfc0e1ca"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 1
-	}
+		"consistent_snapshot": false
+	},
+	"signatures": [
+		{
+			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
+			"sig": "afab8b34f93c99e200505cc6f0d6a9c4e757a7229f96bd31ab618f8bc4c3abe491b372bfec9d231136de46c1e183df194d372360ee9d32652f8c04d7574e2608"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/0/repository/root.json b/client/testdata/go-tuf/consistent-snapshot-false/0/repository/root.json
index f31da23..a9ac50a 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/0/repository/root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/0/repository/root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
-			"sig": "afab8b34f93c99e200505cc6f0d6a9c4e757a7229f96bd31ab618f8bc4c3abe491b372bfec9d231136de46c1e183df194d372360ee9d32652f8c04d7574e2608"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": false,
+		"spec_version": "1.0",
+		"version": 1,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "62f71f99c788f16bcdc8bb252455e3a690350e4ddea5a6aab1f9a3aaabcf369a"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "bca152214dbfd3e7a1b7a7b3e2cc179fb00520fd7212c8a60ba99f14dfc0e1ca"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 1
-	}
+		"consistent_snapshot": false
+	},
+	"signatures": [
+		{
+			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
+			"sig": "afab8b34f93c99e200505cc6f0d6a9c4e757a7229f96bd31ab618f8bc4c3abe491b372bfec9d231136de46c1e183df194d372360ee9d32652f8c04d7574e2608"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/0/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-false/0/repository/snapshot.json
index 58cecb2..5d2428f 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/0/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/0/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
-			"sig": "3f24a81d61a8f1fbe2bf310a9d8263c7b3a5fc87524b92e00a100ce6d8e0f742c0ef05b017234b0d08c9cf4da4591deb65e6f76340afad722b3db1b25d2e0203"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 1,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 588,
 				"hashes": {
-					"sha512": "e0dd9a3833d117cd7bb6fdaae8923d5bda0661cb242be067813bfec3114d83943230b8bb7fcbf093a15d5840f1ecd969f44d3df13e2045d3fb7d22903fbc1bf5"
+					"sha512": "2532c645262d3a15db2afc561d9ae75db96c3b42abe8bd994c173e45ea70177bc1b080e211d92b6f244d267dcb0a0bc2fbcd1c2b008881c19f950c5e8c0035ec"
 				},
-				"length": 588,
 				"version": 1
 			}
-		},
-		"spec_version": "1.0",
-		"version": 1
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
+			"sig": "6efc0efbc7a3b849a58e9cb394af10fe6d199d2ead18e6931932c85f44269d5d73e8f18808d0d9b66fbfd9926b0bda9d2d26a7508a960758c0b84eb8aa31ac0b"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/0/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-false/0/repository/targets.json
index 5bb513f..6a82200 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/0/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/0/repository/targets.json
@@ -1,22 +1,22 @@
 {
-	"signatures": [
-		{
-			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
-			"sig": "4d5c3a5da43f3792d077c1128fa28585982ff2957fae59be02a831fc920d0b91cbeaa99fd6c15066ec4da8bf12f993440a90d1624fd7b0a68070e5d60ed2500f"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 1,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 1
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
+			"sig": "4d5c3a5da43f3792d077c1128fa28585982ff2957fae59be02a831fc920d0b91cbeaa99fd6c15066ec4da8bf12f993440a90d1624fd7b0a68070e5d60ed2500f"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/0/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-false/0/repository/timestamp.json
index 32382a3..92d160d 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/0/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/0/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
-			"sig": "cc163b290f68c6d41fbc7ca01a30416a43a5ee7652d2f99aff3c6ef01e5c2fa9d5f2caf0e745abeee3baa277ddfe43ac636149963cf085686345addc9e000301"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 1,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 617,
 				"hashes": {
-					"sha512": "973d23a7e47e1003cd4f8c0e431b080171408e488084fe736b664433d9be76e1f1048ea76607c1f485f1dcb23ce2b4980257431c39cee0fddcc53559997cd565"
+					"sha512": "6fd318e2cc3bca35d2f597e504c095137263ffe3e72f5e5c64e6c7860bea1207448c8994066ffc1cf20898a9d1586cdf09be4e3ea06f69593ed5c7d772f8dfd1"
 				},
-				"length": 617,
 				"version": 1
 			}
-		},
-		"spec_version": "1.0",
-		"version": 1
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
+			"sig": "943b219ab6c651793da08d8cf38c7d25fb959c75161b5b86562983841433f9f38c237bb87cf6ecfbb3cb7c78113a3ed2651ee57d3515e7edfc3bebbf349f2809"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/1/repository/2.root.json b/client/testdata/go-tuf/consistent-snapshot-false/1/repository/2.root.json
index 928f4f8..38d2617 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/1/repository/2.root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/1/repository/2.root.json
@@ -1,62 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "20e91b55c995989b270091b714347b15169285cb636ef05d68d49ed7b7a96ebfda13898e0d9ef928c382873b9dba90dca492dbf705d56a4b293adaaed574340f"
-		},
-		{
-			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
-			"sig": "65f63745aa8bd39132f827c427ea6d87f620ec805d9f376b6a8400dc3db7eb964e5423d31ed08867916d039661a70d6bf255bca552248021a4e78b5d357c2b0f"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": false,
+		"spec_version": "1.0",
+		"version": 2,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "62f71f99c788f16bcdc8bb252455e3a690350e4ddea5a6aab1f9a3aaabcf369a"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -85,7 +76,16 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 2
-	}
+		"consistent_snapshot": false
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "20e91b55c995989b270091b714347b15169285cb636ef05d68d49ed7b7a96ebfda13898e0d9ef928c382873b9dba90dca492dbf705d56a4b293adaaed574340f"
+		},
+		{
+			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
+			"sig": "65f63745aa8bd39132f827c427ea6d87f620ec805d9f376b6a8400dc3db7eb964e5423d31ed08867916d039661a70d6bf255bca552248021a4e78b5d357c2b0f"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/1/repository/root.json b/client/testdata/go-tuf/consistent-snapshot-false/1/repository/root.json
index 928f4f8..38d2617 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/1/repository/root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/1/repository/root.json
@@ -1,62 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "20e91b55c995989b270091b714347b15169285cb636ef05d68d49ed7b7a96ebfda13898e0d9ef928c382873b9dba90dca492dbf705d56a4b293adaaed574340f"
-		},
-		{
-			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
-			"sig": "65f63745aa8bd39132f827c427ea6d87f620ec805d9f376b6a8400dc3db7eb964e5423d31ed08867916d039661a70d6bf255bca552248021a4e78b5d357c2b0f"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": false,
+		"spec_version": "1.0",
+		"version": 2,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "62f71f99c788f16bcdc8bb252455e3a690350e4ddea5a6aab1f9a3aaabcf369a"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -85,7 +76,16 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 2
-	}
+		"consistent_snapshot": false
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "20e91b55c995989b270091b714347b15169285cb636ef05d68d49ed7b7a96ebfda13898e0d9ef928c382873b9dba90dca492dbf705d56a4b293adaaed574340f"
+		},
+		{
+			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
+			"sig": "65f63745aa8bd39132f827c427ea6d87f620ec805d9f376b6a8400dc3db7eb964e5423d31ed08867916d039661a70d6bf255bca552248021a4e78b5d357c2b0f"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/1/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-false/1/repository/snapshot.json
index c8e5b3c..aed7835 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/1/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/1/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
-			"sig": "bded36f9992b8eb9444a276b397db2ce5f06a8be1273d7f84391b2a098778522a1c49185b2fc858aa99bc69fe820f2444bc8e5077f447ddcf42515c3a7026e0a"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 2,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 789,
 				"hashes": {
-					"sha512": "8672c435a53519972738fada6ed3b7fa37b3ea42b4fa1e436b774e697a8d696d9efbeb6c590a6e16dec0a5e7f789da82ea59a68fae63f343340d1549a075ab1b"
+					"sha512": "7a919ed2a5fb7cf80252c9307ac4d27bc2ab54f9bb803389977dcc3d09ae7dff533639c1b19a810d2b212a5c5e904e0f73ab01324ba79dffbb9f7488204caf2a"
 				},
-				"length": 789,
 				"version": 2
 			}
-		},
-		"spec_version": "1.0",
-		"version": 2
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
+			"sig": "9a3734441c38daa3275ba60a2178b8dfe5f98296f408bf434144b4bd4f68af73b7f6860e6f2e638b93144ac5bebe361642bbff66a1195596bb8c841429b34508"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/1/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-false/1/repository/targets.json
index be81713..0ae4c79 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/1/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/1/repository/targets.json
@@ -1,28 +1,28 @@
 {
-	"signatures": [
-		{
-			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
-			"sig": "81bcf5921834a20b8b0946815ad4316f43ffce20b3793e6653dc5fd4b98f1c6318ce2243948574e82414a102717a6f2d731250b3191c54abc8391fd867503e0b"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 2,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 2
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
+			"sig": "81bcf5921834a20b8b0946815ad4316f43ffce20b3793e6653dc5fd4b98f1c6318ce2243948574e82414a102717a6f2d731250b3191c54abc8391fd867503e0b"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/1/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-false/1/repository/timestamp.json
index 42b04d4..ab60e90 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/1/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/1/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
-			"sig": "8ab93c7453677374d1483c495b49d80128b589ca80c1f3e7806bb3c40bd8be793c6df492ce68b2bcf5d50af73fdf7694b0484093b31577720898d6882ae97d0f"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 2,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 617,
 				"hashes": {
-					"sha512": "957e34523e34c2316a9fd02744162834382101796efca153e35028eb1e3fe970427d4e60e375300d1ac92e1c0a8ec74a1b5575a29d337b3454083a76cb922959"
+					"sha512": "d7204efe9ded4f18d679d75054f43b02b20d74189ea81ad90a67399a8884a810e380a4d343e284c4b6fde506e22a464038871d06950166548a84a76344e2bf3a"
 				},
-				"length": 617,
 				"version": 2
 			}
-		},
-		"spec_version": "1.0",
-		"version": 2
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
+			"sig": "85c5afdd9dd3777d2cb31721519ab2942edffc9e1282b65b2cede505a469051ac5e86388461db49f948a5998b132dddb5ce0156d21622a6d2201fb93322de20f"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/2/repository/3.root.json b/client/testdata/go-tuf/consistent-snapshot-false/2/repository/3.root.json
index 0dec040..fab2f0a 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/2/repository/3.root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/2/repository/3.root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "cfe8b0919d1707ca6c23501909b77c8b94d1ede2b85a3081ab7146244cc6fe436b06ad58163919276f2e37ddbcc13a0dde4851301053dcea2a9bcabc5e1cd004"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": false,
+		"spec_version": "1.0",
+		"version": 3,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 3
-	}
+		"consistent_snapshot": false
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "cfe8b0919d1707ca6c23501909b77c8b94d1ede2b85a3081ab7146244cc6fe436b06ad58163919276f2e37ddbcc13a0dde4851301053dcea2a9bcabc5e1cd004"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/2/repository/root.json b/client/testdata/go-tuf/consistent-snapshot-false/2/repository/root.json
index 0dec040..fab2f0a 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/2/repository/root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/2/repository/root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "cfe8b0919d1707ca6c23501909b77c8b94d1ede2b85a3081ab7146244cc6fe436b06ad58163919276f2e37ddbcc13a0dde4851301053dcea2a9bcabc5e1cd004"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": false,
+		"spec_version": "1.0",
+		"version": 3,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 3
-	}
+		"consistent_snapshot": false
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "cfe8b0919d1707ca6c23501909b77c8b94d1ede2b85a3081ab7146244cc6fe436b06ad58163919276f2e37ddbcc13a0dde4851301053dcea2a9bcabc5e1cd004"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/2/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-false/2/repository/snapshot.json
index 772b23e..ded8ac9 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/2/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/2/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
-			"sig": "94a60aaddf390953b997b783bab689a2cbaf66610b4dee5645ef858480f709b61afefc5eb21c6131aa5d3e2248eccebe77a7b4a8462f6f8f7964680085053903"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 3,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 990,
 				"hashes": {
-					"sha512": "b103f5cd1d68e0b5f7b96af03a27cf971460977976cff0b1d1371dcce6d45ef78e183fa26bf886f3864e84b8ddbbfc1bab7bd0e2be180ad82ed26f22a8e9b68b"
+					"sha512": "987022c23793b3d234d422c3ed4525f8c3771887db610fb2e7d6b455d27ad8b1b4a957a699d519c03754fe4feeb387ec84c95e1edac1d4e9b186bfbdff76ad10"
 				},
-				"length": 990,
 				"version": 3
 			}
-		},
-		"spec_version": "1.0",
-		"version": 3
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
+			"sig": "31896c9165a37aa54cf1c4d5f936035e092b1cf4c233ef35cd12c987aaa02de7ec99f26c198984fe0dcc21765d096b25cd67e7ca058613b2b2abef3193dd880d"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/2/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-false/2/repository/targets.json
index ad58a9d..b22a1d7 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/2/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/2/repository/targets.json
@@ -1,34 +1,34 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "09593c7b47f4dbf1e8ac949fa010279ffbbd36070a54a89b689378441e8111602d4236fa2962063778c82027d4746a8973ba8fea86e9c105190da9fa362d8b0c"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 3,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 3
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "09593c7b47f4dbf1e8ac949fa010279ffbbd36070a54a89b689378441e8111602d4236fa2962063778c82027d4746a8973ba8fea86e9c105190da9fa362d8b0c"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/2/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-false/2/repository/timestamp.json
index d5a05d7..4856974 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/2/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/2/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
-			"sig": "e431037f03bb3e323aa6d9f97533883a0d111698a17cd7eb7843961fa4b15a12a98a8a6cac377df934a9303d3765cc5314f59a160ffe11a32e76c18c27b0180f"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 3,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 617,
 				"hashes": {
-					"sha512": "49d07f15210a34a0b2bf51e2d349b243bba68800796a6f7031adaa14a86da0f3aa96098c46c6f55330fb71a424a6658cdf09683287f72f9082302e9be3aec1ef"
+					"sha512": "70d2f64bc810a0ae1c827c28eed47304c3a9c57402447d129aa3ac851d809a48bd0421aaa99e9e49055984e77f221510415cf27aca8f30f4db1767d6b7bd6024"
 				},
-				"length": 617,
 				"version": 3
 			}
-		},
-		"spec_version": "1.0",
-		"version": 3
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
+			"sig": "22367ebcf7c5265260b288e9fec6110257b8c8745af25f2b14c5d347ddab94f46893926bdd37c58d142089419708e446c5e3c1af5c47c51187fe69ca95038605"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/3/repository/4.root.json b/client/testdata/go-tuf/consistent-snapshot-false/3/repository/4.root.json
index a54c854..8f1b843 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/3/repository/4.root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/3/repository/4.root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "3004c4b60645c6cca18e33835837a1639eead05355aa549f1d1304a22304e7058a50fb6188fc3617a47248eb7481de7a625f036cc69b53daf04a103b12768401"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": false,
+		"spec_version": "1.0",
+		"version": 4,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "722dbc861813bb5b568524d62083e875c08e66fed1694d9161d253fa163dd86f"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 4
-	}
+		"consistent_snapshot": false
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "3004c4b60645c6cca18e33835837a1639eead05355aa549f1d1304a22304e7058a50fb6188fc3617a47248eb7481de7a625f036cc69b53daf04a103b12768401"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/3/repository/root.json b/client/testdata/go-tuf/consistent-snapshot-false/3/repository/root.json
index a54c854..8f1b843 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/3/repository/root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/3/repository/root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "3004c4b60645c6cca18e33835837a1639eead05355aa549f1d1304a22304e7058a50fb6188fc3617a47248eb7481de7a625f036cc69b53daf04a103b12768401"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": false,
+		"spec_version": "1.0",
+		"version": 4,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "722dbc861813bb5b568524d62083e875c08e66fed1694d9161d253fa163dd86f"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 4
-	}
+		"consistent_snapshot": false
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "3004c4b60645c6cca18e33835837a1639eead05355aa549f1d1304a22304e7058a50fb6188fc3617a47248eb7481de7a625f036cc69b53daf04a103b12768401"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/3/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-false/3/repository/snapshot.json
index 8634000..41e4ac6 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/3/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/3/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
-			"sig": "bb6acd05cd4328a69a227ec24f3f241e3b692dfa04301b3ec682c808f143c94bed361ac5215800189f1b415a05ee1bf8534d452dab8548abe514582b91d0f308"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 4,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 1191,
 				"hashes": {
-					"sha512": "75cc15d5a7c20656e37ece0a339434922fb489cf79f8ddf6a11d8c2a797ba1c7c51da0efaf335b31f9185c1eb9a5bbd074e16d412983a104e3bd33877eeb54c3"
+					"sha512": "2bf10fb9469cb5f44ccae3c8dac2f70c19e7c58479f74f21aca7a424774ed7ef43295fff3c05f7cfe457b5832366b64e0550874775e277d7233c060e9f94e140"
 				},
-				"length": 1191,
 				"version": 4
 			}
-		},
-		"spec_version": "1.0",
-		"version": 4
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
+			"sig": "c5efdc1b461ae319c991fd1840771d94dfc8a3e655ac233901a27959e9f2c3e7ab61b83e3d674caf9e2a6043e776d7c32a2c36dbf0922f7f08059d08fc26720a"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/3/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-false/3/repository/targets.json
index 88bb26e..8265b26 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/3/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/3/repository/targets.json
@@ -1,40 +1,40 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "7bfe0a63ee324034807b5341336d9d2d64e9ef3936086577b5bbcc6d021b4656bd6bf14d817bbb3908e4dcb05391d1b4031b527c14d942c2d1e38275d5ff1308"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 4,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			},
 			"3": {
+				"length": 1,
 				"hashes": {
 					"sha512": "3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 4
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "7bfe0a63ee324034807b5341336d9d2d64e9ef3936086577b5bbcc6d021b4656bd6bf14d817bbb3908e4dcb05391d1b4031b527c14d942c2d1e38275d5ff1308"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/3/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-false/3/repository/timestamp.json
index 0b5d5f7..c87022e 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/3/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/3/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
-			"sig": "40e97ae18e413a3b44f2f1fb19c0ab57303fb39e950a38954a845f4ba1185bae2314e20c1dc5f157f60106c50e546e1d3469fb0b4cf6675810798f84f22cd001"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 4,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 618,
 				"hashes": {
-					"sha512": "e55cb3fd889a759eaad70713f44d226a3b9b55b0e934fb6a1588832661c553d7f1e0cd6a2dfffeccabb5312dc9cf11ea88f34afbabd6fb715742ba60eb62756c"
+					"sha512": "4ddee1c0c54af1a3dc54897af33c2457525963059c29583e6df65b9b238732070bd8eb470201154f2d2fa5f8bdf37e01a86e6a53c2bcfe0ff302571458c1898d"
 				},
-				"length": 618,
 				"version": 4
 			}
-		},
-		"spec_version": "1.0",
-		"version": 4
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
+			"sig": "585cdcc87c23711642449d469df8bedb53a67b65ac75c303d13b7022c8c34c1db70c926e009c2438639af3be1d613f7ce4c7e28020865ad5ad93a5b085a76005"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/4/repository/5.root.json b/client/testdata/go-tuf/consistent-snapshot-false/4/repository/5.root.json
index eafaf05..b411336 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/4/repository/5.root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/4/repository/5.root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "bd2edde6ba4f5cb3a0cc28dca272e2fc0be691575082479f86b82cea4e541a686a0c132c3a7eca231a5782e52e629df92f8f3f89a5b1f57e8b5368986bddfa0e"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": false,
+		"spec_version": "1.0",
+		"version": 5,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "3ab34b0c2d4eadccaa0f0cf22ced07b552394063a9de2806993d022360dffc76"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "722dbc861813bb5b568524d62083e875c08e66fed1694d9161d253fa163dd86f"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 5
-	}
+		"consistent_snapshot": false
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "bd2edde6ba4f5cb3a0cc28dca272e2fc0be691575082479f86b82cea4e541a686a0c132c3a7eca231a5782e52e629df92f8f3f89a5b1f57e8b5368986bddfa0e"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/4/repository/root.json b/client/testdata/go-tuf/consistent-snapshot-false/4/repository/root.json
index eafaf05..b411336 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/4/repository/root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/4/repository/root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "bd2edde6ba4f5cb3a0cc28dca272e2fc0be691575082479f86b82cea4e541a686a0c132c3a7eca231a5782e52e629df92f8f3f89a5b1f57e8b5368986bddfa0e"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": false,
+		"spec_version": "1.0",
+		"version": 5,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "3ab34b0c2d4eadccaa0f0cf22ced07b552394063a9de2806993d022360dffc76"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "722dbc861813bb5b568524d62083e875c08e66fed1694d9161d253fa163dd86f"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 5
-	}
+		"consistent_snapshot": false
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "bd2edde6ba4f5cb3a0cc28dca272e2fc0be691575082479f86b82cea4e541a686a0c132c3a7eca231a5782e52e629df92f8f3f89a5b1f57e8b5368986bddfa0e"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/4/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-false/4/repository/snapshot.json
index a47b7a6..489ec31 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/4/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/4/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
-			"sig": "8ce62f94026a58e31a875017e0d10806e19e9541469330cdbfcd9ebfa5f0c317c7eb203256d114307d018400521add578bd2a11c85b5328af3e4efd471b92307"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 5,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 1392,
 				"hashes": {
-					"sha512": "6832a32afe35bb07557081f3a935296cde39c39f6bca65bd068c337743b570818ff6c04a968a40b83228b46d214b44528719babfa3314658df36d4b21b0757ae"
+					"sha512": "93146957ab1f54fe1e8687f408c21a19ad6c033518148bb730b7e635e02f96d9297f1edf12ea5f50354cfcb90385eec9f594d04a08ee876c83759e2314ec8b1a"
 				},
-				"length": 1392,
 				"version": 5
 			}
-		},
-		"spec_version": "1.0",
-		"version": 5
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
+			"sig": "c9da15fd5b0b359a46503d0a23fa3a4e8e481cb2bdb72d6dbec4852ed6f9d32e186b35071b6ca70ec947e1688458c3476d33991af202b177ffd79ff89955e703"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/4/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-false/4/repository/targets.json
index f88f955..d81d1a6 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/4/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/4/repository/targets.json
@@ -1,46 +1,46 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "68f2346cdbe045e8558b2ccd86be66e15466955167557c704b51d7163838f670c53ab9247c16a4ed0cd4ecc981a7e2a04a350b01548f97654499d6f9c17c4202"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 5,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			},
 			"3": {
+				"length": 1,
 				"hashes": {
 					"sha512": "3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb"
-				},
-				"length": 1
+				}
 			},
 			"4": {
+				"length": 1,
 				"hashes": {
 					"sha512": "a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 5
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "68f2346cdbe045e8558b2ccd86be66e15466955167557c704b51d7163838f670c53ab9247c16a4ed0cd4ecc981a7e2a04a350b01548f97654499d6f9c17c4202"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/4/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-false/4/repository/timestamp.json
index 9100ddd..1eb6f40 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/4/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/4/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315",
-			"sig": "36fcb1d9c0e69fe2cd472d97835077b30340da0a326d8d20e844f6a1a84fba439c1662150e029032756b98cd9062686216a77a52b78c6641cd57e8f597d1380b"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 5,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 618,
 				"hashes": {
-					"sha512": "1a984612b0f1657b0a6974bf91e9b33c71a84709a6b36aa76dda4aaea1d132fdd3ef5fd777433a31908bec1f1a39984f9dcc72c3ddbf6b8ed92a7c779d080702"
+					"sha512": "066115510f2f7fbb2f5cb0a1c1d00759161d8a92329e9ce54d4b17c06466b5a4423bb8bcc9e47c0a37db5c7d8d3bc01df10c4ea25605778e788a76e3e9ca1e0e"
 				},
-				"length": 618,
 				"version": 5
 			}
-		},
-		"spec_version": "1.0",
-		"version": 5
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315",
+			"sig": "84b9e41c93b32eed4bdb6febe70f9bd4db39bbc7f0c7f820f6a078bbb7146df080a9ceaa237303e3f69e49eb33cc63f8ddff8fba8330904f5fe8d7a66f70400e"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/5/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-false/5/repository/snapshot.json
index 8e43024..45a607b 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/5/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/5/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
-			"sig": "7ed4b5c650c534154241ee575862730940ecdc61daa4dbbae167aefa2fe2ab47a6dcbccd099ab15630c6ebfd6acdfbacd89f30a6186c791b58a8dc0769bea405"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 6,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 1593,
 				"hashes": {
-					"sha512": "97c2b46ccae4c2338d99819425239796c6647bf242ac64f13ec9347ec38fd8c6a5470756c079e1aaa23a013a8a720440f3128bd6c99f3c9f32492dd829726eee"
+					"sha512": "96fa32225e88f9e98db51369fce606039040efc51f098552594132b301228a78c2f2034d059e4d7d6d7bea14ae9862dd8a995056c5f2ed5ff0d6dc09b9da01df"
 				},
-				"length": 1593,
 				"version": 6
 			}
-		},
-		"spec_version": "1.0",
-		"version": 6
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
+			"sig": "7da0cd1e09be0b8161a1048e08a645e5c8d1558137b2934418bf4e28d4d380b6df2306f5cc89e87e41e5abf079547a709fccd2548bf00fd5acfe5ad2496d670b"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/5/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-false/5/repository/targets.json
index 597f8dc..241d29b 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/5/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/5/repository/targets.json
@@ -1,52 +1,52 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "1e80ae84c4badf194e2fd7225c120999d8f628598fa0e994a2ff7cac705ec2f14601a64ba5370fc668f3fb114975dd81c554400d757f41762c4e12eb4db35d02"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 6,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			},
 			"3": {
+				"length": 1,
 				"hashes": {
 					"sha512": "3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb"
-				},
-				"length": 1
+				}
 			},
 			"4": {
+				"length": 1,
 				"hashes": {
 					"sha512": "a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568"
-				},
-				"length": 1
+				}
 			},
 			"5": {
+				"length": 1,
 				"hashes": {
 					"sha512": "06df05371981a237d0ed11472fae7c94c9ac0eff1d05413516710d17b10a4fb6f4517bda4a695f02d0a73dd4db543b4653df28f5d09dab86f92ffb9b86d01e25"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 6
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "1e80ae84c4badf194e2fd7225c120999d8f628598fa0e994a2ff7cac705ec2f14601a64ba5370fc668f3fb114975dd81c554400d757f41762c4e12eb4db35d02"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-false/5/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-false/5/repository/timestamp.json
index 2c619eb..1129005 100644
--- a/client/testdata/go-tuf/consistent-snapshot-false/5/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-false/5/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315",
-			"sig": "b90b0eaa68d6fbd0fda91dc5c9c27b5ad33665c4cb92e9dfa06742ba71870cb7fcc72d373970f35525c60523a16bae9720d6964da84f579f50480d7f6b27dc01"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 6,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 618,
 				"hashes": {
-					"sha512": "69fe654899c63eedc38d481b56030c560967d00a5e709d536b89de7d166945bce2d5c91737a7b54eb058fccb11c2f8ea300c2529c94263a1f6bcadddfb709cc7"
+					"sha512": "7113ee370f6e1b35df7fd8203d27760e8eb8c32195e8a895f140584caff81256ccdf2d03ed43a5efac45ee4f869908cee2275c0f7e6b54969602e0542c9f78f9"
 				},
-				"length": 618,
 				"version": 6
 			}
-		},
-		"spec_version": "1.0",
-		"version": 6
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315",
+			"sig": "85758e7d1cdbedfd3d363136924a6e7878a2b9b68486ecc65658a29f96b55fcfeeda0f94fcae30fa3ceafc3ef5f82df8c68ad2774b6e4f4ea0e6cdbafdce8e0f"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.root.json b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.root.json
index 008af0d..a564c6a 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
-			"sig": "104eb78cba674adfc7ade1d4396c99466a7d4480e50aab89df53117faffd3d4d4ea87833fe6f83b8dc7f6e1e4a62c0329244c6e5f910627772df3c4d61a8900f"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": true,
+		"spec_version": "1.0",
+		"version": 1,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "62f71f99c788f16bcdc8bb252455e3a690350e4ddea5a6aab1f9a3aaabcf369a"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "bca152214dbfd3e7a1b7a7b3e2cc179fb00520fd7212c8a60ba99f14dfc0e1ca"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 1
-	}
+		"consistent_snapshot": true
+	},
+	"signatures": [
+		{
+			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
+			"sig": "104eb78cba674adfc7ade1d4396c99466a7d4480e50aab89df53117faffd3d4d4ea87833fe6f83b8dc7f6e1e4a62c0329244c6e5f910627772df3c4d61a8900f"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.snapshot.json
index 58cecb2..5d2428f 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
-			"sig": "3f24a81d61a8f1fbe2bf310a9d8263c7b3a5fc87524b92e00a100ce6d8e0f742c0ef05b017234b0d08c9cf4da4591deb65e6f76340afad722b3db1b25d2e0203"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 1,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 588,
 				"hashes": {
-					"sha512": "e0dd9a3833d117cd7bb6fdaae8923d5bda0661cb242be067813bfec3114d83943230b8bb7fcbf093a15d5840f1ecd969f44d3df13e2045d3fb7d22903fbc1bf5"
+					"sha512": "2532c645262d3a15db2afc561d9ae75db96c3b42abe8bd994c173e45ea70177bc1b080e211d92b6f244d267dcb0a0bc2fbcd1c2b008881c19f950c5e8c0035ec"
 				},
-				"length": 588,
 				"version": 1
 			}
-		},
-		"spec_version": "1.0",
-		"version": 1
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
+			"sig": "6efc0efbc7a3b849a58e9cb394af10fe6d199d2ead18e6931932c85f44269d5d73e8f18808d0d9b66fbfd9926b0bda9d2d26a7508a960758c0b84eb8aa31ac0b"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.targets.json b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.targets.json
index 5bb513f..6a82200 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/1.targets.json
@@ -1,22 +1,22 @@
 {
-	"signatures": [
-		{
-			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
-			"sig": "4d5c3a5da43f3792d077c1128fa28585982ff2957fae59be02a831fc920d0b91cbeaa99fd6c15066ec4da8bf12f993440a90d1624fd7b0a68070e5d60ed2500f"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 1,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 1
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
+			"sig": "4d5c3a5da43f3792d077c1128fa28585982ff2957fae59be02a831fc920d0b91cbeaa99fd6c15066ec4da8bf12f993440a90d1624fd7b0a68070e5d60ed2500f"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/root.json b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/root.json
index 008af0d..a564c6a 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
-			"sig": "104eb78cba674adfc7ade1d4396c99466a7d4480e50aab89df53117faffd3d4d4ea87833fe6f83b8dc7f6e1e4a62c0329244c6e5f910627772df3c4d61a8900f"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": true,
+		"spec_version": "1.0",
+		"version": 1,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "62f71f99c788f16bcdc8bb252455e3a690350e4ddea5a6aab1f9a3aaabcf369a"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "bca152214dbfd3e7a1b7a7b3e2cc179fb00520fd7212c8a60ba99f14dfc0e1ca"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 1
-	}
+		"consistent_snapshot": true
+	},
+	"signatures": [
+		{
+			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
+			"sig": "104eb78cba674adfc7ade1d4396c99466a7d4480e50aab89df53117faffd3d4d4ea87833fe6f83b8dc7f6e1e4a62c0329244c6e5f910627772df3c4d61a8900f"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/snapshot.json
index 58cecb2..5d2428f 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
-			"sig": "3f24a81d61a8f1fbe2bf310a9d8263c7b3a5fc87524b92e00a100ce6d8e0f742c0ef05b017234b0d08c9cf4da4591deb65e6f76340afad722b3db1b25d2e0203"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 1,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 588,
 				"hashes": {
-					"sha512": "e0dd9a3833d117cd7bb6fdaae8923d5bda0661cb242be067813bfec3114d83943230b8bb7fcbf093a15d5840f1ecd969f44d3df13e2045d3fb7d22903fbc1bf5"
+					"sha512": "2532c645262d3a15db2afc561d9ae75db96c3b42abe8bd994c173e45ea70177bc1b080e211d92b6f244d267dcb0a0bc2fbcd1c2b008881c19f950c5e8c0035ec"
 				},
-				"length": 588,
 				"version": 1
 			}
-		},
-		"spec_version": "1.0",
-		"version": 1
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
+			"sig": "6efc0efbc7a3b849a58e9cb394af10fe6d199d2ead18e6931932c85f44269d5d73e8f18808d0d9b66fbfd9926b0bda9d2d26a7508a960758c0b84eb8aa31ac0b"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/targets.json
index 5bb513f..6a82200 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/targets.json
@@ -1,22 +1,22 @@
 {
-	"signatures": [
-		{
-			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
-			"sig": "4d5c3a5da43f3792d077c1128fa28585982ff2957fae59be02a831fc920d0b91cbeaa99fd6c15066ec4da8bf12f993440a90d1624fd7b0a68070e5d60ed2500f"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 1,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 1
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
+			"sig": "4d5c3a5da43f3792d077c1128fa28585982ff2957fae59be02a831fc920d0b91cbeaa99fd6c15066ec4da8bf12f993440a90d1624fd7b0a68070e5d60ed2500f"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/timestamp.json
index 32382a3..92d160d 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/0/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/0/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
-			"sig": "cc163b290f68c6d41fbc7ca01a30416a43a5ee7652d2f99aff3c6ef01e5c2fa9d5f2caf0e745abeee3baa277ddfe43ac636149963cf085686345addc9e000301"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 1,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 617,
 				"hashes": {
-					"sha512": "973d23a7e47e1003cd4f8c0e431b080171408e488084fe736b664433d9be76e1f1048ea76607c1f485f1dcb23ce2b4980257431c39cee0fddcc53559997cd565"
+					"sha512": "6fd318e2cc3bca35d2f597e504c095137263ffe3e72f5e5c64e6c7860bea1207448c8994066ffc1cf20898a9d1586cdf09be4e3ea06f69593ed5c7d772f8dfd1"
 				},
-				"length": 617,
 				"version": 1
 			}
-		},
-		"spec_version": "1.0",
-		"version": 1
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
+			"sig": "943b219ab6c651793da08d8cf38c7d25fb959c75161b5b86562983841433f9f38c237bb87cf6ecfbb3cb7c78113a3ed2651ee57d3515e7edfc3bebbf349f2809"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.root.json b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.root.json
index d4e106b..92ff6b2 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.root.json
@@ -1,62 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "7ac71619b21fe3a076fbbf3e17f92177c5374f005c32f1818e7c92eee107e3c726ccf906e800878035a9caf7679610147d72cb515cd76164b08b5c8bf93c0f0e"
-		},
-		{
-			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
-			"sig": "e560f386c0c270bb44cedda965ad21526e65162b41a2c30d84fb3a80f58913432e8dc74e5e7b0635ccdf51a2b951dae3b0ba28b4aac4088641a2b2cd2933dd04"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": true,
+		"spec_version": "1.0",
+		"version": 2,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "62f71f99c788f16bcdc8bb252455e3a690350e4ddea5a6aab1f9a3aaabcf369a"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -85,7 +76,16 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 2
-	}
+		"consistent_snapshot": true
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "7ac71619b21fe3a076fbbf3e17f92177c5374f005c32f1818e7c92eee107e3c726ccf906e800878035a9caf7679610147d72cb515cd76164b08b5c8bf93c0f0e"
+		},
+		{
+			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
+			"sig": "e560f386c0c270bb44cedda965ad21526e65162b41a2c30d84fb3a80f58913432e8dc74e5e7b0635ccdf51a2b951dae3b0ba28b4aac4088641a2b2cd2933dd04"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.snapshot.json
index c8e5b3c..aed7835 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
-			"sig": "bded36f9992b8eb9444a276b397db2ce5f06a8be1273d7f84391b2a098778522a1c49185b2fc858aa99bc69fe820f2444bc8e5077f447ddcf42515c3a7026e0a"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 2,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 789,
 				"hashes": {
-					"sha512": "8672c435a53519972738fada6ed3b7fa37b3ea42b4fa1e436b774e697a8d696d9efbeb6c590a6e16dec0a5e7f789da82ea59a68fae63f343340d1549a075ab1b"
+					"sha512": "7a919ed2a5fb7cf80252c9307ac4d27bc2ab54f9bb803389977dcc3d09ae7dff533639c1b19a810d2b212a5c5e904e0f73ab01324ba79dffbb9f7488204caf2a"
 				},
-				"length": 789,
 				"version": 2
 			}
-		},
-		"spec_version": "1.0",
-		"version": 2
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
+			"sig": "9a3734441c38daa3275ba60a2178b8dfe5f98296f408bf434144b4bd4f68af73b7f6860e6f2e638b93144ac5bebe361642bbff66a1195596bb8c841429b34508"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.targets.json b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.targets.json
index be81713..0ae4c79 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/2.targets.json
@@ -1,28 +1,28 @@
 {
-	"signatures": [
-		{
-			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
-			"sig": "81bcf5921834a20b8b0946815ad4316f43ffce20b3793e6653dc5fd4b98f1c6318ce2243948574e82414a102717a6f2d731250b3191c54abc8391fd867503e0b"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 2,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 2
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
+			"sig": "81bcf5921834a20b8b0946815ad4316f43ffce20b3793e6653dc5fd4b98f1c6318ce2243948574e82414a102717a6f2d731250b3191c54abc8391fd867503e0b"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/root.json b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/root.json
index d4e106b..92ff6b2 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/root.json
@@ -1,62 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "7ac71619b21fe3a076fbbf3e17f92177c5374f005c32f1818e7c92eee107e3c726ccf906e800878035a9caf7679610147d72cb515cd76164b08b5c8bf93c0f0e"
-		},
-		{
-			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
-			"sig": "e560f386c0c270bb44cedda965ad21526e65162b41a2c30d84fb3a80f58913432e8dc74e5e7b0635ccdf51a2b951dae3b0ba28b4aac4088641a2b2cd2933dd04"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": true,
+		"spec_version": "1.0",
+		"version": 2,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "62f71f99c788f16bcdc8bb252455e3a690350e4ddea5a6aab1f9a3aaabcf369a"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -85,7 +76,16 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 2
-	}
+		"consistent_snapshot": true
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "7ac71619b21fe3a076fbbf3e17f92177c5374f005c32f1818e7c92eee107e3c726ccf906e800878035a9caf7679610147d72cb515cd76164b08b5c8bf93c0f0e"
+		},
+		{
+			"keyid": "ce72db3f938914205461a415c9b7b91267a2079df991fd6283aa8461988c1add",
+			"sig": "e560f386c0c270bb44cedda965ad21526e65162b41a2c30d84fb3a80f58913432e8dc74e5e7b0635ccdf51a2b951dae3b0ba28b4aac4088641a2b2cd2933dd04"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/snapshot.json
index c8e5b3c..aed7835 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
-			"sig": "bded36f9992b8eb9444a276b397db2ce5f06a8be1273d7f84391b2a098778522a1c49185b2fc858aa99bc69fe820f2444bc8e5077f447ddcf42515c3a7026e0a"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 2,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 789,
 				"hashes": {
-					"sha512": "8672c435a53519972738fada6ed3b7fa37b3ea42b4fa1e436b774e697a8d696d9efbeb6c590a6e16dec0a5e7f789da82ea59a68fae63f343340d1549a075ab1b"
+					"sha512": "7a919ed2a5fb7cf80252c9307ac4d27bc2ab54f9bb803389977dcc3d09ae7dff533639c1b19a810d2b212a5c5e904e0f73ab01324ba79dffbb9f7488204caf2a"
 				},
-				"length": 789,
 				"version": 2
 			}
-		},
-		"spec_version": "1.0",
-		"version": 2
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
+			"sig": "9a3734441c38daa3275ba60a2178b8dfe5f98296f408bf434144b4bd4f68af73b7f6860e6f2e638b93144ac5bebe361642bbff66a1195596bb8c841429b34508"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/targets.json
index be81713..0ae4c79 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/targets.json
@@ -1,28 +1,28 @@
 {
-	"signatures": [
-		{
-			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
-			"sig": "81bcf5921834a20b8b0946815ad4316f43ffce20b3793e6653dc5fd4b98f1c6318ce2243948574e82414a102717a6f2d731250b3191c54abc8391fd867503e0b"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 2,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 2
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "808aa256a8172bb0cb961767c6768e55ccf732c99afccc6145752d7a328b7937",
+			"sig": "81bcf5921834a20b8b0946815ad4316f43ffce20b3793e6653dc5fd4b98f1c6318ce2243948574e82414a102717a6f2d731250b3191c54abc8391fd867503e0b"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/timestamp.json
index 42b04d4..ab60e90 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/1/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/1/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
-			"sig": "8ab93c7453677374d1483c495b49d80128b589ca80c1f3e7806bb3c40bd8be793c6df492ce68b2bcf5d50af73fdf7694b0484093b31577720898d6882ae97d0f"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 2,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 617,
 				"hashes": {
-					"sha512": "957e34523e34c2316a9fd02744162834382101796efca153e35028eb1e3fe970427d4e60e375300d1ac92e1c0a8ec74a1b5575a29d337b3454083a76cb922959"
+					"sha512": "d7204efe9ded4f18d679d75054f43b02b20d74189ea81ad90a67399a8884a810e380a4d343e284c4b6fde506e22a464038871d06950166548a84a76344e2bf3a"
 				},
-				"length": 617,
 				"version": 2
 			}
-		},
-		"spec_version": "1.0",
-		"version": 2
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
+			"sig": "85c5afdd9dd3777d2cb31721519ab2942edffc9e1282b65b2cede505a469051ac5e86388461db49f948a5998b132dddb5ce0156d21622a6d2201fb93322de20f"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.root.json b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.root.json
index 0695588..3b1c2e2 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "475436056dca79fd151ae830ad2f4dbc7ecc5b146a79319c20a1167d4f214047d8f3847d1cda4ccd32a48acb13acbea55ba7e8254cffaa07e3de9ecdd0c13d03"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": true,
+		"spec_version": "1.0",
+		"version": 3,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 3
-	}
+		"consistent_snapshot": true
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "475436056dca79fd151ae830ad2f4dbc7ecc5b146a79319c20a1167d4f214047d8f3847d1cda4ccd32a48acb13acbea55ba7e8254cffaa07e3de9ecdd0c13d03"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.snapshot.json
index 772b23e..ded8ac9 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
-			"sig": "94a60aaddf390953b997b783bab689a2cbaf66610b4dee5645ef858480f709b61afefc5eb21c6131aa5d3e2248eccebe77a7b4a8462f6f8f7964680085053903"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 3,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 990,
 				"hashes": {
-					"sha512": "b103f5cd1d68e0b5f7b96af03a27cf971460977976cff0b1d1371dcce6d45ef78e183fa26bf886f3864e84b8ddbbfc1bab7bd0e2be180ad82ed26f22a8e9b68b"
+					"sha512": "987022c23793b3d234d422c3ed4525f8c3771887db610fb2e7d6b455d27ad8b1b4a957a699d519c03754fe4feeb387ec84c95e1edac1d4e9b186bfbdff76ad10"
 				},
-				"length": 990,
 				"version": 3
 			}
-		},
-		"spec_version": "1.0",
-		"version": 3
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
+			"sig": "31896c9165a37aa54cf1c4d5f936035e092b1cf4c233ef35cd12c987aaa02de7ec99f26c198984fe0dcc21765d096b25cd67e7ca058613b2b2abef3193dd880d"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.targets.json b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.targets.json
index ad58a9d..b22a1d7 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/3.targets.json
@@ -1,34 +1,34 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "09593c7b47f4dbf1e8ac949fa010279ffbbd36070a54a89b689378441e8111602d4236fa2962063778c82027d4746a8973ba8fea86e9c105190da9fa362d8b0c"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 3,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 3
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "09593c7b47f4dbf1e8ac949fa010279ffbbd36070a54a89b689378441e8111602d4236fa2962063778c82027d4746a8973ba8fea86e9c105190da9fa362d8b0c"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/root.json b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/root.json
index 0695588..3b1c2e2 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "475436056dca79fd151ae830ad2f4dbc7ecc5b146a79319c20a1167d4f214047d8f3847d1cda4ccd32a48acb13acbea55ba7e8254cffaa07e3de9ecdd0c13d03"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": true,
+		"spec_version": "1.0",
+		"version": 3,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "d482fa4805a50870aa1356ace6b764f7ab47ed4dc38f49b1a189afa25f179e94"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 3
-	}
+		"consistent_snapshot": true
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "475436056dca79fd151ae830ad2f4dbc7ecc5b146a79319c20a1167d4f214047d8f3847d1cda4ccd32a48acb13acbea55ba7e8254cffaa07e3de9ecdd0c13d03"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/snapshot.json
index 772b23e..ded8ac9 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
-			"sig": "94a60aaddf390953b997b783bab689a2cbaf66610b4dee5645ef858480f709b61afefc5eb21c6131aa5d3e2248eccebe77a7b4a8462f6f8f7964680085053903"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 3,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 990,
 				"hashes": {
-					"sha512": "b103f5cd1d68e0b5f7b96af03a27cf971460977976cff0b1d1371dcce6d45ef78e183fa26bf886f3864e84b8ddbbfc1bab7bd0e2be180ad82ed26f22a8e9b68b"
+					"sha512": "987022c23793b3d234d422c3ed4525f8c3771887db610fb2e7d6b455d27ad8b1b4a957a699d519c03754fe4feeb387ec84c95e1edac1d4e9b186bfbdff76ad10"
 				},
-				"length": 990,
 				"version": 3
 			}
-		},
-		"spec_version": "1.0",
-		"version": 3
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "289e5a9e71afd7909326aa4caea92f7557ee0e2283d8c31f0c3401ce67248a45",
+			"sig": "31896c9165a37aa54cf1c4d5f936035e092b1cf4c233ef35cd12c987aaa02de7ec99f26c198984fe0dcc21765d096b25cd67e7ca058613b2b2abef3193dd880d"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/targets.json
index ad58a9d..b22a1d7 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/targets.json
@@ -1,34 +1,34 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "09593c7b47f4dbf1e8ac949fa010279ffbbd36070a54a89b689378441e8111602d4236fa2962063778c82027d4746a8973ba8fea86e9c105190da9fa362d8b0c"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 3,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 3
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "09593c7b47f4dbf1e8ac949fa010279ffbbd36070a54a89b689378441e8111602d4236fa2962063778c82027d4746a8973ba8fea86e9c105190da9fa362d8b0c"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/timestamp.json
index d5a05d7..4856974 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/2/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/2/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
-			"sig": "e431037f03bb3e323aa6d9f97533883a0d111698a17cd7eb7843961fa4b15a12a98a8a6cac377df934a9303d3765cc5314f59a160ffe11a32e76c18c27b0180f"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 3,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 617,
 				"hashes": {
-					"sha512": "49d07f15210a34a0b2bf51e2d349b243bba68800796a6f7031adaa14a86da0f3aa96098c46c6f55330fb71a424a6658cdf09683287f72f9082302e9be3aec1ef"
+					"sha512": "70d2f64bc810a0ae1c827c28eed47304c3a9c57402447d129aa3ac851d809a48bd0421aaa99e9e49055984e77f221510415cf27aca8f30f4db1767d6b7bd6024"
 				},
-				"length": 617,
 				"version": 3
 			}
-		},
-		"spec_version": "1.0",
-		"version": 3
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
+			"sig": "22367ebcf7c5265260b288e9fec6110257b8c8745af25f2b14c5d347ddab94f46893926bdd37c58d142089419708e446c5e3c1af5c47c51187fe69ca95038605"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.root.json b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.root.json
index 2b2f50b..a389f49 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "15431a0217deb636e2e79876cfdfc8b78fdda1119e6c8512c7dc61af240a7d2303f172e7fc28de7dfe58d92c84f5118ccd09d0f29f49aaa3f7ef95edf21e2d0a"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": true,
+		"spec_version": "1.0",
+		"version": 4,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "722dbc861813bb5b568524d62083e875c08e66fed1694d9161d253fa163dd86f"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 4
-	}
+		"consistent_snapshot": true
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "15431a0217deb636e2e79876cfdfc8b78fdda1119e6c8512c7dc61af240a7d2303f172e7fc28de7dfe58d92c84f5118ccd09d0f29f49aaa3f7ef95edf21e2d0a"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.snapshot.json
index 8634000..41e4ac6 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
-			"sig": "bb6acd05cd4328a69a227ec24f3f241e3b692dfa04301b3ec682c808f143c94bed361ac5215800189f1b415a05ee1bf8534d452dab8548abe514582b91d0f308"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 4,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 1191,
 				"hashes": {
-					"sha512": "75cc15d5a7c20656e37ece0a339434922fb489cf79f8ddf6a11d8c2a797ba1c7c51da0efaf335b31f9185c1eb9a5bbd074e16d412983a104e3bd33877eeb54c3"
+					"sha512": "2bf10fb9469cb5f44ccae3c8dac2f70c19e7c58479f74f21aca7a424774ed7ef43295fff3c05f7cfe457b5832366b64e0550874775e277d7233c060e9f94e140"
 				},
-				"length": 1191,
 				"version": 4
 			}
-		},
-		"spec_version": "1.0",
-		"version": 4
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
+			"sig": "c5efdc1b461ae319c991fd1840771d94dfc8a3e655ac233901a27959e9f2c3e7ab61b83e3d674caf9e2a6043e776d7c32a2c36dbf0922f7f08059d08fc26720a"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.targets.json b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.targets.json
index 88bb26e..8265b26 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/4.targets.json
@@ -1,40 +1,40 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "7bfe0a63ee324034807b5341336d9d2d64e9ef3936086577b5bbcc6d021b4656bd6bf14d817bbb3908e4dcb05391d1b4031b527c14d942c2d1e38275d5ff1308"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 4,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			},
 			"3": {
+				"length": 1,
 				"hashes": {
 					"sha512": "3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 4
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "7bfe0a63ee324034807b5341336d9d2d64e9ef3936086577b5bbcc6d021b4656bd6bf14d817bbb3908e4dcb05391d1b4031b527c14d942c2d1e38275d5ff1308"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/root.json b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/root.json
index 2b2f50b..a389f49 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "15431a0217deb636e2e79876cfdfc8b78fdda1119e6c8512c7dc61af240a7d2303f172e7fc28de7dfe58d92c84f5118ccd09d0f29f49aaa3f7ef95edf21e2d0a"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": true,
+		"spec_version": "1.0",
+		"version": 4,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "8656ad20568cd3534c405e4d9a84b0c6e6163f7f66434df77416502835b9b160"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "722dbc861813bb5b568524d62083e875c08e66fed1694d9161d253fa163dd86f"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 4
-	}
+		"consistent_snapshot": true
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "15431a0217deb636e2e79876cfdfc8b78fdda1119e6c8512c7dc61af240a7d2303f172e7fc28de7dfe58d92c84f5118ccd09d0f29f49aaa3f7ef95edf21e2d0a"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/snapshot.json
index 8634000..41e4ac6 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
-			"sig": "bb6acd05cd4328a69a227ec24f3f241e3b692dfa04301b3ec682c808f143c94bed361ac5215800189f1b415a05ee1bf8534d452dab8548abe514582b91d0f308"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 4,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 1191,
 				"hashes": {
-					"sha512": "75cc15d5a7c20656e37ece0a339434922fb489cf79f8ddf6a11d8c2a797ba1c7c51da0efaf335b31f9185c1eb9a5bbd074e16d412983a104e3bd33877eeb54c3"
+					"sha512": "2bf10fb9469cb5f44ccae3c8dac2f70c19e7c58479f74f21aca7a424774ed7ef43295fff3c05f7cfe457b5832366b64e0550874775e277d7233c060e9f94e140"
 				},
-				"length": 1191,
 				"version": 4
 			}
-		},
-		"spec_version": "1.0",
-		"version": 4
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
+			"sig": "c5efdc1b461ae319c991fd1840771d94dfc8a3e655ac233901a27959e9f2c3e7ab61b83e3d674caf9e2a6043e776d7c32a2c36dbf0922f7f08059d08fc26720a"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/targets.json
index 88bb26e..8265b26 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/targets.json
@@ -1,40 +1,40 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "7bfe0a63ee324034807b5341336d9d2d64e9ef3936086577b5bbcc6d021b4656bd6bf14d817bbb3908e4dcb05391d1b4031b527c14d942c2d1e38275d5ff1308"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 4,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			},
 			"3": {
+				"length": 1,
 				"hashes": {
 					"sha512": "3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 4
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "7bfe0a63ee324034807b5341336d9d2d64e9ef3936086577b5bbcc6d021b4656bd6bf14d817bbb3908e4dcb05391d1b4031b527c14d942c2d1e38275d5ff1308"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/timestamp.json
index 0b5d5f7..c87022e 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/3/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/3/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
-			"sig": "40e97ae18e413a3b44f2f1fb19c0ab57303fb39e950a38954a845f4ba1185bae2314e20c1dc5f157f60106c50e546e1d3469fb0b4cf6675810798f84f22cd001"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 4,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 618,
 				"hashes": {
-					"sha512": "e55cb3fd889a759eaad70713f44d226a3b9b55b0e934fb6a1588832661c553d7f1e0cd6a2dfffeccabb5312dc9cf11ea88f34afbabd6fb715742ba60eb62756c"
+					"sha512": "4ddee1c0c54af1a3dc54897af33c2457525963059c29583e6df65b9b238732070bd8eb470201154f2d2fa5f8bdf37e01a86e6a53c2bcfe0ff302571458c1898d"
 				},
-				"length": 618,
 				"version": 4
 			}
-		},
-		"spec_version": "1.0",
-		"version": 4
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "aa3255b4e8e17e566d2bdbea0e5842978f9fa1d2fa9ec76ae76b146164acbfc8",
+			"sig": "585cdcc87c23711642449d469df8bedb53a67b65ac75c303d13b7022c8c34c1db70c926e009c2438639af3be1d613f7ce4c7e28020865ad5ad93a5b085a76005"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.root.json b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.root.json
index 955b19c..dcb0e92 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "2b6f30258eaf8b4b2d900a2efb4a597b45a9c0c5a0720d5521dd37d63c34d1db62aafaa1d95b6d881f9c991615ab68930c24ef247d2f45836bca3659e36d9c0b"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": true,
+		"spec_version": "1.0",
+		"version": 5,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "3ab34b0c2d4eadccaa0f0cf22ced07b552394063a9de2806993d022360dffc76"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "722dbc861813bb5b568524d62083e875c08e66fed1694d9161d253fa163dd86f"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 5
-	}
+		"consistent_snapshot": true
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "2b6f30258eaf8b4b2d900a2efb4a597b45a9c0c5a0720d5521dd37d63c34d1db62aafaa1d95b6d881f9c991615ab68930c24ef247d2f45836bca3659e36d9c0b"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.snapshot.json
index a47b7a6..489ec31 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
-			"sig": "8ce62f94026a58e31a875017e0d10806e19e9541469330cdbfcd9ebfa5f0c317c7eb203256d114307d018400521add578bd2a11c85b5328af3e4efd471b92307"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 5,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 1392,
 				"hashes": {
-					"sha512": "6832a32afe35bb07557081f3a935296cde39c39f6bca65bd068c337743b570818ff6c04a968a40b83228b46d214b44528719babfa3314658df36d4b21b0757ae"
+					"sha512": "93146957ab1f54fe1e8687f408c21a19ad6c033518148bb730b7e635e02f96d9297f1edf12ea5f50354cfcb90385eec9f594d04a08ee876c83759e2314ec8b1a"
 				},
-				"length": 1392,
 				"version": 5
 			}
-		},
-		"spec_version": "1.0",
-		"version": 5
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
+			"sig": "c9da15fd5b0b359a46503d0a23fa3a4e8e481cb2bdb72d6dbec4852ed6f9d32e186b35071b6ca70ec947e1688458c3476d33991af202b177ffd79ff89955e703"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.targets.json b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.targets.json
index f88f955..d81d1a6 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/5.targets.json
@@ -1,46 +1,46 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "68f2346cdbe045e8558b2ccd86be66e15466955167557c704b51d7163838f670c53ab9247c16a4ed0cd4ecc981a7e2a04a350b01548f97654499d6f9c17c4202"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 5,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			},
 			"3": {
+				"length": 1,
 				"hashes": {
 					"sha512": "3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb"
-				},
-				"length": 1
+				}
 			},
 			"4": {
+				"length": 1,
 				"hashes": {
 					"sha512": "a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 5
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "68f2346cdbe045e8558b2ccd86be66e15466955167557c704b51d7163838f670c53ab9247c16a4ed0cd4ecc981a7e2a04a350b01548f97654499d6f9c17c4202"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/root.json b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/root.json
index 955b19c..dcb0e92 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/root.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/root.json
@@ -1,58 +1,53 @@
 {
-	"signatures": [
-		{
-			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
-			"sig": "2b6f30258eaf8b4b2d900a2efb4a597b45a9c0c5a0720d5521dd37d63c34d1db62aafaa1d95b6d881f9c991615ab68930c24ef247d2f45836bca3659e36d9c0b"
-		}
-	],
 	"signed": {
 		"_type": "root",
-		"consistent_snapshot": true,
+		"spec_version": "1.0",
+		"version": 5,
 		"expires": "2100-01-01T00:00:00Z",
 		"keys": {
 			"a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "3ab34b0c2d4eadccaa0f0cf22ced07b552394063a9de2806993d022360dffc76"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "722dbc861813bb5b568524d62083e875c08e66fed1694d9161d253fa163dd86f"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "153986a7370e002f377dd68797e7466c421180c1571e233de2f8ab41c8af4f54"
-				},
-				"scheme": "ed25519"
+				}
 			},
 			"bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1": {
+				"keytype": "ed25519",
+				"scheme": "ed25519",
 				"keyid_hash_algorithms": [
 					"sha256",
 					"sha512"
 				],
-				"keytype": "ed25519",
 				"keyval": {
 					"public": "aee574e56780ea1709a8b56e02d4ffdd9a3a1deaed61e2eb0701f376a4422e42"
-				},
-				"scheme": "ed25519"
+				}
 			}
 		},
 		"roles": {
@@ -81,7 +76,12 @@
 				"threshold": 1
 			}
 		},
-		"spec_version": "1.0",
-		"version": 5
-	}
+		"consistent_snapshot": true
+	},
+	"signatures": [
+		{
+			"keyid": "b2403f96ae9b1089d8cbc15bbc35e9acbacd7984571f951b43aab56aedcfa84f",
+			"sig": "2b6f30258eaf8b4b2d900a2efb4a597b45a9c0c5a0720d5521dd37d63c34d1db62aafaa1d95b6d881f9c991615ab68930c24ef247d2f45836bca3659e36d9c0b"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/snapshot.json
index a47b7a6..489ec31 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
-			"sig": "8ce62f94026a58e31a875017e0d10806e19e9541469330cdbfcd9ebfa5f0c317c7eb203256d114307d018400521add578bd2a11c85b5328af3e4efd471b92307"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 5,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 1392,
 				"hashes": {
-					"sha512": "6832a32afe35bb07557081f3a935296cde39c39f6bca65bd068c337743b570818ff6c04a968a40b83228b46d214b44528719babfa3314658df36d4b21b0757ae"
+					"sha512": "93146957ab1f54fe1e8687f408c21a19ad6c033518148bb730b7e635e02f96d9297f1edf12ea5f50354cfcb90385eec9f594d04a08ee876c83759e2314ec8b1a"
 				},
-				"length": 1392,
 				"version": 5
 			}
-		},
-		"spec_version": "1.0",
-		"version": 5
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
+			"sig": "c9da15fd5b0b359a46503d0a23fa3a4e8e481cb2bdb72d6dbec4852ed6f9d32e186b35071b6ca70ec947e1688458c3476d33991af202b177ffd79ff89955e703"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/targets.json
index f88f955..d81d1a6 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/targets.json
@@ -1,46 +1,46 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "68f2346cdbe045e8558b2ccd86be66e15466955167557c704b51d7163838f670c53ab9247c16a4ed0cd4ecc981a7e2a04a350b01548f97654499d6f9c17c4202"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 5,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			},
 			"3": {
+				"length": 1,
 				"hashes": {
 					"sha512": "3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb"
-				},
-				"length": 1
+				}
 			},
 			"4": {
+				"length": 1,
 				"hashes": {
 					"sha512": "a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 5
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "68f2346cdbe045e8558b2ccd86be66e15466955167557c704b51d7163838f670c53ab9247c16a4ed0cd4ecc981a7e2a04a350b01548f97654499d6f9c17c4202"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/timestamp.json
index 9100ddd..1eb6f40 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/4/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/4/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315",
-			"sig": "36fcb1d9c0e69fe2cd472d97835077b30340da0a326d8d20e844f6a1a84fba439c1662150e029032756b98cd9062686216a77a52b78c6641cd57e8f597d1380b"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 5,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 618,
 				"hashes": {
-					"sha512": "1a984612b0f1657b0a6974bf91e9b33c71a84709a6b36aa76dda4aaea1d132fdd3ef5fd777433a31908bec1f1a39984f9dcc72c3ddbf6b8ed92a7c779d080702"
+					"sha512": "066115510f2f7fbb2f5cb0a1c1d00759161d8a92329e9ce54d4b17c06466b5a4423bb8bcc9e47c0a37db5c7d8d3bc01df10c4ea25605778e788a76e3e9ca1e0e"
 				},
-				"length": 618,
 				"version": 5
 			}
-		},
-		"spec_version": "1.0",
-		"version": 5
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315",
+			"sig": "84b9e41c93b32eed4bdb6febe70f9bd4db39bbc7f0c7f820f6a078bbb7146df080a9ceaa237303e3f69e49eb33cc63f8ddff8fba8330904f5fe8d7a66f70400e"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/5/repository/6.snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/5/repository/6.snapshot.json
index 8e43024..45a607b 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/5/repository/6.snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/5/repository/6.snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
-			"sig": "7ed4b5c650c534154241ee575862730940ecdc61daa4dbbae167aefa2fe2ab47a6dcbccd099ab15630c6ebfd6acdfbacd89f30a6186c791b58a8dc0769bea405"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 6,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 1593,
 				"hashes": {
-					"sha512": "97c2b46ccae4c2338d99819425239796c6647bf242ac64f13ec9347ec38fd8c6a5470756c079e1aaa23a013a8a720440f3128bd6c99f3c9f32492dd829726eee"
+					"sha512": "96fa32225e88f9e98db51369fce606039040efc51f098552594132b301228a78c2f2034d059e4d7d6d7bea14ae9862dd8a995056c5f2ed5ff0d6dc09b9da01df"
 				},
-				"length": 1593,
 				"version": 6
 			}
-		},
-		"spec_version": "1.0",
-		"version": 6
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
+			"sig": "7da0cd1e09be0b8161a1048e08a645e5c8d1558137b2934418bf4e28d4d380b6df2306f5cc89e87e41e5abf079547a709fccd2548bf00fd5acfe5ad2496d670b"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/5/repository/6.targets.json b/client/testdata/go-tuf/consistent-snapshot-true/5/repository/6.targets.json
index 597f8dc..241d29b 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/5/repository/6.targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/5/repository/6.targets.json
@@ -1,52 +1,52 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "1e80ae84c4badf194e2fd7225c120999d8f628598fa0e994a2ff7cac705ec2f14601a64ba5370fc668f3fb114975dd81c554400d757f41762c4e12eb4db35d02"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 6,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			},
 			"3": {
+				"length": 1,
 				"hashes": {
 					"sha512": "3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb"
-				},
-				"length": 1
+				}
 			},
 			"4": {
+				"length": 1,
 				"hashes": {
 					"sha512": "a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568"
-				},
-				"length": 1
+				}
 			},
 			"5": {
+				"length": 1,
 				"hashes": {
 					"sha512": "06df05371981a237d0ed11472fae7c94c9ac0eff1d05413516710d17b10a4fb6f4517bda4a695f02d0a73dd4db543b4653df28f5d09dab86f92ffb9b86d01e25"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 6
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "1e80ae84c4badf194e2fd7225c120999d8f628598fa0e994a2ff7cac705ec2f14601a64ba5370fc668f3fb114975dd81c554400d757f41762c4e12eb4db35d02"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/5/repository/snapshot.json b/client/testdata/go-tuf/consistent-snapshot-true/5/repository/snapshot.json
index 8e43024..45a607b 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/5/repository/snapshot.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/5/repository/snapshot.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
-			"sig": "7ed4b5c650c534154241ee575862730940ecdc61daa4dbbae167aefa2fe2ab47a6dcbccd099ab15630c6ebfd6acdfbacd89f30a6186c791b58a8dc0769bea405"
-		}
-	],
 	"signed": {
 		"_type": "snapshot",
+		"spec_version": "1.0",
+		"version": 6,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"targets.json": {
+				"length": 1593,
 				"hashes": {
-					"sha512": "97c2b46ccae4c2338d99819425239796c6647bf242ac64f13ec9347ec38fd8c6a5470756c079e1aaa23a013a8a720440f3128bd6c99f3c9f32492dd829726eee"
+					"sha512": "96fa32225e88f9e98db51369fce606039040efc51f098552594132b301228a78c2f2034d059e4d7d6d7bea14ae9862dd8a995056c5f2ed5ff0d6dc09b9da01df"
 				},
-				"length": 1593,
 				"version": 6
 			}
-		},
-		"spec_version": "1.0",
-		"version": 6
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "b096bc2d67080cec22e6c0bbaa69cfd9d714b9e9ad847d255f950b2728855fef",
+			"sig": "7da0cd1e09be0b8161a1048e08a645e5c8d1558137b2934418bf4e28d4d380b6df2306f5cc89e87e41e5abf079547a709fccd2548bf00fd5acfe5ad2496d670b"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/5/repository/targets.json b/client/testdata/go-tuf/consistent-snapshot-true/5/repository/targets.json
index 597f8dc..241d29b 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/5/repository/targets.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/5/repository/targets.json
@@ -1,52 +1,52 @@
 {
-	"signatures": [
-		{
-			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
-			"sig": "1e80ae84c4badf194e2fd7225c120999d8f628598fa0e994a2ff7cac705ec2f14601a64ba5370fc668f3fb114975dd81c554400d757f41762c4e12eb4db35d02"
-		}
-	],
 	"signed": {
 		"_type": "targets",
-		"expires": "2100-01-01T00:00:00Z",
 		"spec_version": "1.0",
+		"version": 6,
+		"expires": "2100-01-01T00:00:00Z",
 		"targets": {
 			"0": {
+				"length": 1,
 				"hashes": {
 					"sha512": "31bca02094eb78126a517b206a88c73cfa9ec6f704c7030d18212cace820f025f00bf0ea68dbf3f3a5436ca63b53bf7bf80ad8d5de7d8359d0b7fed9dbc3ab99"
-				},
-				"length": 1
+				}
 			},
 			"1": {
+				"length": 1,
 				"hashes": {
 					"sha512": "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a"
-				},
-				"length": 1
+				}
 			},
 			"2": {
+				"length": 1,
 				"hashes": {
 					"sha512": "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114"
-				},
-				"length": 1
+				}
 			},
 			"3": {
+				"length": 1,
 				"hashes": {
 					"sha512": "3bafbf08882a2d10133093a1b8433f50563b93c14acd05b79028eb1d12799027241450980651994501423a66c276ae26c43b739bc65c4e16b10c3af6c202aebb"
-				},
-				"length": 1
+				}
 			},
 			"4": {
+				"length": 1,
 				"hashes": {
 					"sha512": "a321d8b405e3ef2604959847b36d171eebebc4a8941dc70a4784935a4fca5d5813de84dfa049f06549aa61b20848c1633ce81b675286ea8fb53db240d831c568"
-				},
-				"length": 1
+				}
 			},
 			"5": {
+				"length": 1,
 				"hashes": {
 					"sha512": "06df05371981a237d0ed11472fae7c94c9ac0eff1d05413516710d17b10a4fb6f4517bda4a695f02d0a73dd4db543b4653df28f5d09dab86f92ffb9b86d01e25"
-				},
-				"length": 1
+				}
 			}
-		},
-		"version": 6
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "bc8f087663855564b358ddf314d5932ab920af17bd1df2f58b397afd82d76dc1",
+			"sig": "1e80ae84c4badf194e2fd7225c120999d8f628598fa0e994a2ff7cac705ec2f14601a64ba5370fc668f3fb114975dd81c554400d757f41762c4e12eb4db35d02"
+		}
+	]
 }
\ No newline at end of file
diff --git a/client/testdata/go-tuf/consistent-snapshot-true/5/repository/timestamp.json b/client/testdata/go-tuf/consistent-snapshot-true/5/repository/timestamp.json
index 2c619eb..1129005 100644
--- a/client/testdata/go-tuf/consistent-snapshot-true/5/repository/timestamp.json
+++ b/client/testdata/go-tuf/consistent-snapshot-true/5/repository/timestamp.json
@@ -1,23 +1,23 @@
 {
-	"signatures": [
-		{
-			"keyid": "a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315",
-			"sig": "b90b0eaa68d6fbd0fda91dc5c9c27b5ad33665c4cb92e9dfa06742ba71870cb7fcc72d373970f35525c60523a16bae9720d6964da84f579f50480d7f6b27dc01"
-		}
-	],
 	"signed": {
 		"_type": "timestamp",
+		"spec_version": "1.0",
+		"version": 6,
 		"expires": "2100-01-01T00:00:00Z",
 		"meta": {
 			"snapshot.json": {
+				"length": 618,
 				"hashes": {
-					"sha512": "69fe654899c63eedc38d481b56030c560967d00a5e709d536b89de7d166945bce2d5c91737a7b54eb058fccb11c2f8ea300c2529c94263a1f6bcadddfb709cc7"
+					"sha512": "7113ee370f6e1b35df7fd8203d27760e8eb8c32195e8a895f140584caff81256ccdf2d03ed43a5efac45ee4f869908cee2275c0f7e6b54969602e0542c9f78f9"
 				},
-				"length": 618,
 				"version": 6
 			}
-		},
-		"spec_version": "1.0",
-		"version": 6
-	}
+		}
+	},
+	"signatures": [
+		{
+			"keyid": "a8eaf6de5aecfd0a72b60295b1e1cd12f349079ebcbbb63dbe7072f162e85315",
+			"sig": "85758e7d1cdbedfd3d363136924a6e7878a2b9b68486ecc65658a29f96b55fcfeeda0f94fcae30fa3ceafc3ef5f82df8c68ad2774b6e4f4ea0e6cdbafdce8e0f"
+		}
+	]
 }
\ No newline at end of file
diff --git a/repo_test.go b/repo_test.go
index a021ac0..c71bf5f 100644
--- a/repo_test.go
+++ b/repo_test.go
@@ -21,6 +21,7 @@ import (
 	"github.com/theupdateframework/go-tuf/encrypted"
 	"github.com/theupdateframework/go-tuf/internal/sets"
 	"github.com/theupdateframework/go-tuf/pkg/keys"
+	"github.com/theupdateframework/go-tuf/pkg/targets"
 	"github.com/theupdateframework/go-tuf/util"
 	"github.com/theupdateframework/go-tuf/verify"
 	"golang.org/x/crypto/ed25519"
@@ -165,8 +166,11 @@ func (rs *RepoSuite) TestInit(c *C) {
 		c.Assert(root.ConsistentSnapshot, Equals, v)
 	}
 
-	// Init() fails if targets have been added
+	// Add a target.
+	generateAndAddPrivateKey(c, r, "targets")
 	c.Assert(r.AddTarget("foo.txt", nil), IsNil)
+
+	// Init() fails if targets have been added
 	c.Assert(r.Init(true), Equals, ErrInitNotAllowed)
 }
 
@@ -632,7 +636,7 @@ func (rs *RepoSuite) TestSign(c *C) {
 	r, err := NewRepo(local)
 	c.Assert(err, IsNil)
 
-	c.Assert(r.Sign("foo.json"), Equals, ErrInvalidRole{"foo", "only signing top-level metadata supported"})
+	c.Assert(r.Sign("foo.json"), Equals, ErrMissingMetadata{"foo.json"})
 
 	// signing with no keys returns ErrInsufficientKeys
 	c.Assert(r.Sign("root.json"), Equals, ErrInsufficientKeys{"root.json"})
@@ -1386,16 +1390,20 @@ func (rs *RepoSuite) TestKeyPersistence(c *C) {
 	c.Assert(insecureStore.SaveSigner("targets", signer), IsNil)
 	assertKeys("targets", false, []*data.PrivateKey{privateKey})
 
+	c.Assert(insecureStore.SaveSigner("foo", signer), IsNil)
+	assertKeys("foo", false, []*data.PrivateKey{privateKey})
+
 	// Test changing the passphrase
 	// 1. Create a secure store with a passphrase (create new object and temp folder so we discard any previous state)
 	tmp = newTmpDir(c)
 	store = FileSystemStore(tmp.path, testPassphraseFunc)
 
-	// 1.5. Changing passphrase only works for top-level roles.
+	// 1.5. Changing passphrase works for top-level and delegated roles.
 	r, err := NewRepo(store)
 	c.Assert(err, IsNil)
 
-	c.Assert(r.ChangePassphrase("foo"), DeepEquals, ErrInvalidRole{"foo", "only support passphrases for top-level roles"})
+	c.Assert(r.ChangePassphrase("targets"), NotNil)
+	c.Assert(r.ChangePassphrase("foo"), NotNil)
 
 	// 2. Test changing the passphrase when the keys file does not exist - should FAIL
 	c.Assert(store.(PassphraseChanger).ChangePassphrase("root"), NotNil)
@@ -1506,6 +1514,8 @@ func (rs *RepoSuite) TestCustomTargetMetadata(c *C) {
 	r, err := NewRepo(local)
 	c.Assert(err, IsNil)
 
+	generateAndAddPrivateKey(c, r, "targets")
+
 	custom := json.RawMessage(`{"foo":"bar"}`)
 	assertCustomMeta := func(file string, custom *json.RawMessage) {
 		t, err := r.topLevelTargets()
@@ -1553,7 +1563,7 @@ func (rs *RepoSuite) TestUnknownKeyIDs(c *C) {
 	c.Assert(root.Version, Equals, int64(1))
 
 	root.Keys["unknown-key-id"] = signer.PublicData()
-	r.setTopLevelMeta("root.json", root)
+	r.setMeta("root.json", root)
 
 	// commit the metadata to the store.
 	c.Assert(r.AddTargets([]string{}, nil), IsNil)
@@ -1692,7 +1702,9 @@ func (rs *RepoSuite) TestAddOrUpdateSignatures(c *C) {
 	// generate signatures externally and append
 	rootMeta, err := r.SignedMeta("root.json")
 	c.Assert(err, IsNil)
-	rootSig, err := rootKey.SignMessage(rootMeta.Signed)
+	rootCanonical, err := cjson.EncodeCanonical(rootMeta.Signed)
+	c.Assert(err, IsNil)
+	rootSig, err := rootKey.SignMessage(rootCanonical)
 	c.Assert(err, IsNil)
 	for _, id := range rootKey.PublicData().IDs() {
 		c.Assert(r.AddOrUpdateSignature("root.json", data.Signature{
@@ -1704,7 +1716,9 @@ func (rs *RepoSuite) TestAddOrUpdateSignatures(c *C) {
 	c.Assert(r.AddTarget("foo.txt", nil), IsNil)
 	targetsMeta, err := r.SignedMeta("targets.json")
 	c.Assert(err, IsNil)
-	targetsSig, err := targetsKey.SignMessage(targetsMeta.Signed)
+	targetsCanonical, err := cjson.EncodeCanonical(targetsMeta.Signed)
+	c.Assert(err, IsNil)
+	targetsSig, err := targetsKey.SignMessage(targetsCanonical)
 	c.Assert(err, IsNil)
 	for _, id := range targetsKey.PublicData().IDs() {
 		r.AddOrUpdateSignature("targets.json", data.Signature{
@@ -1716,7 +1730,9 @@ func (rs *RepoSuite) TestAddOrUpdateSignatures(c *C) {
 	c.Assert(r.Snapshot(), IsNil)
 	snapshotMeta, err := r.SignedMeta("snapshot.json")
 	c.Assert(err, IsNil)
-	snapshotSig, err := snapshotKey.SignMessage(snapshotMeta.Signed)
+	snapshotCanonical, err := cjson.EncodeCanonical(snapshotMeta.Signed)
+	c.Assert(err, IsNil)
+	snapshotSig, err := snapshotKey.SignMessage(snapshotCanonical)
 	c.Assert(err, IsNil)
 	for _, id := range snapshotKey.PublicData().IDs() {
 		r.AddOrUpdateSignature("snapshot.json", data.Signature{
@@ -1727,7 +1743,9 @@ func (rs *RepoSuite) TestAddOrUpdateSignatures(c *C) {
 	c.Assert(r.Timestamp(), IsNil)
 	timestampMeta, err := r.SignedMeta("timestamp.json")
 	c.Assert(err, IsNil)
-	timestampSig, err := timestampKey.SignMessage(timestampMeta.Signed)
+	timestampCanonical, err := cjson.EncodeCanonical(timestampMeta.Signed)
+	c.Assert(err, IsNil)
+	timestampSig, err := timestampKey.SignMessage(timestampCanonical)
 	c.Assert(err, IsNil)
 	for _, id := range timestampKey.PublicData().IDs() {
 		r.AddOrUpdateSignature("timestamp.json", data.Signature{
@@ -1750,7 +1768,7 @@ func (rs *RepoSuite) TestBadAddOrUpdateSignatures(c *C) {
 
 	c.Assert(r.AddOrUpdateSignature("targets.json", data.Signature{
 		KeyID:     "foo",
-		Signature: nil}), Equals, ErrInvalidRole{"targets", "role missing from top-level keys"})
+		Signature: nil}), Equals, ErrInvalidRole{"targets", "role is not in verifier DB"})
 
 	// generate root key offline and add as a verification key
 	rootKey, err := keys.GenerateEd25519Key()
@@ -1769,12 +1787,14 @@ func (rs *RepoSuite) TestBadAddOrUpdateSignatures(c *C) {
 	// add a signature with a bad role
 	rootMeta, err := r.SignedMeta("root.json")
 	c.Assert(err, IsNil)
-	rootSig, err := rootKey.Sign(rand.Reader, rootMeta.Signed, crypto.Hash(0))
+	rootCanonical, err := cjson.EncodeCanonical(rootMeta.Signed)
+	c.Assert(err, IsNil)
+	rootSig, err := rootKey.Sign(rand.Reader, rootCanonical, crypto.Hash(0))
 	c.Assert(err, IsNil)
 	for _, id := range rootKey.PublicData().IDs() {
 		c.Assert(r.AddOrUpdateSignature("invalid_root.json", data.Signature{
 			KeyID:     id,
-			Signature: rootSig}), Equals, ErrInvalidRole{"invalid_root", "only signing top-level metadata supported"})
+			Signature: rootSig}), Equals, ErrInvalidRole{"invalid_root", "no trusted keys for role"})
 	}
 
 	// add a root signature with an key ID that is for the targets role
@@ -1855,5 +1875,672 @@ func (rs *RepoSuite) TestSignDigest(c *C) {
 	c.Assert(err, IsNil)
 	c.Assert(targets.Targets["sha256:bc11b176a293bb341a0f2d0d226f52e7fcebd186a7c4dfca5fc64f305f06b94c"].FileMeta.Length, Equals, size)
 	c.Assert(targets.Targets["sha256:bc11b176a293bb341a0f2d0d226f52e7fcebd186a7c4dfca5fc64f305f06b94c"].FileMeta.Hashes["sha256"], DeepEquals, hex_digest_bytes)
+}
+
+func concat(ss ...[]string) []string {
+	ret := []string{}
+	for _, s := range ss {
+		ret = append(ret, s...)
+	}
+	return ret
+}
+
+func checkSigKeyIDs(c *C, local LocalStore, fileToKeyIDs map[string][]string) {
+	metas, err := local.GetMeta()
+	c.Assert(err, IsNil)
+
+	for f, keyIDs := range fileToKeyIDs {
+		meta, ok := metas[f]
+		c.Assert(ok, Equals, true, Commentf("meta file: %v", f))
+
+		s := &data.Signed{}
+		err = json.Unmarshal(meta, s)
+		c.Assert(err, IsNil)
+
+		gotKeyIDs := []string{}
+		for _, sig := range s.Signatures {
+			gotKeyIDs = append(gotKeyIDs, sig.KeyID)
+		}
+		gotKeyIDs = sets.DeduplicateStrings(gotKeyIDs)
+		sort.Strings(gotKeyIDs)
+
+		sort.Strings(keyIDs)
+		c.Assert(gotKeyIDs, DeepEquals, keyIDs)
+	}
+}
+
+func (rs *RepoSuite) TestDelegations(c *C) {
+	tmp := newTmpDir(c)
+	local := FileSystemStore(tmp.path, nil)
+	r, err := NewRepo(local)
+	c.Assert(err, IsNil)
+
+	// Add one key to each role
+	genKey(c, r, "root")
+	targetsKeyIDs := genKey(c, r, "targets")
+	genKey(c, r, "snapshot")
+	genKey(c, r, "timestamp")
+
+	// commit the metadata to the store.
+	c.Assert(r.AddTargets([]string{}, nil), IsNil)
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	snapshot, err := r.snapshot()
+	c.Assert(err, IsNil)
+	c.Assert(snapshot.Meta, HasLen, 1)
+	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(1))
+
+	checkSigKeyIDs(c, local, map[string][]string{
+		"1.targets.json": targetsKeyIDs,
+	})
+
+	saveNewKey := func(role string) keys.Signer {
+		key, err := keys.GenerateEd25519Key()
+		c.Assert(err, IsNil)
+
+		err = local.SaveSigner(role, key)
+		c.Assert(err, IsNil)
+
+		return key
+	}
+
+	// Delegate from targets -> role1 for A/*, B/* with one key, threshold 1.
+	role1ABKey := saveNewKey("role1")
+	role1AB := data.DelegatedRole{
+		Name:      "role1",
+		KeyIDs:    role1ABKey.PublicData().IDs(),
+		Paths:     []string{"A/*", "B/*"},
+		Threshold: 1,
+	}
+	err = r.AddDelegatedRole("targets", role1AB, []*data.PublicKey{
+		role1ABKey.PublicData(),
+	})
+	c.Assert(err, IsNil)
+
+	// Adding duplicate delegation should return an error.
+	err = r.AddDelegatedRole("targets", role1AB, []*data.PublicKey{
+		role1ABKey.PublicData(),
+	})
+	c.Assert(err, NotNil)
+
+	// Delegate from targets -> role2 for C/*, D/* with three key, threshold 2.
+	role2CDKey1 := saveNewKey("role2")
+	role2CDKey2 := saveNewKey("role2")
+	role2CDKey3 := saveNewKey("role2")
+	role2CD := data.DelegatedRole{
+		Name: "role2",
+		KeyIDs: concat(
+			role2CDKey1.PublicData().IDs(),
+			role2CDKey2.PublicData().IDs(),
+			role2CDKey3.PublicData().IDs(),
+		),
+		Paths:     []string{"C/*", "D/*"},
+		Threshold: 2,
+	}
+	err = r.AddDelegatedRole("targets", role2CD, []*data.PublicKey{
+		role2CDKey1.PublicData(),
+		role2CDKey2.PublicData(),
+		role2CDKey3.PublicData(),
+	})
+	c.Assert(err, IsNil)
+
+	// Delegate from role1 -> role2 for A/allium.txt with one key, threshold 1.
+	role1To2Key := saveNewKey("role2")
+	role1To2 := data.DelegatedRole{
+		Name:        "role2",
+		KeyIDs:      role1To2Key.PublicData().IDs(),
+		Paths:       []string{"A/allium.txt"},
+		Threshold:   1,
+		Terminating: true,
+	}
+	err = r.AddDelegatedRole("role1", role1To2, []*data.PublicKey{
+		role1To2Key.PublicData(),
+	})
+	c.Assert(err, IsNil)
+
+	checkDelegations := func(delegator string, delegatedRoles ...data.DelegatedRole) {
+		t, err := r.targets(delegator)
+		c.Assert(err, IsNil)
+
+		// Check that delegated roles are copied verbatim.
+		c.Assert(t.Delegations.Roles, DeepEquals, delegatedRoles)
+
+		// Check that public keys match key IDs in roles.
+		expectedKeyIDs := []string{}
+		for _, dr := range delegatedRoles {
+			expectedKeyIDs = append(expectedKeyIDs, dr.KeyIDs...)
+		}
+		expectedKeyIDs = sets.DeduplicateStrings(expectedKeyIDs)
+		sort.Strings(expectedKeyIDs)
+
+		gotKeyIDs := []string{}
+		for _, k := range t.Delegations.Keys {
+			gotKeyIDs = append(gotKeyIDs, k.IDs()...)
+		}
+		gotKeyIDs = sets.DeduplicateStrings(gotKeyIDs)
+		sort.Strings(gotKeyIDs)
+
+		c.Assert(gotKeyIDs, DeepEquals, expectedKeyIDs)
+	}
+
+	checkDelegations("targets", role1AB, role2CD)
+	checkDelegations("role1", role1To2)
+
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	snapshot, err = r.snapshot()
+	c.Assert(err, IsNil)
+	c.Assert(snapshot.Meta, HasLen, 3)
+	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(2))
+	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(1))
+	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(1))
+
+	checkSigKeyIDs(c, local, map[string][]string{
+		"2.targets.json": targetsKeyIDs,
+		"1.role1.json":   role1ABKey.PublicData().IDs(),
+		"1.role2.json": concat(
+			role2CDKey1.PublicData().IDs(),
+			role2CDKey2.PublicData().IDs(),
+			role2CDKey3.PublicData().IDs(),
+			role1To2Key.PublicData().IDs(),
+		),
+	})
+
+	// Add a variety of targets.
+	files := map[string]string{
+		// targets.json
+		"potato.txt": "potatoes can be starchy or waxy",
+		// role1.json
+		"A/apple.txt":  "apples are sometimes red",
+		"B/banana.txt": "bananas are yellow and sometimes brown",
+		// role2.json
+		"C/clementine.txt": "clementines are a citrus fruit",
+		"D/durian.txt":     "durians are spiky",
+		"A/allium.txt":     "alliums include garlic and leeks",
+	}
+	for name, content := range files {
+		tmp.writeStagedTarget(name, content)
+		c.Assert(r.AddTarget(name, nil), IsNil)
+	}
+
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	snapshot, err = r.snapshot()
+	c.Assert(err, IsNil)
+	c.Assert(snapshot.Meta, HasLen, 3)
+	// All roles should have new targets.
+	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
+	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(2))
+	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(2))
+
+	checkSigKeyIDs(c, local, map[string][]string{
+		"3.targets.json": targetsKeyIDs,
+		"2.role1.json":   role1ABKey.PublicData().IDs(),
+		"2.role2.json": concat(
+			role2CDKey1.PublicData().IDs(),
+			role2CDKey2.PublicData().IDs(),
+			role2CDKey3.PublicData().IDs(),
+			role1To2Key.PublicData().IDs(),
+		),
+	})
+
+	// Check that the given targets role has signed for the given filenames, with
+	// the correct file metadata.
+	checkTargets := func(role string, filenames ...string) {
+		t, err := r.targets(role)
+		c.Assert(err, IsNil)
+		c.Assert(t.Targets, HasLen, len(filenames))
+
+		for _, fn := range filenames {
+			content := files[fn]
+
+			fm, err := util.GenerateTargetFileMeta(strings.NewReader(content))
+			c.Assert(err, IsNil)
+
+			c.Assert(util.TargetFileMetaEqual(t.Targets[fn], fm), IsNil)
+		}
+	}
+
+	checkTargets("targets", "potato.txt")
+	checkTargets("role1", "A/apple.txt", "B/banana.txt")
+	checkTargets("role2", "C/clementine.txt", "D/durian.txt", "A/allium.txt")
+
+	// Test AddTargetToPreferredRole.
+	// role2 is the default signer for A/allium.txt, but role1 is also eligible
+	// for A/*.txt according to the delegation from the top-level targets role.
+	c.Assert(r.RemoveTarget("A/allium.txt"), IsNil)
+	tmp.writeStagedTarget("A/allium.txt", files["A/allium.txt"])
+	c.Assert(r.AddTargetToPreferredRole("A/allium.txt", nil, "role1"), IsNil)
+
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	snapshot, err = r.snapshot()
+	c.Assert(err, IsNil)
+	c.Assert(snapshot.Meta, HasLen, 3)
+	// Only role1 and role2 should have bumped versions.
+	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
+	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(3))
+	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(3))
+
+	checkSigKeyIDs(c, local, map[string][]string{
+		"3.targets.json": targetsKeyIDs,
+		"3.role1.json":   role1ABKey.PublicData().IDs(),
+		"3.role2.json": concat(
+			role2CDKey1.PublicData().IDs(),
+			role2CDKey2.PublicData().IDs(),
+			role2CDKey3.PublicData().IDs(),
+			role1To2Key.PublicData().IDs(),
+		),
+	})
+
+	// role1 now signs A/allium.txt.
+	checkTargets("targets", "potato.txt")
+	checkTargets("role1", "A/apple.txt", "B/banana.txt", "A/allium.txt")
+	checkTargets("role2", "C/clementine.txt", "D/durian.txt")
+
+	// Remove the delegation from role1 to role2.
+	c.Assert(r.ResetTargetsDelegations("role1"), IsNil)
+	checkDelegations("targets", role1AB, role2CD)
+	checkDelegations("role1")
+
+	// Try to sign A/allium.txt with role2.
+	// It should fail since we removed the role1 -> role2 delegation.
+	c.Assert(r.RemoveTarget("A/allium.txt"), IsNil)
+	tmp.writeStagedTarget("A/allium.txt", files["A/allium.txt"])
+	c.Assert(r.AddTargetToPreferredRole("A/allium.txt", nil, "role2"), Equals, ErrNoDelegatedTarget{Path: "A/allium.txt"})
+
+	// Try to sign A/allium.txt with the default role (role1).
+	c.Assert(r.AddTarget("A/allium.txt", nil), IsNil)
+
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	snapshot, err = r.snapshot()
+	c.Assert(err, IsNil)
+	c.Assert(snapshot.Meta, HasLen, 3)
+	// Only role1 should have a bumped version.
+	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
+	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(4))
+	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(3))
+
+	checkSigKeyIDs(c, local, map[string][]string{
+		"3.targets.json": targetsKeyIDs,
+		"4.role1.json":   role1ABKey.PublicData().IDs(),
+		"3.role2.json": concat(
+			// Metadata (and therefore signers) for role2.json shouldn't have
+			// changed, even though we revoked role1To2Key. Clients verify the
+			// signature using keys specified by 4.role1.json, so role1To2Key
+			// shouldn't contribute to the threshold.
+			role2CDKey1.PublicData().IDs(),
+			role2CDKey2.PublicData().IDs(),
+			role2CDKey3.PublicData().IDs(),
+			role1To2Key.PublicData().IDs(),
+		),
+	})
+
+	// Re-sign target signed by role2 to test that role1To2Key is not used going
+	// forward.
+	c.Assert(r.RemoveTarget("C/clementine.txt"), IsNil)
+	tmp.writeStagedTarget("C/clementine.txt", files["C/clementine.txt"])
+	c.Assert(r.AddTarget("C/clementine.txt", nil), IsNil)
+
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	snapshot, err = r.snapshot()
+	c.Assert(err, IsNil)
+	c.Assert(snapshot.Meta, HasLen, 3)
+	// Only role2 should have a bumped version.
+	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
+	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(4))
+	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(4))
+
+	checkSigKeyIDs(c, local, map[string][]string{
+		"3.targets.json": targetsKeyIDs,
+		"4.role1.json":   role1ABKey.PublicData().IDs(),
+		"4.role2.json": concat(
+			role2CDKey1.PublicData().IDs(),
+			role2CDKey2.PublicData().IDs(),
+			role2CDKey3.PublicData().IDs(),
+			// Note that role1To2Key no longer signs since the role1 -> role2
+			// delegation was removed.
+		),
+	})
+
+	// Targets should still be signed by the same roles.
+	checkTargets("targets", "potato.txt")
+	checkTargets("role1", "A/apple.txt", "B/banana.txt", "A/allium.txt")
+	checkTargets("role2", "C/clementine.txt", "D/durian.txt")
+
+	// Add back the role1 -> role2 delegation, and verify that it doesn't change
+	// existing targets in role2.json.
+	err = r.AddDelegatedRole("role1", role1To2, []*data.PublicKey{
+		role1To2Key.PublicData(),
+	})
+	c.Assert(err, IsNil)
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	snapshot, err = r.snapshot()
+	c.Assert(err, IsNil)
+	c.Assert(snapshot.Meta, HasLen, 3)
+	// Both role1 and role2 should have a bumped version.
+	// role1 is bumped because the delegations changed.
+	// role2 is only bumped because its expiration is bumped.
+	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
+	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(5))
+	c.Assert(snapshot.Meta["role2.json"].Version, Equals, int64(5))
+
+	checkTargets("targets", "potato.txt")
+	checkTargets("role1", "A/apple.txt", "B/banana.txt", "A/allium.txt")
+	checkTargets("role2", "C/clementine.txt", "D/durian.txt")
+}
+
+func (rs *RepoSuite) TestHashBinDelegations(c *C) {
+	tmp := newTmpDir(c)
+	local := FileSystemStore(tmp.path, nil)
+	r, err := NewRepo(local)
+	c.Assert(err, IsNil)
+
+	// Add one key to each role
+	genKey(c, r, "root")
+	targetsKeyIDs := genKey(c, r, "targets")
+	genKey(c, r, "snapshot")
+	genKey(c, r, "timestamp")
+
+	hb, err := targets.NewHashBins("bins_", 3)
+	if err != nil {
+		c.Assert(err, IsNil)
+	}
+
+	// Generate key for the intermediate bins role.
+	binsKey, err := keys.GenerateEd25519Key()
+	c.Assert(err, IsNil)
+	err = local.SaveSigner("bins", binsKey)
+	c.Assert(err, IsNil)
+
+	// Generate key for the leaf bins role.
+	leafKey, err := keys.GenerateEd25519Key()
+	c.Assert(err, IsNil)
+	for i := uint64(0); i < hb.NumBins(); i++ {
+		b := hb.GetBin(i)
+		err = local.SaveSigner(b.RoleName(), leafKey)
+		if err != nil {
+			c.Assert(err, IsNil)
+		}
+	}
+
+	err = r.AddDelegatedRole("targets", data.DelegatedRole{
+		Name:      "bins",
+		KeyIDs:    binsKey.PublicData().IDs(),
+		Paths:     []string{"*.txt"},
+		Threshold: 1,
+	}, []*data.PublicKey{
+		binsKey.PublicData(),
+	})
+	c.Assert(err, IsNil)
+
+	err = r.AddDelegatedRolesForPathHashBins("bins", hb, []*data.PublicKey{leafKey.PublicData()}, 1)
+	c.Assert(err, IsNil)
+	targets, err := r.targets("bins")
+	c.Assert(err, IsNil)
+	c.Assert(targets.Delegations.Roles, HasLen, 8)
+
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	tmp.writeStagedTarget("foo.txt", "foo")
+	err = r.AddTarget("foo.txt", nil)
+	c.Assert(err, IsNil)
+
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	snapshot, err := r.snapshot()
+	c.Assert(err, IsNil)
+	// 1 targets.json, 1 bins.json, 8 bins_*.json.
+	c.Assert(snapshot.Meta, HasLen, 10)
+	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(1))
+	c.Assert(snapshot.Meta["bins.json"].Version, Equals, int64(1))
+	c.Assert(snapshot.Meta["bins_0-1.json"].Version, Equals, int64(1))
+	c.Assert(snapshot.Meta["bins_2-3.json"].Version, Equals, int64(1))
+	c.Assert(snapshot.Meta["bins_4-5.json"].Version, Equals, int64(1))
+	c.Assert(snapshot.Meta["bins_6-7.json"].Version, Equals, int64(1))
+	c.Assert(snapshot.Meta["bins_8-9.json"].Version, Equals, int64(1))
+	c.Assert(snapshot.Meta["bins_a-b.json"].Version, Equals, int64(1))
+	c.Assert(snapshot.Meta["bins_c-d.json"].Version, Equals, int64(2))
+	c.Assert(snapshot.Meta["bins_e-f.json"].Version, Equals, int64(1))
+
+	targets, err = r.targets("bins_c-d")
+	c.Assert(err, IsNil)
+	c.Assert(targets.Targets, HasLen, 1)
+
+	checkSigKeyIDs(c, local, map[string][]string{
+		"targets.json":    targetsKeyIDs,
+		"1.bins.json":     binsKey.PublicData().IDs(),
+		"1.bins_0-1.json": leafKey.PublicData().IDs(),
+		"1.bins_2-3.json": leafKey.PublicData().IDs(),
+		"1.bins_4-5.json": leafKey.PublicData().IDs(),
+		"1.bins_6-7.json": leafKey.PublicData().IDs(),
+		"1.bins_8-9.json": leafKey.PublicData().IDs(),
+		"1.bins_a-b.json": leafKey.PublicData().IDs(),
+		"1.bins_c-d.json": leafKey.PublicData().IDs(),
+		"2.bins_c-d.json": leafKey.PublicData().IDs(),
+		"1.bins_e-f.json": leafKey.PublicData().IDs(),
+	})
+}
+
+func (rs *RepoSuite) TestResetTargetsDelegationsWithExpires(c *C) {
+	tmp := newTmpDir(c)
+	local := FileSystemStore(tmp.path, nil)
+	r, err := NewRepo(local)
+	c.Assert(err, IsNil)
+
+	// Add one key to each role
+	genKey(c, r, "root")
+	targetsKeyIDs := genKey(c, r, "targets")
+	genKey(c, r, "snapshot")
+	genKey(c, r, "timestamp")
+
+	// commit the metadata to the store.
+	c.Assert(r.AddTargets([]string{}, nil), IsNil)
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	snapshot, err := r.snapshot()
+	c.Assert(err, IsNil)
+	c.Assert(snapshot.Meta, HasLen, 1)
+	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(1))
 
+	checkSigKeyIDs(c, local, map[string][]string{
+		"1.targets.json": targetsKeyIDs,
+	})
+
+	role1Key, err := keys.GenerateEd25519Key()
+	c.Assert(err, IsNil)
+
+	err = local.SaveSigner("role1", role1Key)
+	c.Assert(err, IsNil)
+
+	// Delegate from targets -> role1 for A/*, B/* with one key, threshold 1.
+	role1 := data.DelegatedRole{
+		Name:      "role1",
+		KeyIDs:    role1Key.PublicData().IDs(),
+		Paths:     []string{"A/*", "B/*"},
+		Threshold: 1,
+	}
+	err = r.AddDelegatedRole("targets", role1, []*data.PublicKey{
+		role1Key.PublicData(),
+	})
+	c.Assert(err, IsNil)
+
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	snapshot, err = r.snapshot()
+	c.Assert(err, IsNil)
+	c.Assert(snapshot.Meta, HasLen, 2)
+	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(2))
+	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(1))
+
+	checkSigKeyIDs(c, local, map[string][]string{
+		"1.targets.json": targetsKeyIDs,
+		"targets.json":   targetsKeyIDs,
+		"1.role1.json":   role1Key.PublicData().IDs(),
+		"role1.json":     role1Key.PublicData().IDs(),
+	})
+
+	c.Assert(r.ResetTargetsDelegations("targets"), IsNil)
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+
+	snapshot, err = r.snapshot()
+	c.Assert(err, IsNil)
+	c.Assert(snapshot.Meta, HasLen, 2)
+	c.Assert(snapshot.Meta["targets.json"].Version, Equals, int64(3))
+	c.Assert(snapshot.Meta["role1.json"].Version, Equals, int64(1))
+
+	checkSigKeyIDs(c, local, map[string][]string{
+		"2.targets.json": targetsKeyIDs,
+		"targets.json":   targetsKeyIDs,
+		"1.role1.json":   role1Key.PublicData().IDs(),
+		"role1.json":     role1Key.PublicData().IDs(),
+	})
+}
+
+func (rs *RepoSuite) TestSignWithDelegations(c *C) {
+	tmp := newTmpDir(c)
+	local := FileSystemStore(tmp.path, nil)
+	r, err := NewRepo(local)
+	c.Assert(err, IsNil)
+
+	// Add one key to each role
+	genKey(c, r, "root")
+	genKey(c, r, "targets")
+	genKey(c, r, "snapshot")
+	genKey(c, r, "timestamp")
+
+	role1Key, err := keys.GenerateEd25519Key()
+	c.Assert(err, IsNil)
+
+	role1 := data.DelegatedRole{
+		Name:      "role1",
+		KeyIDs:    role1Key.PublicData().IDs(),
+		Paths:     []string{"A/*", "B/*"},
+		Threshold: 1,
+	}
+	err = r.AddDelegatedRole("targets", role1, []*data.PublicKey{
+		role1Key.PublicData(),
+	})
+	c.Assert(err, IsNil)
+
+	// targets.json should be signed, but role1.json is not signed because there
+	// is no key in the local store.
+	m, err := local.GetMeta()
+	c.Assert(err, IsNil)
+	targetsMeta := &data.Signed{}
+	c.Assert(json.Unmarshal(m["targets.json"], targetsMeta), IsNil)
+	c.Assert(len(targetsMeta.Signatures), Equals, 1)
+	role1Meta := &data.Signed{}
+	c.Assert(json.Unmarshal(m["role1.json"], role1Meta), IsNil)
+	c.Assert(len(role1Meta.Signatures), Equals, 0)
+
+	c.Assert(r.Snapshot(), DeepEquals, ErrInsufficientSignatures{"role1.json", verify.ErrNoSignatures})
+
+	// Sign role1.json.
+	c.Assert(local.SaveSigner("role1", role1Key), IsNil)
+	c.Assert(r.Sign("role1.json"), IsNil)
+
+	m, err = local.GetMeta()
+	c.Assert(err, IsNil)
+	targetsMeta = &data.Signed{}
+	c.Assert(json.Unmarshal(m["targets.json"], targetsMeta), IsNil)
+	c.Assert(len(targetsMeta.Signatures), Equals, 1)
+	role1Meta = &data.Signed{}
+	c.Assert(json.Unmarshal(m["role1.json"], role1Meta), IsNil)
+	c.Assert(len(role1Meta.Signatures), Equals, 1)
+
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
+}
+
+func (rs *RepoSuite) TestAddOrUpdateSignatureWithDelegations(c *C) {
+	tmp := newTmpDir(c)
+	local := FileSystemStore(tmp.path, nil)
+	r, err := NewRepo(local)
+	c.Assert(err, IsNil)
+
+	// Add one key to each role
+	genKey(c, r, "root")
+	genKey(c, r, "targets")
+	genKey(c, r, "snapshot")
+	genKey(c, r, "timestamp")
+
+	role1Key, err := keys.GenerateEd25519Key()
+	c.Assert(err, IsNil)
+
+	role1 := data.DelegatedRole{
+		Name:      "role1",
+		KeyIDs:    role1Key.PublicData().IDs(),
+		Paths:     []string{"A/*", "B/*"},
+		Threshold: 1,
+	}
+	err = r.AddDelegatedRole("targets", role1, []*data.PublicKey{
+		role1Key.PublicData(),
+	})
+	c.Assert(err, IsNil)
+
+	// targets.json should be signed, but role1.json is not signed because there
+	// is no key in the local store.
+	m, err := local.GetMeta()
+	c.Assert(err, IsNil)
+	targetsMeta := &data.Signed{}
+	c.Assert(json.Unmarshal(m["targets.json"], targetsMeta), IsNil)
+	c.Assert(len(targetsMeta.Signatures), Equals, 1)
+	role1Meta := &data.Signed{}
+	c.Assert(json.Unmarshal(m["role1.json"], role1Meta), IsNil)
+	c.Assert(len(role1Meta.Signatures), Equals, 0)
+
+	c.Assert(r.Snapshot(), DeepEquals, ErrInsufficientSignatures{"role1.json", verify.ErrNoSignatures})
+
+	// Sign role1.json.
+	canonical, err := cjson.EncodeCanonical(role1Meta.Signed)
+	c.Assert(err, IsNil)
+	sig, err := role1Key.SignMessage(canonical)
+	c.Assert(err, IsNil)
+	err = r.AddOrUpdateSignature("role1.json", data.Signature{
+		KeyID:     role1Key.PublicData().IDs()[0],
+		Signature: sig,
+	})
+	c.Assert(err, IsNil)
+
+	m, err = local.GetMeta()
+	c.Assert(err, IsNil)
+	targetsMeta = &data.Signed{}
+	c.Assert(json.Unmarshal(m["targets.json"], targetsMeta), IsNil)
+	c.Assert(len(targetsMeta.Signatures), Equals, 1)
+	role1Meta = &data.Signed{}
+	c.Assert(json.Unmarshal(m["role1.json"], role1Meta), IsNil)
+	c.Assert(len(role1Meta.Signatures), Equals, 1)
+
+	c.Assert(r.Snapshot(), IsNil)
+	c.Assert(r.Timestamp(), IsNil)
+	c.Assert(r.Commit(), IsNil)
 }