Repository: theupdateframework/go-tuf
Pull request #267 (2022-04-12 13:25:59)

chore(deps): bump actions/setup-python from 2.3.2 to 3.1.2
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.3.2 to 3.1.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/actions/setup-python/releases">actions/setup-python's releases</a>.</em></p>
<blockquote>
<h2>Update actions/cache version to 2.0.2</h2>
<p>In scope of this release we updated <code>actions/cache</code> package as the new version contains fixes related to GHES 3.5 (<a href="https://github-redirect.dependabot.com/actions/setup-python/pull/382">actions/setup-python#382</a>)</p>
<h2>Add &quot;cache-hit&quot; output and fix &quot;python-version&quot; output for PyPy</h2>
<p>This release introduces new output cache-hit (<a href="https://github-redirect.dependabot.com/actions/setup-python/pull/373">actions/setup-python#373</a>) and fix python-version output for PyPy (<a href="https://github-redirect.dependabot.com/actions/setup-python/pull/365">actions/setup-python#365</a>)</p>
<p>The cache-hit output contains boolean value indicating that an exact match was found for the key. It shows that the action uses already existing cache or not. The output is available only if cache is enabled.</p>
<p>The python-version contains version of Python or PyPy.</p>
<h2>Support caching poetry dependencies and caching on GHES 3.5</h2>
<ul>
<li>In the scope of this release, we added <a href="https://github-redirect.dependabot.com/actions/setup-python/issues/362">support for caching from GHES 3.5</a> and fixed the download issue for files &gt; 2GB during restore.</li>
<li>Caching poetry dependencies</li>
</ul>
<pre lang="yaml"><code>steps:
- uses: actions/checkout@v3
- name: Install poetry
  run: pipx install poetry
- uses: actions/setup-python@v3
  with:
    python-version: '3.9'
    cache: 'poetry'
- run: poetry install
- run: poetry run pytest
</code></pre>
<h2>v3.0.0</h2>
<h2>What's Changed</h2>
<ul>
<li>Update default runtime to node16 (<a href="https://github-redirect.dependabot.com/actions/setup-python/pull/340">actions/setup-python#340</a>)</li>
<li>Update <code>package-lock.json</code> file version to 2, <code>@types/node</code> to 16.11.25 and <code>typescript</code> to 4.2.3 (<a href="https://github-redirect.dependabot.com/actions/setup-python/pull/341">actions/setup-python#341</a>)</li>
<li>Remove legacy <code>pypy2</code> and <code>pypy3</code> keywords (<a href="https://github-redirect.dependabot.com/actions/setup-python/pull/342">actions/setup-python#342</a>)</li>
</ul>
<h3>Breaking Changes</h3>
<p>With the update to Node 16, all scripts will now be run with Node 16 rather than Node 12.</p>
<p>This new major release removes support of legacy <code>pypy2</code> and <code>pypy3</code> keywords. Please use more specific and flexible syntax to specify a PyPy version:</p>
<pre lang="yaml"><code>jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version:
        - 'pypy-2.7' # the latest available version of PyPy that supports Python 2.7
        - 'pypy-3.8' # the latest available version of PyPy that supports Python 3.8
        - 'pypy-3.8-v7.3.8' # Python 3.8 and PyPy 7.3.8
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-python@v3
      with:
        python-version: ${{ matrix.python-version }}
&lt;/tr&gt;&lt;/table&gt; 
</code></pre>
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/actions/setup-python/commit/98f2ad02fd48d057ee3b4d4f66525b231c3e52b6"><code>98f2ad0</code></a> Updated <code>@​actions/cache</code> (<a href="https://github-redirect.dependabot.com/actions/setup-python/issues/382">#382</a>)</li>
<li><a href="https://github.com/actions/setup-python/commit/5d6f0c8a87d930c1f9308457abe4c4568399410a"><code>5d6f0c8</code></a> ci(workflow): add 'npm' cache for actions/setup-node in .github/workflows (<a href="https://github-redirect.dependabot.com/actions/setup-python/issues/379">#379</a>)</li>
<li><a href="https://github.com/actions/setup-python/commit/21c0493ecfd34b1217f0a90ec19a327f3cc0a048"><code>21c0493</code></a> Cache hit output (<a href="https://github-redirect.dependabot.com/actions/setup-python/issues/373">#373</a>)</li>
<li><a href="https://github.com/actions/setup-python/commit/7933d5a3dd7112211f44c3c6d4c1156a64d3f5bf"><code>7933d5a</code></a> Add pyton-version to setup PyPy output (<a href="https://github-redirect.dependabot.com/actions/setup-python/issues/365">#365</a>)</li>
<li><a href="https://github.com/actions/setup-python/commit/7885ec3539f8a6278aa15a514b195c3b3e10dd32"><code>7885ec3</code></a> Rework pipenv caching test (<a href="https://github-redirect.dependabot.com/actions/setup-python/issues/375">#375</a>)</li>
<li><a href="https://github.com/actions/setup-python/commit/9c644ca2ab8e57ea0a487b5ec2f8290740378bfd"><code>9c644ca</code></a> Update README.md to fix setup-python version  in example (<a href="https://github-redirect.dependabot.com/actions/setup-python/issues/368">#368</a>)</li>
<li><a href="https://github.com/actions/setup-python/commit/3e8e90edf01accdf7b76addef61eac60c478e3a7"><code>3e8e90e</code></a> dist fix (<a href="https://github-redirect.dependabot.com/actions/setup-python/issues/367">#367</a>)</li>
<li><a href="https://github.com/actions/setup-python/commit/05fb98de9ae200fbc898ddcaa011ef774ac3837f"><code>05fb98d</code></a> Cache on ghes (<a href="https://github-redirect.dependabot.com/actions/setup-python/issues/363">#363</a>)</li>
<li><a href="https://github.com/actions/setup-python/commit/6c566026c0404efac87e650f7de19f11a9406300"><code>6c56602</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/actions/setup-python/issues/281">#281</a> from patrick91/feature/poetry-caching</li>
<li><a href="https://github.com/actions/setup-python/commit/9516be869fd78eb4feec5395859f8dd36d3c8b75"><code>9516be8</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/actions/setup-python/issues/358">#358</a> from actions/brcrista/codeql-main</li>
<li>Additional commits viewable in <a href="https://github.com/actions/setup-python/compare/7f80679172b057fc5e90d70d197929d454754a5a...98f2ad02fd48d057ee3b4d4f66525b231c3e52b6">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/setup-python&package-manager=github_actions&previous-version=2.3.2&new-version=3.1.2)](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: @dependabot rebase
asraa: @theupdateframework/go-tuf-maintainers PTAL this is ready

Patch:
diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml
new file mode 100644
index 0000000..b2e9929
--- /dev/null
+++ b/.github/workflows/changelog.yml
@@ -0,0 +1,18 @@
+name: "Changelog checks"
+
+on:
+  pull_request_target:
+    types:
+      - opened
+      - edited
+      - synchronize
+
+jobs:
+  conventional-commits-lint-check:
+    name: "Lint PR title"
+    runs-on: "ubuntu-latest"
+    steps:
+      - name:
+        uses: amannn/action-semantic-pull-request@bc0a635f0c6bdf5af06a87cdb20ac66d121c58a4
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 212efcd..056a925 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -38,11 +38,11 @@ jobs:
 
     steps:
     - name: Checkout repository
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
 
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@v1
+      uses: github/codeql-action/init@v2
       with:
         languages: ${{ matrix.language }}
         # If you wish to specify custom queries, you can do so here or in a config file.
@@ -53,7 +53,7 @@ jobs:
     # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
     # If this step fails, then you should remove it and run the build manually (see below)
     - name: Autobuild
-      uses: github/codeql-action/autobuild@v1
+      uses: github/codeql-action/autobuild@v2
 
     # ℹ️ Command-line programs to run using the OS shell.
     # 📚 https://git.io/JvXDl
@@ -67,4 +67,4 @@ jobs:
     #   make release
 
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@v1
+      uses: github/codeql-action/analyze@v2
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/client.go b/client/client.go
index 893e161..bf22041 100644
--- a/client/client.go
+++ b/client/client.go
@@ -69,10 +69,10 @@ type Client struct {
 
 	// The following four fields represent the versions of metatdata either
 	// from local storage or from recently downloaded metadata
-	rootVer      int
-	targetsVer   int
-	snapshotVer  int
-	timestampVer int
+	rootVer      int64
+	targetsVer   int64
+	snapshotVer  int64
+	timestampVer int64
 
 	// targets is the list of available targets, either from local storage
 	// or from recently downloaded targets metadata
@@ -612,7 +612,7 @@ func (c *Client) downloadTarget(file string, get remoteGetFunc, hashes data.Hash
 
 // downloadVersionedMeta downloads top-level metadata from remote storage and
 // verifies it using the given file metadata.
-func (c *Client) downloadMeta(name string, version int, m data.FileMeta) ([]byte, error) {
+func (c *Client) downloadMeta(name string, version int64, m data.FileMeta) ([]byte, error) {
 	r, size, err := func() (io.ReadCloser, int64, error) {
 		if c.consistentSnapshot {
 			path := util.VersionedPath(name, version)
diff --git a/client/errors.go b/client/errors.go
index 4806ba4..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 (
@@ -42,27 +40,13 @@ func (e ErrDecodeFailed) Error() string {
 type ErrMaxDelegations struct {
 	Target          string
 	MaxDelegations  int
-	SnapshotVersion int
+	SnapshotVersion int64
 }
 
 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
 }
@@ -87,7 +71,7 @@ func (e ErrWrongSize) Error() string {
 }
 
 type ErrLatestSnapshot struct {
-	Version int
+	Version int64
 }
 
 func (e ErrLatestSnapshot) Error() string {
@@ -101,7 +85,7 @@ func IsLatestSnapshot(err error) bool {
 
 type ErrUnknownTarget struct {
 	Name            string
-	SnapshotVersion int
+	SnapshotVersion int64
 }
 
 func (e ErrUnknownTarget) Error() string {
@@ -128,7 +112,7 @@ func (e ErrInvalidURL) Error() string {
 
 type ErrRoleNotInSnapshot struct {
 	Role            string
-	SnapshotVersion int
+	SnapshotVersion int64
 }
 
 func (e ErrRoleNotInSnapshot) Error() string {
diff --git a/data/types.go b/data/types.go
index db60c16..6ec2fc3 100644
--- a/data/types.go
+++ b/data/types.go
@@ -96,7 +96,7 @@ func DefaultExpires(role string) time.Time {
 type Root struct {
 	Type        string                `json:"_type"`
 	SpecVersion string                `json:"spec_version"`
-	Version     int                   `json:"version"`
+	Version     int64                 `json:"version"`
 	Expires     time.Time             `json:"expires"`
 	Keys        map[string]*PublicKey `json:"keys"`
 	Roles       map[string]*Role      `json:"roles"`
@@ -167,7 +167,7 @@ func (f FileMeta) HashAlgorithms() []string {
 
 type SnapshotFileMeta struct {
 	FileMeta
-	Version int `json:"version"`
+	Version int64 `json:"version"`
 }
 
 type SnapshotFiles map[string]SnapshotFileMeta
@@ -175,7 +175,7 @@ type SnapshotFiles map[string]SnapshotFileMeta
 type Snapshot struct {
 	Type        string           `json:"_type"`
 	SpecVersion string           `json:"spec_version"`
-	Version     int              `json:"version"`
+	Version     int64            `json:"version"`
 	Expires     time.Time        `json:"expires"`
 	Meta        SnapshotFiles    `json:"meta"`
 	Custom      *json.RawMessage `json:"custom,omitempty"`
@@ -203,7 +203,7 @@ func (f TargetFileMeta) HashAlgorithms() []string {
 type Targets struct {
 	Type        string           `json:"_type"`
 	SpecVersion string           `json:"spec_version"`
-	Version     int              `json:"version"`
+	Version     int64            `json:"version"`
 	Expires     time.Time        `json:"expires"`
 	Targets     TargetFiles      `json:"targets"`
 	Delegations *Delegations     `json:"delegations,omitempty"`
@@ -302,7 +302,7 @@ func NewTargets() *Targets {
 
 type TimestampFileMeta struct {
 	FileMeta
-	Version int `json:"version"`
+	Version int64 `json:"version"`
 }
 
 type TimestampFiles map[string]TimestampFileMeta
@@ -310,7 +310,7 @@ type TimestampFiles map[string]TimestampFileMeta
 type Timestamp struct {
 	Type        string           `json:"_type"`
 	SpecVersion string           `json:"spec_version"`
-	Version     int              `json:"version"`
+	Version     int64            `json:"version"`
 	Expires     time.Time        `json:"expires"`
 	Meta        TimestampFiles   `json:"meta"`
 	Custom      *json.RawMessage `json:"custom,omitempty"`
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 e6257e7..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"
@@ -40,9 +39,11 @@ type LocalStore interface {
 	// This will also reset the staged meta to signal incrementing version numbers.
 	// TUF 1.0 requires that the root metadata version numbers in the repository does not
 	// gaps. To avoid this, we will only increment the number once until we commit.
-	Commit(bool, map[string]int, map[string]data.Hashes) error
+	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.
@@ -125,7 +126,7 @@ func (m *memoryStore) WalkStagedTargets(paths []string, targetsFn TargetsWalkFun
 	return nil
 }
 
-func (m *memoryStore) Commit(consistentSnapshot bool, versions map[string]int, hashes map[string]data.Hashes) error {
+func (m *memoryStore) Commit(consistentSnapshot bool, versions map[string]int64, hashes map[string]data.Hashes) error {
 	for name, meta := range m.stagedMeta {
 		paths := computeMetadataPaths(consistentSnapshot, name, versions)
 		for _, path := range paths {
@@ -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
 	}
 
@@ -369,7 +369,7 @@ func (f *fileSystemStore) createRepoFile(path string) (*os.File, error) {
 	return os.Create(dst)
 }
 
-func (f *fileSystemStore) Commit(consistentSnapshot bool, versions map[string]int, hashes map[string]data.Hashes) error {
+func (f *fileSystemStore) Commit(consistentSnapshot bool, versions map[string]int64, hashes map[string]data.Hashes) error {
 	isTarget := func(path string) bool {
 		return strings.HasPrefix(path, "targets/")
 	}
@@ -700,7 +700,7 @@ func computeTargetPaths(consistentSnapshot bool, name string, hashes map[string]
 	}
 }
 
-func computeMetadataPaths(consistentSnapshot bool, name string, versions map[string]int) []string {
+func computeMetadataPaths(consistentSnapshot bool, name string, versions map[string]int64) []string {
 	copyVersion := false
 
 	switch name {
diff --git a/repo.go b/repo.go
index 53a65a7..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
 }
@@ -143,7 +152,7 @@ func (r *Repo) snapshot() (*data.Snapshot, error) {
 	return snapshot, nil
 }
 
-func (r *Repo) RootVersion() (int, error) {
+func (r *Repo) RootVersion() (int64, error) {
 	root, err := r.root()
 	if err != nil {
 		return -1, err
@@ -152,9 +161,9 @@ func (r *Repo) RootVersion() (int, 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) {
@@ -202,16 +211,16 @@ func (r *Repo) Targets() (data.TargetFiles, error) {
 	return targets.Targets, nil
 }
 
-func (r *Repo) SetTargetsVersion(v int) error {
+func (r *Repo) SetTargetsVersion(v int64) error {
 	t, err := r.topLevelTargets()
 	if err != nil {
 		return err
 	}
 	t.Version = v
-	return r.setTopLevelMeta("targets.json", t)
+	return r.setMeta("targets.json", t)
 }
 
-func (r *Repo) TargetsVersion() (int, error) {
+func (r *Repo) TargetsVersion() (int64, error) {
 	t, err := r.topLevelTargets()
 	if err != nil {
 		return -1, err
@@ -219,16 +228,16 @@ func (r *Repo) TargetsVersion() (int, error) {
 	return t.Version, nil
 }
 
-func (r *Repo) SetTimestampVersion(v int) error {
+func (r *Repo) SetTimestampVersion(v int64) error {
 	ts, err := r.timestamp()
 	if err != nil {
 		return err
 	}
 	ts.Version = v
-	return r.setTopLevelMeta("timestamp.json", ts)
+	return r.setMeta("timestamp.json", ts)
 }
 
-func (r *Repo) TimestampVersion() (int, error) {
+func (r *Repo) TimestampVersion() (int64, error) {
 	ts, err := r.timestamp()
 	if err != nil {
 		return -1, err
@@ -236,17 +245,17 @@ func (r *Repo) TimestampVersion() (int, error) {
 	return ts.Version, nil
 }
 
-func (r *Repo) SetSnapshotVersion(v int) error {
+func (r *Repo) SetSnapshotVersion(v int64) error {
 	s, err := r.snapshot()
 	if err != nil {
 		return err
 	}
 
 	s.Version = v
-	return r.setTopLevelMeta("snapshot.json", s)
+	return r.setMeta("snapshot.json", s)
 }
 
-func (r *Repo) SnapshotVersion() (int, error) {
+func (r *Repo) SnapshotVersion() (int64, error) {
 	s, err := r.snapshot()
 	if err != nil {
 		return -1, err
@@ -255,17 +264,21 @@ func (r *Repo) SnapshotVersion() (int, 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 []byte{}, err
+		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 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
+		}
+
+		dbs = append(dbs, ddbs...)
+	}
+
+	return dbs, nil
+}
+
+func (r *Repo) signersForRole(role string) ([]keys.Signer, error) {
+	dbs, err := r.dbsForRole(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
+	signers := []keys.Signer{}
+	for _, db := range dbs {
+		ss, err := r.getSignersInDB(role, db)
+		if err != nil {
+			return nil, err
+		}
+
+		signers = append(signers, ss...)
 	}
 
-	return out.Bytes(), nil
+	return signers, nil
 }
 
-func (r *Repo) setTopLevelMeta(roleFilename string, meta interface{}) error {
-	keys, err := r.getSortedSigningKeys(strings.TrimSuffix(roleFilename, ".json"))
+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"}
+	}
+
+	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 !roleData.ValidKey(signature.KeyID) {
+	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}
+
+	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 r.writeTargetWithExpires(t, expires)
+	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
+		}
+
+		// 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
 		}
-		path = util.NormalizeTarget(path)
 
-		// if we have custom metadata, set it, otherwise maintain
+		// 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,56 +1309,103 @@ 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)
 	}
 	return err
 }
 
-func (r *Repo) fileVersions() (map[string]int, 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
+func (r *Repo) fileVersions() (map[string]int64, error) {
+	versions := make(map[string]int64)
+
+	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
 	}
-	versions := make(map[string]int)
-	versions["root.json"] = root.Version
-	versions["targets.json"] = targets.Version
-	versions["snapshot.json"] = snapshot.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/util/util.go b/util/util.go
index ac86761..b6bf9cf 100644
--- a/util/util.go
+++ b/util/util.go
@@ -30,8 +30,8 @@ func (e ErrWrongLength) Error() string {
 }
 
 type ErrWrongVersion struct {
-	Expected int
-	Actual   int
+	Expected int64
+	Actual   int64
 }
 
 func (e ErrWrongVersion) Error() string {
@@ -102,7 +102,7 @@ func hashEqual(actual data.Hashes, expected data.Hashes) error {
 	return nil
 }
 
-func versionEqual(actual int, expected int) error {
+func versionEqual(actual int64, expected int64) error {
 	if actual != expected {
 		return ErrWrongVersion{expected, actual}
 	}
@@ -183,10 +183,10 @@ func GenerateFileMeta(r io.Reader, hashAlgorithms ...string) (data.FileMeta, err
 }
 
 type versionedMeta struct {
-	Version int `json:"version"`
+	Version int64 `json:"version"`
 }
 
-func generateVersionedFileMeta(r io.Reader, hashAlgorithms ...string) (data.FileMeta, int, error) {
+func generateVersionedFileMeta(r io.Reader, hashAlgorithms ...string) (data.FileMeta, int64, error) {
 	b, err := ioutil.ReadAll(r)
 	if err != nil {
 		return data.FileMeta{}, 0, err
@@ -253,8 +253,8 @@ func NormalizeTarget(p string) string {
 	return strings.TrimPrefix(path.Join("/", p), "/")
 }
 
-func VersionedPath(p string, version int) string {
-	return path.Join(path.Dir(p), strconv.Itoa(version)+"."+path.Base(p))
+func VersionedPath(p string, version int64) string {
+	return path.Join(path.Dir(p), strconv.FormatInt(version, 10)+"."+path.Base(p))
 }
 
 func HashedPaths(p string, hashes data.Hashes) []string {
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
 	}
diff --git a/verify/errors.go b/verify/errors.go
index c84f216..11dfa14 100644
--- a/verify/errors.go
+++ b/verify/errors.go
@@ -43,8 +43,8 @@ func (e ErrExpired) Error() string {
 }
 
 type ErrLowVersion struct {
-	Actual  int
-	Current int
+	Actual  int64
+	Current int64
 }
 
 func (e ErrLowVersion) Error() string {
@@ -52,8 +52,8 @@ func (e ErrLowVersion) Error() string {
 }
 
 type ErrWrongVersion struct {
-	Given    int
-	Expected int
+	Given    int64
+	Expected int64
 }
 
 func (e ErrWrongVersion) Error() string {
diff --git a/verify/verify.go b/verify/verify.go
index 2586a60..7b6726f 100644
--- a/verify/verify.go
+++ b/verify/verify.go
@@ -13,10 +13,10 @@ import (
 type signedMeta struct {
 	Type    string    `json:"_type"`
 	Expires time.Time `json:"expires"`
-	Version int       `json:"version"`
+	Version int64     `json:"version"`
 }
 
-func (db *DB) VerifyIgnoreExpiredCheck(s *data.Signed, role string, minVersion int) error {
+func (db *DB) VerifyIgnoreExpiredCheck(s *data.Signed, role string, minVersion int64) error {
 	if err := db.VerifySignatures(s, role); err != nil {
 		return err
 	}
@@ -46,7 +46,7 @@ func (db *DB) VerifyIgnoreExpiredCheck(s *data.Signed, role string, minVersion i
 	return nil
 }
 
-func (db *DB) Verify(s *data.Signed, role string, minVersion int) error {
+func (db *DB) Verify(s *data.Signed, role string, minVersion int64) error {
 
 	err := db.VerifyIgnoreExpiredCheck(s, role, minVersion)
 
@@ -124,7 +124,7 @@ func (db *DB) VerifySignatures(s *data.Signed, role string) error {
 	return nil
 }
 
-func (db *DB) Unmarshal(b []byte, v interface{}, role string, minVersion int) error {
+func (db *DB) Unmarshal(b []byte, v interface{}, role string, minVersion int64) error {
 	s := &data.Signed{}
 	if err := json.Unmarshal(b, s); err != nil {
 		return err
@@ -136,7 +136,7 @@ func (db *DB) Unmarshal(b []byte, v interface{}, role string, minVersion int) er
 }
 
 // UnmarshalExpired is exactly like Unmarshal except ignores expired timestamp error.
-func (db *DB) UnmarshalIgnoreExpired(b []byte, v interface{}, role string, minVersion int) error {
+func (db *DB) UnmarshalIgnoreExpired(b []byte, v interface{}, role string, minVersion int64) error {
 	s := &data.Signed{}
 	if err := json.Unmarshal(b, s); err != nil {
 		return err


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index a55d5ae..55b6b10 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
@@ -31,7 +31,7 @@ jobs:
           go-version: ${{ matrix.go-version }}
 
       - name: Setup - Python
-        uses: actions/setup-python@7f80679172b057fc5e90d70d197929d454754a5a
+        uses: actions/setup-python@98f2ad02fd48d057ee3b4d4f66525b231c3e52b6
         with:
           python-version: 3.6
           cache: "pip"
@@ -61,18 +61,9 @@ 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:
           version: v1.45.2
-
-  conventional-commits-lint-check:
-    runs-on: "ubuntu-latest"
-    steps:
-      - name: Checkout code
-        uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579
-        with:
-          fetch-depth: 0
-      - name: Commitsar Action
-        uses: aevea/commitsar@159cec82966ca402a09ae3c185524a5256affa22
+          args: --timeout 3m 
diff --git a/client/client_test.go b/client/client_test.go
index 5ad38b3..85fa57e 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -456,39 +456,39 @@ func (s *ClientSuite) TestUpdateRoots(c *C) {
 	var tests = []struct {
 		fixturePath      string
 		expectedError    error
-		expectedVersions map[string]int
+		expectedVersions map[string]int64
 	}{
 		// Succeeds when there is no root update.
-		{"testdata/Published1Time", nil, map[string]int{"root": 1, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published1Time", nil, map[string]int64{"root": 1, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Succeeds when client only has root.json
-		{"testdata/Published1Time_client_root_only", nil, map[string]int{"root": 1, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published1Time_client_root_only", nil, map[string]int64{"root": 1, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Succeeds updating root from version 1 to version 2.
-		{"testdata/Published2Times_keyrotated", nil, map[string]int{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published2Times_keyrotated", nil, map[string]int64{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Succeeds updating root from version 1 to version 2 when the client's initial root version is expired.
-		{"testdata/Published2Times_keyrotated_initialrootexpired", nil, map[string]int{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published2Times_keyrotated_initialrootexpired", nil, map[string]int64{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Succeeds updating root from version 1 to version 3 when versions 1 and 2 are expired.
-		{"testdata/Published3Times_keyrotated_initialrootsexpired", nil, map[string]int{"root": 3, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published3Times_keyrotated_initialrootsexpired", nil, map[string]int64{"root": 3, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Succeeds updating root from version 2 to version 3.
-		{"testdata/Published3Times_keyrotated_initialrootsexpired_clientversionis2", nil, map[string]int{"root": 3, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published3Times_keyrotated_initialrootsexpired_clientversionis2", nil, map[string]int64{"root": 3, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Fails updating root from version 1 to version 3 when versions 1 and 3 are expired but version 2 is not expired.
-		{"testdata/Published3Times_keyrotated_latestrootexpired", ErrDecodeFailed{File: "root.json", Err: verify.ErrExpired{}}, map[string]int{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
+		{"testdata/Published3Times_keyrotated_latestrootexpired", ErrDecodeFailed{File: "root.json", Err: verify.ErrExpired{}}, map[string]int64{"root": 2, "timestamp": 1, "snapshot": 1, "targets": 1}},
 		// Fails updating root from version 1 to version 2 when old root 1 did not sign off on it (nth root didn't sign off n+1).
-		{"testdata/Published2Times_keyrotated_invalidOldRootSignature", errors.New("tuf: signature verification failed"), map[string]int{}},
+		{"testdata/Published2Times_keyrotated_invalidOldRootSignature", errors.New("tuf: signature verification failed"), map[string]int64{}},
 		// Fails updating root from version 1 to version 2 when the new root 2 did not sign itself (n+1th root didn't sign off n+1)
-		{"testdata/Published2Times_keyrotated_invalidNewRootSignature", errors.New("tuf: signature verification failed"), map[string]int{}},
+		{"testdata/Published2Times_keyrotated_invalidNewRootSignature", errors.New("tuf: signature verification failed"), map[string]int64{}},
 		// Fails updating root to 2.root.json when the value of the version field inside it is 1 (rollback attack prevention).
-		{"testdata/Published1Time_backwardRootVersion", verify.ErrWrongVersion(verify.ErrWrongVersion{Given: 1, Expected: 2}), map[string]int{}},
+		{"testdata/Published1Time_backwardRootVersion", verify.ErrWrongVersion(verify.ErrWrongVersion{Given: 1, Expected: 2}), map[string]int64{}},
 		// Fails updating root to 2.root.json when the value of the version field inside it is 3 (rollforward attack prevention).
-		{"testdata/Published3Times_keyrotated_forwardRootVersion", verify.ErrWrongVersion(verify.ErrWrongVersion{Given: 3, Expected: 2}), map[string]int{}},
+		{"testdata/Published3Times_keyrotated_forwardRootVersion", verify.ErrWrongVersion(verify.ErrWrongVersion{Given: 3, Expected: 2}), map[string]int64{}},
 		// Fails updating when there is no local trusted root.
-		{"testdata/Published1Time_client_no_root", errors.New("tuf: no root keys found in local meta store"), map[string]int{}},
+		{"testdata/Published1Time_client_no_root", errors.New("tuf: no root keys found in local meta store"), map[string]int64{}},
 
 		// snapshot role key rotation increase the snapshot and timestamp.
-		{"testdata/Published2Times_snapshot_keyrotated", nil, map[string]int{"root": 2, "timestamp": 2, "snapshot": 2, "targets": 1}},
+		{"testdata/Published2Times_snapshot_keyrotated", nil, map[string]int64{"root": 2, "timestamp": 2, "snapshot": 2, "targets": 1}},
 		// targets role key rotation increase the snapshot, timestamp, and targets.
-		{"testdata/Published2Times_targets_keyrotated", nil, map[string]int{"root": 2, "timestamp": 2, "snapshot": 2, "targets": 2}},
+		{"testdata/Published2Times_targets_keyrotated", nil, map[string]int64{"root": 2, "timestamp": 2, "snapshot": 2, "targets": 2}},
 		// timestamp role key rotation increase the timestamp.
-		{"testdata/Published2Times_timestamp_keyrotated", nil, map[string]int{"root": 2, "timestamp": 2, "snapshot": 1, "targets": 1}},
+		{"testdata/Published2Times_timestamp_keyrotated", nil, map[string]int64{"root": 2, "timestamp": 2, "snapshot": 1, "targets": 1}},
 	}
 
 	for _, test := range tests {
@@ -498,7 +498,7 @@ func (s *ClientSuite) TestUpdateRoots(c *C) {
 			c.Assert(err, IsNil)
 			// Check if the root.json is being saved in non-volatile storage.
 			tufClient.getLocalMeta()
-			versionMethods := map[string]int{"root": tufClient.rootVer,
+			versionMethods := map[string]int64{"root": tufClient.rootVer,
 				"timestamp": tufClient.timestampVer,
 				"snapshot":  tufClient.snapshotVer,
 				"targets":   tufClient.targetsVer}
@@ -800,7 +800,7 @@ func (s *ClientSuite) TestUpdateLocalRootExpired(c *C) {
 	c.Assert(s.repo.Commit(), IsNil)
 	s.syncRemote(c)
 
-	const expectedRootVersion = 3
+	const expectedRootVersion = int64(3)
 
 	// check the update downloads the non expired remote root.json and
 	// restarts itself, thus successfully updating
diff --git a/client/delegations_test.go b/client/delegations_test.go
index fe1d72b..c7303ac 100644
--- a/client/delegations_test.go
+++ b/client/delegations_test.go
@@ -129,7 +129,7 @@ func TestPersistedMeta(t *testing.T) {
 
 	type expectedTargets struct {
 		name    string
-		version int
+		version int64
 	}
 	var persistedTests = []struct {
 		file          string
@@ -241,7 +241,7 @@ func TestPersistedMeta(t *testing.T) {
 	}
 }
 
-func versionOfStoredTargets(name string, store map[string]json.RawMessage) (int, error) {
+func versionOfStoredTargets(name string, store map[string]json.RawMessage) (int64, error) {
 	rawTargets, ok := store[name]
 	if !ok {
 		return 0, nil
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 5e85a8e..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"
@@ -123,28 +124,28 @@ func testNewRepo(c *C, newRepo func(local LocalStore, hashAlgorithms ...string)
 	root, err := r.root()
 	c.Assert(err, IsNil)
 	c.Assert(root.Type, Equals, "root")
-	c.Assert(root.Version, Equals, 1)
+	c.Assert(root.Version, Equals, int64(1))
 	c.Assert(root.Keys, NotNil)
 	c.Assert(root.Keys, HasLen, 0)
 
 	targets, err := r.topLevelTargets()
 	c.Assert(err, IsNil)
 	c.Assert(targets.Type, Equals, "targets")
-	c.Assert(targets.Version, Equals, 1)
+	c.Assert(targets.Version, Equals, int64(1))
 	c.Assert(targets.Targets, NotNil)
 	c.Assert(targets.Targets, HasLen, 0)
 
 	snapshot, err := r.snapshot()
 	c.Assert(err, IsNil)
 	c.Assert(snapshot.Type, Equals, "snapshot")
-	c.Assert(snapshot.Version, Equals, 1)
+	c.Assert(snapshot.Version, Equals, int64(1))
 	c.Assert(snapshot.Meta, NotNil)
 	c.Assert(snapshot.Meta, HasLen, 0)
 
 	timestamp, err := r.timestamp()
 	c.Assert(err, IsNil)
 	c.Assert(timestamp.Type, Equals, "timestamp")
-	c.Assert(timestamp.Version, Equals, 1)
+	c.Assert(timestamp.Version, Equals, int64(1))
 	c.Assert(timestamp.Meta, NotNil)
 	c.Assert(timestamp.Meta, HasLen, 0)
 }
@@ -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)
 }
 
@@ -354,7 +358,7 @@ func (rs *RepoSuite) TestAddPrivateKey(c *C) {
 	// check root metadata is correct
 	root, err := r.root()
 	c.Assert(err, IsNil)
-	c.Assert(root.Version, Equals, 1)
+	c.Assert(root.Version, Equals, int64(1))
 	c.Assert(root.Roles, NotNil)
 	c.Assert(root.Roles, HasLen, 1)
 	rs.assertNumUniqueKeys(c, root, "root", 1)
@@ -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"})
@@ -768,19 +772,19 @@ func (rs *RepoSuite) TestCommitVersions(c *C) {
 	// on initial commit everything should be at version 1.
 	rootVersion, err := r.RootVersion()
 	c.Assert(err, IsNil)
-	c.Assert(rootVersion, Equals, 1)
+	c.Assert(rootVersion, Equals, int64(1))
 
 	targetsVersion, err := r.TargetsVersion()
 	c.Assert(err, IsNil)
-	c.Assert(targetsVersion, Equals, 1)
+	c.Assert(targetsVersion, Equals, int64(1))
 
 	snapshotVersion, err := r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(snapshotVersion, Equals, 1)
+	c.Assert(snapshotVersion, Equals, int64(1))
 
 	timestampVersion, err := r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(timestampVersion, Equals, 1)
+	c.Assert(timestampVersion, Equals, int64(1))
 
 	// taking a snapshot should only increment snapshot and timestamp.
 	c.Assert(r.Snapshot(), IsNil)
@@ -789,19 +793,19 @@ func (rs *RepoSuite) TestCommitVersions(c *C) {
 
 	rootVersion, err = r.RootVersion()
 	c.Assert(err, IsNil)
-	c.Assert(rootVersion, Equals, 1)
+	c.Assert(rootVersion, Equals, int64(1))
 
 	targetsVersion, err = r.TargetsVersion()
 	c.Assert(err, IsNil)
-	c.Assert(targetsVersion, Equals, 1)
+	c.Assert(targetsVersion, Equals, int64(1))
 
 	snapshotVersion, err = r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(snapshotVersion, Equals, 2)
+	c.Assert(snapshotVersion, Equals, int64(2))
 
 	timestampVersion, err = r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(timestampVersion, Equals, 2)
+	c.Assert(timestampVersion, Equals, int64(2))
 
 	// rotating multiple keys should increment the root once.
 	genKey(c, r, "targets")
@@ -813,19 +817,19 @@ func (rs *RepoSuite) TestCommitVersions(c *C) {
 
 	rootVersion, err = r.RootVersion()
 	c.Assert(err, IsNil)
-	c.Assert(rootVersion, Equals, 2)
+	c.Assert(rootVersion, Equals, int64(2))
 
 	targetsVersion, err = r.TargetsVersion()
 	c.Assert(err, IsNil)
-	c.Assert(targetsVersion, Equals, 1)
+	c.Assert(targetsVersion, Equals, int64(1))
 
 	snapshotVersion, err = r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(snapshotVersion, Equals, 3)
+	c.Assert(snapshotVersion, Equals, int64(3))
 
 	timestampVersion, err = r.TimestampVersion()
 	c.Assert(err, IsNil)
-	c.Assert(timestampVersion, Equals, 3)
+	c.Assert(timestampVersion, Equals, int64(3))
 }
 
 type tmpDir struct {
@@ -862,11 +866,11 @@ func (t *tmpDir) assertHashedFilesNotExist(path string, hashes data.Hashes) {
 	}
 }
 
-func (t *tmpDir) assertVersionedFileExist(path string, version int) {
+func (t *tmpDir) assertVersionedFileExist(path string, version int64) {
 	t.assertExists(util.VersionedPath(path, version))
 }
 
-func (t *tmpDir) assertVersionedFileNotExist(path string, version int) {
+func (t *tmpDir) assertVersionedFileNotExist(path string, version int64) {
 	t.assertNotExist(util.VersionedPath(path, version))
 }
 
@@ -1034,9 +1038,9 @@ func (rs *RepoSuite) TestConsistentSnapshot(c *C) {
 
 	versions, err := r.fileVersions()
 	c.Assert(err, IsNil)
-	c.Assert(versions["root.json"], Equals, 1)
-	c.Assert(versions["targets.json"], Equals, 1)
-	c.Assert(versions["snapshot.json"], Equals, 1)
+	c.Assert(versions["root.json"], Equals, int64(1))
+	c.Assert(versions["targets.json"], Equals, int64(1))
+	c.Assert(versions["snapshot.json"], Equals, int64(1))
 
 	hashes, err := r.fileHashes()
 	c.Assert(err, IsNil)
@@ -1072,9 +1076,9 @@ func (rs *RepoSuite) TestConsistentSnapshot(c *C) {
 
 	versions, err = r.fileVersions()
 	c.Assert(err, IsNil)
-	c.Assert(versions["root.json"], Equals, 1)
-	c.Assert(versions["targets.json"], Equals, 2)
-	c.Assert(versions["snapshot.json"], Equals, 2)
+	c.Assert(versions["root.json"], Equals, int64(1))
+	c.Assert(versions["targets.json"], Equals, int64(2))
+	c.Assert(versions["snapshot.json"], Equals, int64(2))
 
 	// Save the old hashes for foo.txt to make sure we can assert it doesn't exist later.
 	fooHashes := hashes["targets/foo.txt"]
@@ -1136,7 +1140,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 
 	root, err := r.root()
 	c.Assert(err, IsNil)
-	c.Assert(root.Version, Equals, 1)
+	c.Assert(root.Version, Equals, int64(1))
 
 	expires := time.Now().Add(24 * time.Hour)
 	_, err = r.GenKeyWithExpires("root", expires)
@@ -1147,7 +1151,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	root, err = r.root()
 	c.Assert(err, IsNil)
 	c.Assert(root.Expires.Unix(), DeepEquals, expires.Round(time.Second).Unix())
-	c.Assert(root.Version, Equals, 2)
+	c.Assert(root.Version, Equals, int64(2))
 
 	expires = time.Now().Add(12 * time.Hour)
 	role, ok := root.Roles["root"]
@@ -1162,7 +1166,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	root, err = r.root()
 	c.Assert(err, IsNil)
 	c.Assert(root.Expires.Unix(), DeepEquals, expires.Round(time.Second).Unix())
-	c.Assert(root.Version, Equals, 3)
+	c.Assert(root.Version, Equals, int64(3))
 
 	expires = time.Now().Add(6 * time.Hour)
 	c.Assert(r.AddTargetWithExpires("foo.txt", nil, expires), IsNil)
@@ -1172,7 +1176,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	targets, err := r.topLevelTargets()
 	c.Assert(err, IsNil)
 	c.Assert(targets.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
-	c.Assert(targets.Version, Equals, 2)
+	c.Assert(targets.Version, Equals, int64(2))
 
 	expires = time.Now().Add(2 * time.Hour)
 	c.Assert(r.RemoveTargetWithExpires("foo.txt", expires), IsNil)
@@ -1182,7 +1186,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	targets, err = r.topLevelTargets()
 	c.Assert(err, IsNil)
 	c.Assert(targets.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
-	c.Assert(targets.Version, Equals, 3)
+	c.Assert(targets.Version, Equals, int64(3))
 
 	expires = time.Now().Add(time.Hour)
 	c.Assert(r.SnapshotWithExpires(expires), IsNil)
@@ -1191,7 +1195,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	snapshot, err := r.snapshot()
 	c.Assert(err, IsNil)
 	c.Assert(snapshot.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
-	c.Assert(snapshot.Version, Equals, 6)
+	c.Assert(snapshot.Version, Equals, int64(6))
 
 	_, snapshotHasRoot := snapshot.Meta["root.json"]
 	c.Assert(snapshotHasRoot, Equals, false)
@@ -1202,7 +1206,7 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	c.Assert(r.Commit(), IsNil)
 	snapshot, err = r.snapshot()
 	c.Assert(err, IsNil)
-	c.Assert(snapshot.Version, Equals, 7)
+	c.Assert(snapshot.Version, Equals, int64(7))
 
 	expires = time.Now().Add(10 * time.Minute)
 	c.Assert(r.TimestampWithExpires(expires), IsNil)
@@ -1210,13 +1214,13 @@ func (rs *RepoSuite) TestExpiresAndVersion(c *C) {
 	timestamp, err := r.timestamp()
 	c.Assert(err, IsNil)
 	c.Assert(timestamp.Expires.Unix(), Equals, expires.Round(time.Second).Unix())
-	c.Assert(timestamp.Version, Equals, 8)
+	c.Assert(timestamp.Version, Equals, int64(8))
 
 	c.Assert(r.Timestamp(), IsNil)
 	c.Assert(r.Commit(), IsNil)
 	timestamp, err = r.timestamp()
 	c.Assert(err, IsNil)
-	c.Assert(timestamp.Version, Equals, 9)
+	c.Assert(timestamp.Version, Equals, int64(9))
 	c.Assert(timestamp.Meta["snapshot.json"].Version, Equals, snapshot.Version)
 }
 
@@ -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()
@@ -1550,10 +1560,10 @@ func (rs *RepoSuite) TestUnknownKeyIDs(c *C) {
 
 	root, err := r.root()
 	c.Assert(err, IsNil)
-	c.Assert(root.Version, Equals, 1)
+	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)
@@ -1574,7 +1584,7 @@ func (rs *RepoSuite) TestUnknownKeyIDs(c *C) {
 		Signatures []data.Signature `json:"signatures"`
 	}
 	c.Assert(json.Unmarshal(rootJSON, &signedRoot), IsNil)
-	c.Assert(signedRoot.Signed.Version, Equals, 1)
+	c.Assert(signedRoot.Signed.Version, Equals, int64(1))
 
 	unknownKey, ok := signedRoot.Signed.Keys["unknown-key-id"]
 	c.Assert(ok, Equals, true)
@@ -1597,7 +1607,7 @@ func (rs *RepoSuite) TestUnknownKeyIDs(c *C) {
 	c.Assert(ok, Equals, true)
 
 	c.Assert(json.Unmarshal(rootJSON, &signedRoot), IsNil)
-	c.Assert(signedRoot.Signed.Version, Equals, 2)
+	c.Assert(signedRoot.Signed.Version, Equals, int64(2))
 
 	unknownKey, ok = signedRoot.Signed.Keys["unknown-key-id"]
 	c.Assert(ok, Equals, true)
@@ -1651,19 +1661,19 @@ func (rs *RepoSuite) TestThreshold(c *C) {
 	// Check versions updated
 	rootVersion, err := r.RootVersion()
 	c.Assert(err, IsNil)
-	c.Assert(rootVersion, Equals, 2)
+	c.Assert(rootVersion, Equals, int64(2))
 
 	targetsVersion, err := r.TargetsVersion()
 	c.Assert(err, IsNil)
-	c.Assert(targetsVersion, Equals, 1)
+	c.Assert(targetsVersion, Equals, int64(1))
 
 	snapshotVersion, err := r.SnapshotVersion()
 	c.Assert(err, IsNil)
-	c.Assert(snapshotVersion, Equals, 2)
+	c.Assert(snapshotVersion, Equals, int64(2))
 
 	timestampVersion, err := r.TimestampVersion()
 	c.Assert(err, IsNil)
-	c.Assert(timestampVersion, Equals, 2)
+	c.Assert(timestampVersion, Equals, int64(2))
 }
 
 func (rs *RepoSuite) TestAddOrUpdateSignatures(c *C) {
@@ -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)
 }
diff --git a/util/util_test.go b/util/util_test.go
index ba924f8..4ee4894 100644
--- a/util/util_test.go
+++ b/util/util_test.go
@@ -113,7 +113,7 @@ func (UtilSuite) TestSnapshotFileMetaEqual(c *C) {
 		err      func(test) error
 	}
 
-	fileMeta := func(version int, length int64, hashes map[string]string) data.SnapshotFileMeta {
+	fileMeta := func(version int64, length int64, hashes map[string]string) data.SnapshotFileMeta {
 		return data.SnapshotFileMeta{
 			FileMeta: data.FileMeta{
 				Length: length,
diff --git a/verify/verify_test.go b/verify/verify_test.go
index 648db32..4d9d379 100644
--- a/verify/verify_test.go
+++ b/verify/verify_test.go
@@ -68,7 +68,7 @@ func (VerifySuite) Test(c *C) {
 		keys  []*data.PublicKey
 		roles map[string]*data.Role
 		s     *data.Signed
-		ver   int
+		ver   int64
 		exp   *time.Time
 		typ   string
 		role  string
@@ -77,7 +77,7 @@ func (VerifySuite) Test(c *C) {
 	}
 
 	expiredTime := time.Now().Add(-time.Hour)
-	minVer := 10
+	minVer := int64(10)
 	tests := []test{
 		{
 			name: "no signatures",
@@ -255,7 +255,7 @@ func (VerifySuite) Test(c *C) {
 }
 
 func (VerifySuite) TestVerifyIgnoreExpired(c *C) {
-	minVer := 10
+	minVer := int64(10)
 	role := "root"
 	k, _ := keys.GenerateEd25519Key()
 	s, _ := sign.Marshal(&signedMeta{Type: role, Version: minVer, Expires: time.Now().Add(-time.Hour)}, k)