Repository: sigstore/rekor
Pull request #1601 (2023-07-27 23:10:36)

Refactor Verifiers to return multiple keys
This supports DSSE and intoto types that allow for multiple keys/signatures.

Fixes https://github.com/sigstore/rekor/issues/1278

<!--
Thanks for opening a pull request! Please do not just delete this text.  The three fields below are mandatory.

Please remember to:
- This PR requires an issue. If it is a new feature, the issue should proceed the PR and will have allowed sufficent time for discussions to take place. Please use
issue tags such as "Closes #XYZ" or "Resolves sigstore/repo-name#XYZ".
  [documentation](https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword)
- ensure your commits are signed-off, as sigstore uses the [DCO](https://en.wikipedia.org/wiki/Developer_Certificate_of_Origin) using `git commit -s`, or `git commit -s --amend` if you want to amend already existing commits
- lastly, ensure there are no merge commits!

Thank you :)
-->

#### Summary
<!--
 Explain the **motivation** for making this change. What existing problem does the pull request solve? How can reviewers test this PR?
-->

#### Release Note
<!--
Add a release note for each of the following conditions:

* Config changes (additions, deletions, updates)
* API additions—new endpoint, new response fields, or newly accepted request parameters
* Database changes (any)
* Websocket additions or changes
* Anything noteworthy to an administrator running private sigstore instances (err on the side of over-communicating)
* New features and improvements, including behavioural changes, UI changes and CLI changes
* Bug fixes and fixes of previous known issues
* Deprecation warnings, breaking changes, or compatibility notes

If no release notes are required write NONE. Use past-tense.

-->

#### Documentation
<!--

Does this change require an update to documentation? How will users implement your new feature?

Please reference a PR within https://docs.sigstore.dev

-->


haydentherapper: Only functional change is to return multiple keys for the DSSE and intoto v2 types. Next PR will refactor Identities.
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore) Report
> Merging [#1601](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore) (769a719) into [main](https://app.codecov.io/gh/sigstore/rekor/commit/2bd83dacf5a302da83ab4eaf20ff7ad119cb6c11?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore) (2bd83da) will **decrease** coverage by `19.06%`.
> Report is 4 commits behind head on main.
> The diff coverage is `66.25%`.

```diff
@@             Coverage Diff             @@
##             main    #1601       +/-   ##
===========================================
- Coverage   67.00%   47.94%   -19.06%     
===========================================
  Files          83       75        -8     
  Lines        8389     7827      -562     
===========================================
- Hits         5621     3753     -1868     
- Misses       2092     3711     +1619     
+ Partials      676      363      -313     
```

| Flag | Coverage Δ | |
|---|---|---|
| e2etests | `?` | |
| unittests | `47.94% <66.25%> (+0.20%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Files Changed](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore) | Coverage Δ | |
|---|---|---|
| [pkg/types/dsse/v0.0.1/entry.go](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL3R5cGVzL2Rzc2UvdjAuMC4xL2VudHJ5Lmdv) | `57.34% <0.00%> (-15.06%)` | :arrow_down: |
| [pkg/types/entries.go](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL3R5cGVzL2VudHJpZXMuZ28=) | `4.61% <ø> (-47.70%)` | :arrow_down: |
| [pkg/types/rfc3161/v0.0.1/entry.go](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL3R5cGVzL3JmYzMxNjEvdjAuMC4xL2VudHJ5Lmdv) | `43.75% <0.00%> (-22.23%)` | :arrow_down: |
| [pkg/types/test\_util.go](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL3R5cGVzL3Rlc3RfdXRpbC5nbw==) | `0.00% <0.00%> (ø)` | |
| [pkg/types/hashedrekord/v0.0.1/entry.go](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL3R5cGVzL2hhc2hlZHJla29yZC92MC4wLjEvZW50cnkuZ28=) | `59.79% <50.00%> (-16.53%)` | :arrow_down: |
| [pkg/types/intoto/v0.0.1/entry.go](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL3R5cGVzL2ludG90by92MC4wLjEvZW50cnkuZ28=) | `55.09% <50.00%> (-14.26%)` | :arrow_down: |
| [pkg/types/jar/v0.0.1/entry.go](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL3R5cGVzL2phci92MC4wLjEvZW50cnkuZ28=) | `43.58% <50.00%> (-17.28%)` | :arrow_down: |
| [pkg/types/intoto/v0.0.2/entry.go](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL3R5cGVzL2ludG90by92MC4wLjIvZW50cnkuZ28=) | `53.10% <66.66%> (-14.04%)` | :arrow_down: |
| [pkg/types/rekord/v0.0.1/entry.go](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL3R5cGVzL3Jla29yZC92MC4wLjEvZW50cnkuZ28=) | `56.85% <72.72%> (-12.33%)` | :arrow_down: |
| [pkg/types/alpine/v0.0.1/entry.go](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore#diff-cGtnL3R5cGVzL2FscGluZS92MC4wLjEvZW50cnkuZ28=) | `58.73% <100.00%> (-14.48%)` | :arrow_down: |
| ... and [4 more](https://app.codecov.io/gh/sigstore/rekor/pull/1601?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore) | |

... and [44 files with indirect coverage changes](https://app.codecov.io/gh/sigstore/rekor/pull/1601/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=sigstore)



Patch:
diff --git a/pkg/types/alpine/v0.0.1/entry.go b/pkg/types/alpine/v0.0.1/entry.go
index 98d31da..cd3f20b 100644
--- a/pkg/types/alpine/v0.0.1/entry.go
+++ b/pkg/types/alpine/v0.0.1/entry.go
@@ -351,11 +351,15 @@ func (v V001Entry) CreateFromArtifactProperties(ctx context.Context, props types
 	return &returnVal, nil
 }
 
-func (v V001Entry) Verifier() (pki.PublicKey, error) {
+func (v V001Entry) Verifiers() ([]pki.PublicKey, error) {
 	if v.AlpineModel.PublicKey == nil || v.AlpineModel.PublicKey.Content == nil {
 		return nil, errors.New("alpine v0.0.1 entry not initialized")
 	}
-	return x509.NewPublicKey(bytes.NewReader(*v.AlpineModel.PublicKey.Content))
+	key, err := x509.NewPublicKey(bytes.NewReader(*v.AlpineModel.PublicKey.Content))
+	if err != nil {
+		return nil, err
+	}
+	return []pki.PublicKey{key}, nil
 }
 
 func (v V001Entry) Insertable() (bool, error) {
diff --git a/pkg/types/cose/v0.0.1/entry.go b/pkg/types/cose/v0.0.1/entry.go
index b7c12a9..d5a74b4 100644
--- a/pkg/types/cose/v0.0.1/entry.go
+++ b/pkg/types/cose/v0.0.1/entry.go
@@ -348,11 +348,15 @@ func (v V001Entry) CreateFromArtifactProperties(_ context.Context, props types.A
 	return &returnVal, nil
 }
 
-func (v V001Entry) Verifier() (pki.PublicKey, error) {
+func (v V001Entry) Verifiers() ([]pki.PublicKey, error) {
 	if v.CoseObj.PublicKey == nil {
 		return nil, errors.New("cose v0.0.1 entry not initialized")
 	}
-	return x509.NewPublicKey(bytes.NewReader(*v.CoseObj.PublicKey))
+	key, err := x509.NewPublicKey(bytes.NewReader(*v.CoseObj.PublicKey))
+	if err != nil {
+		return nil, err
+	}
+	return []pki.PublicKey{key}, nil
 }
 
 func (v V001Entry) Insertable() (bool, error) {
diff --git a/pkg/types/dsse/v0.0.1/entry.go b/pkg/types/dsse/v0.0.1/entry.go
index 3cb2ef0..ba41742 100644
--- a/pkg/types/dsse/v0.0.1/entry.go
+++ b/pkg/types/dsse/v0.0.1/entry.go
@@ -403,13 +403,20 @@ func verifyEnvelope(allPubKeyBytes [][]byte, env *dsse.Envelope) (map[string]*x5
 	return verifierBySig, nil
 }
 
-func (v V001Entry) Verifier() (pki.PublicKey, error) {
+func (v V001Entry) Verifiers() ([]pki.PublicKey, error) {
 	if len(v.DSSEObj.Signatures) == 0 {
 		return nil, errors.New("dsse v0.0.1 entry not initialized")
 	}
 
-	//TODO: return multiple pki.PublicKeys; sigstore/rekor issue #1278
-	return x509.NewPublicKey(bytes.NewReader(*v.DSSEObj.Signatures[0].Verifier))
+	var keys []pki.PublicKey
+	for _, s := range v.DSSEObj.Signatures {
+		key, err := x509.NewPublicKey(bytes.NewReader(*s.Verifier))
+		if err != nil {
+			return nil, err
+		}
+		keys = append(keys, key)
+	}
+	return keys, nil
 }
 
 func (v V001Entry) Insertable() (bool, error) {
diff --git a/pkg/types/entries.go b/pkg/types/entries.go
index 9309b4c..3bbf47e 100644
--- a/pkg/types/entries.go
+++ b/pkg/types/entries.go
@@ -37,7 +37,7 @@ type EntryImpl interface {
 	Canonicalize(ctx context.Context) ([]byte, error) // marshal the canonical entry to be put into the tlog
 	Unmarshal(e models.ProposedEntry) error           // unmarshal the abstract entry into the specific struct for this versioned type
 	CreateFromArtifactProperties(context.Context, ArtifactProperties) (models.ProposedEntry, error)
-	Verifier() (pki.PublicKey, error)
+	Verifiers() ([]pki.PublicKey, error)
 	Insertable() (bool, error) // denotes whether the entry that was unmarshalled has the writeOnly fields required to validate and insert into the log
 }
 
diff --git a/pkg/types/hashedrekord/v0.0.1/entry.go b/pkg/types/hashedrekord/v0.0.1/entry.go
index 82f54fe..5fdef02 100644
--- a/pkg/types/hashedrekord/v0.0.1/entry.go
+++ b/pkg/types/hashedrekord/v0.0.1/entry.go
@@ -246,11 +246,15 @@ func (v V001Entry) CreateFromArtifactProperties(_ context.Context, props types.A
 	return &returnVal, nil
 }
 
-func (v V001Entry) Verifier() (pki.PublicKey, error) {
+func (v V001Entry) Verifiers() ([]pki.PublicKey, error) {
 	if v.HashedRekordObj.Signature == nil || v.HashedRekordObj.Signature.PublicKey == nil || v.HashedRekordObj.Signature.PublicKey.Content == nil {
 		return nil, errors.New("hashedrekord v0.0.1 entry not initialized")
 	}
-	return x509.NewPublicKey(bytes.NewReader(v.HashedRekordObj.Signature.PublicKey.Content))
+	key, err := x509.NewPublicKey(bytes.NewReader(v.HashedRekordObj.Signature.PublicKey.Content))
+	if err != nil {
+		return nil, err
+	}
+	return []pki.PublicKey{key}, nil
 }
 
 func (v V001Entry) Insertable() (bool, error) {
diff --git a/pkg/types/helm/v0.0.1/entry.go b/pkg/types/helm/v0.0.1/entry.go
index dfb05c2..9100a7d 100644
--- a/pkg/types/helm/v0.0.1/entry.go
+++ b/pkg/types/helm/v0.0.1/entry.go
@@ -349,11 +349,15 @@ func (v V001Entry) CreateFromArtifactProperties(ctx context.Context, props types
 	return &returnVal, nil
 }
 
-func (v V001Entry) Verifier() (pki.PublicKey, error) {
+func (v V001Entry) Verifiers() ([]pki.PublicKey, error) {
 	if v.HelmObj.PublicKey == nil || v.HelmObj.PublicKey.Content == nil {
 		return nil, errors.New("helm v0.0.1 entry not initialized")
 	}
-	return pgp.NewPublicKey(bytes.NewReader(*v.HelmObj.PublicKey.Content))
+	key, err := pgp.NewPublicKey(bytes.NewReader(*v.HelmObj.PublicKey.Content))
+	if err != nil {
+		return nil, err
+	}
+	return []pki.PublicKey{key}, nil
 }
 
 func (v V001Entry) Insertable() (bool, error) {
diff --git a/pkg/types/intoto/v0.0.1/entry.go b/pkg/types/intoto/v0.0.1/entry.go
index 1018d4c..ceb7371 100644
--- a/pkg/types/intoto/v0.0.1/entry.go
+++ b/pkg/types/intoto/v0.0.1/entry.go
@@ -353,11 +353,15 @@ func (v V001Entry) CreateFromArtifactProperties(_ context.Context, props types.A
 	return &returnVal, nil
 }
 
-func (v V001Entry) Verifier() (pki.PublicKey, error) {
+func (v V001Entry) Verifiers() ([]pki.PublicKey, error) {
 	if v.IntotoObj.PublicKey == nil {
 		return nil, errors.New("intoto v0.0.1 entry not initialized")
 	}
-	return x509.NewPublicKey(bytes.NewReader(*v.IntotoObj.PublicKey))
+	key, err := x509.NewPublicKey(bytes.NewReader(*v.IntotoObj.PublicKey))
+	if err != nil {
+		return nil, err
+	}
+	return []pki.PublicKey{key}, nil
 }
 
 func (v V001Entry) Insertable() (bool, error) {
diff --git a/pkg/types/intoto/v0.0.2/entry.go b/pkg/types/intoto/v0.0.2/entry.go
index 5231eee..69a9b4c 100644
--- a/pkg/types/intoto/v0.0.2/entry.go
+++ b/pkg/types/intoto/v0.0.2/entry.go
@@ -457,7 +457,7 @@ func verifyEnvelope(allPubKeyBytes [][]byte, env *dsse.Envelope) (map[string]*x5
 	return verifierBySig, nil
 }
 
-func (v V002Entry) Verifier() (pki.PublicKey, error) {
+func (v V002Entry) Verifiers() ([]pki.PublicKey, error) {
 	if v.IntotoObj.Content == nil || v.IntotoObj.Content.Envelope == nil {
 		return nil, errors.New("intoto v0.0.2 entry not initialized")
 	}
@@ -467,7 +467,15 @@ func (v V002Entry) Verifier() (pki.PublicKey, error) {
 		return nil, errors.New("no signatures found on intoto entry")
 	}
 
-	return x509.NewPublicKey(bytes.NewReader(*v.IntotoObj.Content.Envelope.Signatures[0].PublicKey))
+	var keys []pki.PublicKey
+	for _, s := range v.IntotoObj.Content.Envelope.Signatures {
+		key, err := x509.NewPublicKey(bytes.NewReader(*s.PublicKey))
+		if err != nil {
+			return nil, err
+		}
+		keys = append(keys, key)
+	}
+	return keys, nil
 }
 
 func (v V002Entry) Insertable() (bool, error) {
diff --git a/pkg/types/jar/v0.0.1/entry.go b/pkg/types/jar/v0.0.1/entry.go
index 60faa25..01fc6ac 100644
--- a/pkg/types/jar/v0.0.1/entry.go
+++ b/pkg/types/jar/v0.0.1/entry.go
@@ -338,11 +338,15 @@ func (v *V001Entry) CreateFromArtifactProperties(ctx context.Context, props type
 	return &returnVal, nil
 }
 
-func (v V001Entry) Verifier() (pki.PublicKey, error) {
+func (v V001Entry) Verifiers() ([]pki.PublicKey, error) {
 	if v.JARModel.Signature == nil || v.JARModel.Signature.PublicKey == nil || v.JARModel.Signature.PublicKey.Content == nil {
 		return nil, errors.New("jar v0.0.1 entry not initialized")
 	}
-	return x509.NewPublicKey(bytes.NewReader(*v.JARModel.Signature.PublicKey.Content))
+	key, err := x509.NewPublicKey(bytes.NewReader(*v.JARModel.Signature.PublicKey.Content))
+	if err != nil {
+		return nil, err
+	}
+	return []pki.PublicKey{key}, nil
 }
 
 func (v V001Entry) Insertable() (bool, error) {
diff --git a/pkg/types/rekord/v0.0.1/entry.go b/pkg/types/rekord/v0.0.1/entry.go
index dd124e1..da0af23 100644
--- a/pkg/types/rekord/v0.0.1/entry.go
+++ b/pkg/types/rekord/v0.0.1/entry.go
@@ -425,23 +425,29 @@ func (v V001Entry) CreateFromArtifactProperties(ctx context.Context, props types
 	return &returnVal, nil
 }
 
-func (v V001Entry) Verifier() (pki.PublicKey, error) {
+func (v V001Entry) Verifiers() ([]pki.PublicKey, error) {
 	if v.RekordObj.Signature == nil || v.RekordObj.Signature.PublicKey == nil || v.RekordObj.Signature.PublicKey.Content == nil {
 		return nil, errors.New("rekord v0.0.1 entry not initialized")
 	}
 
+	var key pki.PublicKey
+	var err error
 	switch f := *v.RekordObj.Signature.Format; f {
 	case "x509":
-		return x509.NewPublicKey(bytes.NewReader(*v.RekordObj.Signature.PublicKey.Content))
+		key, err = x509.NewPublicKey(bytes.NewReader(*v.RekordObj.Signature.PublicKey.Content))
 	case "ssh":
-		return ssh.NewPublicKey(bytes.NewReader(*v.RekordObj.Signature.PublicKey.Content))
+		key, err = ssh.NewPublicKey(bytes.NewReader(*v.RekordObj.Signature.PublicKey.Content))
 	case "pgp":
-		return pgp.NewPublicKey(bytes.NewReader(*v.RekordObj.Signature.PublicKey.Content))
+		key, err = pgp.NewPublicKey(bytes.NewReader(*v.RekordObj.Signature.PublicKey.Content))
 	case "minisign":
-		return minisign.NewPublicKey(bytes.NewReader(*v.RekordObj.Signature.PublicKey.Content))
+		key, err = minisign.NewPublicKey(bytes.NewReader(*v.RekordObj.Signature.PublicKey.Content))
 	default:
 		return nil, fmt.Errorf("unexpected format of public key: %s", f)
 	}
+	if err != nil {
+		return nil, err
+	}
+	return []pki.PublicKey{key}, nil
 }
 
 func (v V001Entry) Insertable() (bool, error) {
diff --git a/pkg/types/rfc3161/v0.0.1/entry.go b/pkg/types/rfc3161/v0.0.1/entry.go
index 35a21e0..9a6c049 100644
--- a/pkg/types/rfc3161/v0.0.1/entry.go
+++ b/pkg/types/rfc3161/v0.0.1/entry.go
@@ -207,8 +207,8 @@ func (v V001Entry) CreateFromArtifactProperties(_ context.Context, props types.A
 	return &returnVal, nil
 }
 
-func (v V001Entry) Verifier() (pki.PublicKey, error) {
-	return nil, errors.New("Verifier() does not support rfc3161 entry type")
+func (v V001Entry) Verifiers() ([]pki.PublicKey, error) {
+	return nil, errors.New("Verifiers() does not support rfc3161 entry type")
 }
 
 func (v V001Entry) Insertable() (bool, error) {
diff --git a/pkg/types/rpm/v0.0.1/entry.go b/pkg/types/rpm/v0.0.1/entry.go
index a10b60c..fd3b91c 100644
--- a/pkg/types/rpm/v0.0.1/entry.go
+++ b/pkg/types/rpm/v0.0.1/entry.go
@@ -371,11 +371,15 @@ func (v V001Entry) CreateFromArtifactProperties(ctx context.Context, props types
 	return &returnVal, nil
 }
 
-func (v V001Entry) Verifier() (pki.PublicKey, error) {
+func (v V001Entry) Verifiers() ([]pki.PublicKey, error) {
 	if v.RPMModel.PublicKey == nil || v.RPMModel.PublicKey.Content == nil {
 		return nil, errors.New("rpm v0.0.1 entry not initialized")
 	}
-	return pgp.NewPublicKey(bytes.NewReader(*v.RPMModel.PublicKey.Content))
+	key, err := pgp.NewPublicKey(bytes.NewReader(*v.RPMModel.PublicKey.Content))
+	if err != nil {
+		return nil, err
+	}
+	return []pki.PublicKey{key}, nil
 }
 
 func (v V001Entry) Insertable() (bool, error) {
diff --git a/pkg/types/tuf/v0.0.1/entry.go b/pkg/types/tuf/v0.0.1/entry.go
index ec471c9..b8413ca 100644
--- a/pkg/types/tuf/v0.0.1/entry.go
+++ b/pkg/types/tuf/v0.0.1/entry.go
@@ -369,7 +369,7 @@ func (v V001Entry) CreateFromArtifactProperties(ctx context.Context, props types
 	return &returnVal, nil
 }
 
-func (v V001Entry) Verifier() (pki.PublicKey, error) {
+func (v V001Entry) Verifiers() ([]pki.PublicKey, error) {
 	if v.TufObj.Root == nil {
 		return nil, errors.New("tuf v0.0.1 entry not initialized")
 	}
@@ -377,7 +377,11 @@ func (v V001Entry) Verifier() (pki.PublicKey, error) {
 	if err != nil {
 		return nil, err
 	}
-	return ptuf.NewPublicKey(bytes.NewReader(keyBytes))
+	key, err := ptuf.NewPublicKey(bytes.NewReader(keyBytes))
+	if err != nil {
+		return nil, err
+	}
+	return []pki.PublicKey{key}, nil
 }
 
 func (v V001Entry) Insertable() (bool, error) {


Test patch:
diff --git a/pkg/types/alpine/alpine_test.go b/pkg/types/alpine/alpine_test.go
index a961968..e0c4240 100644
--- a/pkg/types/alpine/alpine_test.go
+++ b/pkg/types/alpine/alpine_test.go
@@ -43,7 +43,7 @@ func (u UnmarshalFailsTester) Unmarshal(_ models.ProposedEntry) error {
 	return errors.New("error")
 }
 
-func (u UnmarshalFailsTester) Verifier() (pki.PublicKey, error) {
+func (u UnmarshalFailsTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/alpine/v0.0.1/entry_test.go b/pkg/types/alpine/v0.0.1/entry_test.go
index f6c6cc8..03fd600 100644
--- a/pkg/types/alpine/v0.0.1/entry_test.go
+++ b/pkg/types/alpine/v0.0.1/entry_test.go
@@ -179,19 +179,19 @@ func TestCrossFieldValidation(t *testing.T) {
 			}
 		}
 
-		verifier, err := v.Verifier()
+		verifiers, err := v.Verifiers()
 		if tc.expectedVerifierSuccess {
 			if err != nil {
 				t.Errorf("%v: unexpected error, got %v", tc.caseDesc, err)
 			} else {
-				pub, _ := verifier.CanonicalValue()
+				pub, _ := verifiers[0].CanonicalValue()
 				if !reflect.DeepEqual(pub, keyBytes) {
 					t.Errorf("%v: verifier and public keys do not match: %v, %v", tc.caseDesc, string(pub), string(keyBytes))
 				}
 			}
 		} else {
 			if err == nil {
-				s, _ := verifier.CanonicalValue()
+				s, _ := verifiers[0].CanonicalValue()
 				t.Errorf("%v: expected error for %v, got %v", tc.caseDesc, string(s), err)
 			}
 		}
diff --git a/pkg/types/cose/cose_test.go b/pkg/types/cose/cose_test.go
index 080253a..237e232 100644
--- a/pkg/types/cose/cose_test.go
+++ b/pkg/types/cose/cose_test.go
@@ -44,7 +44,7 @@ func (u UnmarshalFailsTester) Unmarshal(_ models.ProposedEntry) error {
 	return errors.New("error")
 }
 
-func (u UnmarshalFailsTester) Verifier() (pki.PublicKey, error) {
+func (u UnmarshalFailsTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/cose/v0.0.1/entry_test.go b/pkg/types/cose/v0.0.1/entry_test.go
index 34af5cf..0aed90d 100644
--- a/pkg/types/cose/v0.0.1/entry_test.go
+++ b/pkg/types/cose/v0.0.1/entry_test.go
@@ -278,10 +278,10 @@ func TestV001Entry_Unmarshal(t *testing.T) {
 				}
 			}
 
-			verifier, err := v.Verifier()
+			verifiers, err := v.Verifiers()
 			if !tt.wantVerifierErr {
 				if err != nil {
-					s, _ := verifier.CanonicalValue()
+					s, _ := verifiers[0].CanonicalValue()
 					t.Errorf("%v: unexpected error for %v, got %v", tt.name, string(s), err)
 				}
 
@@ -305,12 +305,12 @@ func TestV001Entry_Unmarshal(t *testing.T) {
 					}
 				}
 
-				pubV, _ := verifier.CanonicalValue()
+				pubV, _ := verifiers[0].CanonicalValue()
 				if !reflect.DeepEqual(pubV, pub) && !reflect.DeepEqual(pubV, pemBytes) {
 					t.Errorf("verifier and public keys do not match: %v, %v", string(pubV), string(pub))
 				}
 			} else if err == nil {
-				s, _ := verifier.CanonicalValue()
+				s, _ := verifiers[0].CanonicalValue()
 				t.Errorf("%v: expected error for %v, got %v", tt.name, string(s), err)
 			}
 		})
diff --git a/pkg/types/dsse/dsse_test.go b/pkg/types/dsse/dsse_test.go
index c8579b4..d81aa16 100644
--- a/pkg/types/dsse/dsse_test.go
+++ b/pkg/types/dsse/dsse_test.go
@@ -44,7 +44,7 @@ func (u UnmarshalFailsTester) Unmarshal(_ models.ProposedEntry) error {
 	return errors.New("error")
 }
 
-func (u UnmarshalFailsTester) Verifier() (pki.PublicKey, error) {
+func (u UnmarshalFailsTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/hashedrekord/hashedrekord_test.go b/pkg/types/hashedrekord/hashedrekord_test.go
index e033954..aeb2975 100644
--- a/pkg/types/hashedrekord/hashedrekord_test.go
+++ b/pkg/types/hashedrekord/hashedrekord_test.go
@@ -43,7 +43,7 @@ func (u UnmarshalFailsTester) Unmarshal(_ models.ProposedEntry) error {
 	return errors.New("error")
 }
 
-func (u UnmarshalFailsTester) Verifier() (pki.PublicKey, error) {
+func (u UnmarshalFailsTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/hashedrekord/v0.0.1/entry_test.go b/pkg/types/hashedrekord/v0.0.1/entry_test.go
index ba9a528..6c9fb2f 100644
--- a/pkg/types/hashedrekord/v0.0.1/entry_test.go
+++ b/pkg/types/hashedrekord/v0.0.1/entry_test.go
@@ -315,12 +315,12 @@ func TestCrossFieldValidation(t *testing.T) {
 			}
 		}
 
-		verifier, err := v.Verifier()
+		verifiers, err := v.Verifiers()
 		if tc.expectedVerifierSuccess {
 			if err != nil {
 				t.Errorf("%v: unexpected error, got %v", tc.caseDesc, err)
 			} else {
-				pub, _ := verifier.CanonicalValue()
+				pub, _ := verifiers[0].CanonicalValue()
 				// invalidKeyBytes is a valid ed25519 key
 				if !reflect.DeepEqual(pub, keyBytes) && !reflect.DeepEqual(pub, invalidKeyBytes) {
 					t.Errorf("verifier and public keys do not match: %v, %v", string(pub), string(keyBytes))
@@ -328,7 +328,7 @@ func TestCrossFieldValidation(t *testing.T) {
 			}
 		} else {
 			if err == nil {
-				s, _ := verifier.CanonicalValue()
+				s, _ := verifiers[0].CanonicalValue()
 				t.Errorf("%v: expected error for %v, got %v", tc.caseDesc, string(s), err)
 			}
 		}
diff --git a/pkg/types/helm/helm_test.go b/pkg/types/helm/helm_test.go
index db9d7a7..f3e17a6 100644
--- a/pkg/types/helm/helm_test.go
+++ b/pkg/types/helm/helm_test.go
@@ -43,7 +43,7 @@ func (u UnmarshalFailsTester) Unmarshal(_ models.ProposedEntry) error {
 	return errors.New("error")
 }
 
-func (u UnmarshalFailsTester) Verifier() (pki.PublicKey, error) {
+func (u UnmarshalFailsTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/helm/v0.0.1/entry_test.go b/pkg/types/helm/v0.0.1/entry_test.go
index 36a4cf3..d9f79eb 100644
--- a/pkg/types/helm/v0.0.1/entry_test.go
+++ b/pkg/types/helm/v0.0.1/entry_test.go
@@ -211,20 +211,20 @@ func TestCrossFieldValidation(t *testing.T) {
 				}
 			}
 
-			verifier, err := v.Verifier()
+			verifiers, err := v.Verifiers()
 			if tc.expectedVerifierSuccess {
 				if err != nil {
 					t.Errorf("%v: unexpected error, got %v", tc.caseDesc, err)
 				} else {
 					// TODO: Improve this test once CanonicalValue returns same result as input for PGP keys
-					_, err := verifier.CanonicalValue()
+					_, err := verifiers[0].CanonicalValue()
 					if err != nil {
 						t.Errorf("%v: unexpected error getting canonical value, got %v", tc.caseDesc, err)
 					}
 				}
 			} else {
 				if err == nil {
-					s, _ := verifier.CanonicalValue()
+					s, _ := verifiers[0].CanonicalValue()
 					t.Errorf("%v: expected error for %v, got %v", tc.caseDesc, string(s), err)
 				}
 			}
diff --git a/pkg/types/intoto/intoto_test.go b/pkg/types/intoto/intoto_test.go
index af4c90f..782e50f 100644
--- a/pkg/types/intoto/intoto_test.go
+++ b/pkg/types/intoto/intoto_test.go
@@ -43,7 +43,7 @@ func (u UnmarshalFailsTester) Unmarshal(_ models.ProposedEntry) error {
 	return errors.New("error")
 }
 
-func (u UnmarshalFailsTester) Verifier() (pki.PublicKey, error) {
+func (u UnmarshalFailsTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/intoto/v0.0.1/entry_test.go b/pkg/types/intoto/v0.0.1/entry_test.go
index 9a6b2ee..23eb549 100644
--- a/pkg/types/intoto/v0.0.1/entry_test.go
+++ b/pkg/types/intoto/v0.0.1/entry_test.go
@@ -336,19 +336,19 @@ func TestV001Entry_Unmarshal(t *testing.T) {
 					t.Errorf("index keys from hydrated object do not match those generated from canonicalized (and re-hydrated) object: %v %v", got, canonicalIndexKeys)
 				}
 
-				verifier, err := v.Verifier()
+				verifiers, err := v.Verifiers()
 				if !tt.wantVerifierErr {
 					if err != nil {
 						t.Errorf("%v: unexpected error, got %v", tt.name, err)
 					} else {
-						pubV, _ := verifier.CanonicalValue()
+						pubV, _ := verifiers[0].CanonicalValue()
 						if !reflect.DeepEqual(pubV, pub) && !reflect.DeepEqual(pubV, pemBytes) {
 							t.Errorf("verifier and public keys do not match: %v, %v", string(pubV), string(pub))
 						}
 					}
 				} else {
 					if err == nil {
-						s, _ := verifier.CanonicalValue()
+						s, _ := verifiers[0].CanonicalValue()
 						t.Errorf("%v: expected error for %v, got %v", tt.name, string(s), err)
 					}
 				}
diff --git a/pkg/types/intoto/v0.0.2/entry_test.go b/pkg/types/intoto/v0.0.2/entry_test.go
index 0301468..cde6970 100644
--- a/pkg/types/intoto/v0.0.2/entry_test.go
+++ b/pkg/types/intoto/v0.0.2/entry_test.go
@@ -377,19 +377,19 @@ func TestV002Entry_Unmarshal(t *testing.T) {
 					t.Errorf("index keys from hydrated object do not match those generated from canonicalized (and re-hydrated) object: %v %v", got, canonicalIndexKeys)
 				}
 
-				verifier, err := v.Verifier()
+				verifiers, err := v.Verifiers()
 				if !tt.wantVerifierErr {
 					if err != nil {
 						t.Errorf("%v: unexpected error, got %v", tt.name, err)
 					} else {
-						pubV, _ := verifier.CanonicalValue()
+						pubV, _ := verifiers[0].CanonicalValue()
 						if !reflect.DeepEqual(pubV, pub) && !reflect.DeepEqual(pubV, pemBytes) {
 							t.Errorf("verifier and public keys do not match: %v, %v", string(pubV), string(pub))
 						}
 					}
 				} else {
 					if err == nil {
-						s, _ := verifier.CanonicalValue()
+						s, _ := verifiers[0].CanonicalValue()
 						t.Errorf("%v: expected error for %v, got %v", tt.name, string(s), err)
 					}
 				}
diff --git a/pkg/types/jar/jar_test.go b/pkg/types/jar/jar_test.go
index 4e43b74..afadab5 100644
--- a/pkg/types/jar/jar_test.go
+++ b/pkg/types/jar/jar_test.go
@@ -42,7 +42,7 @@ func (u UnmarshalFailsTester) Unmarshal(_ models.ProposedEntry) error {
 	return errors.New("error")
 }
 
-func (u UnmarshalFailsTester) Verifier() (pki.PublicKey, error) {
+func (u UnmarshalFailsTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/jar/v0.0.1/entry_test.go b/pkg/types/jar/v0.0.1/entry_test.go
index bb5b54e..9a096b3 100644
--- a/pkg/types/jar/v0.0.1/entry_test.go
+++ b/pkg/types/jar/v0.0.1/entry_test.go
@@ -142,19 +142,19 @@ Hr/+CxFvaJWmpYqNkLDGRU+9orzh5hI2RrcuaQ==
 			}
 		}
 
-		verifier, err := v.Verifier()
+		verifiers, err := v.Verifiers()
 		if tc.expectedVerifierSuccess {
 			if err != nil {
 				t.Errorf("%v: unexpected error, got %v", tc.caseDesc, err)
 			} else {
-				pub, _ := verifier.CanonicalValue()
+				pub, _ := verifiers[0].CanonicalValue()
 				if !reflect.DeepEqual(pub, []byte(certificate)) {
 					t.Errorf("verifier and public keys do not match: %v, %v", string(pub), certificate)
 				}
 			}
 		} else {
 			if err == nil {
-				s, _ := verifier.CanonicalValue()
+				s, _ := verifiers[0].CanonicalValue()
 				t.Errorf("%v: expected error for %v, got %v", tc.caseDesc, string(s), err)
 			}
 		}
diff --git a/pkg/types/rekord/rekord_test.go b/pkg/types/rekord/rekord_test.go
index 7d16941..c4cd059 100644
--- a/pkg/types/rekord/rekord_test.go
+++ b/pkg/types/rekord/rekord_test.go
@@ -43,7 +43,7 @@ func (u UnmarshalFailsTester) Unmarshal(_ models.ProposedEntry) error {
 	return errors.New("error")
 }
 
-func (u UnmarshalFailsTester) Verifier() (pki.PublicKey, error) {
+func (u UnmarshalFailsTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/rekord/v0.0.1/entry_test.go b/pkg/types/rekord/v0.0.1/entry_test.go
index ecca289..e236a50 100644
--- a/pkg/types/rekord/v0.0.1/entry_test.go
+++ b/pkg/types/rekord/v0.0.1/entry_test.go
@@ -258,13 +258,13 @@ func TestCrossFieldValidation(t *testing.T) {
 			}
 		}
 
-		verifier, err := v.Verifier()
+		verifiers, err := v.Verifiers()
 		if tc.expectedVerifierSuccess {
 			if err != nil {
 				t.Errorf("%v: unexpected error, got %v", tc.caseDesc, err)
 			} else {
 				// TODO: Improve this test once CanonicalValue returns same result as input for PGP keys
-				_, err := verifier.CanonicalValue()
+				_, err := verifiers[0].CanonicalValue()
 				if err != nil {
 					t.Errorf("%v: unexpected error getting canonical value, got %v", tc.caseDesc, err)
 				}
@@ -272,7 +272,7 @@ func TestCrossFieldValidation(t *testing.T) {
 
 		} else {
 			if err == nil {
-				s, _ := verifier.CanonicalValue()
+				s, _ := verifiers[0].CanonicalValue()
 				t.Errorf("%v: expected error for %v, got %v", tc.caseDesc, string(s), err)
 			}
 		}
diff --git a/pkg/types/rfc3161/rfc3161_test.go b/pkg/types/rfc3161/rfc3161_test.go
index f9a6b3f..556267e 100644
--- a/pkg/types/rfc3161/rfc3161_test.go
+++ b/pkg/types/rfc3161/rfc3161_test.go
@@ -43,7 +43,7 @@ func (u UnmarshalFailsTester) Unmarshal(_ models.ProposedEntry) error {
 	return errors.New("error")
 }
 
-func (u UnmarshalFailsTester) Verifier() (pki.PublicKey, error) {
+func (u UnmarshalFailsTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/rpm/rpm_test.go b/pkg/types/rpm/rpm_test.go
index d365238..390cf21 100644
--- a/pkg/types/rpm/rpm_test.go
+++ b/pkg/types/rpm/rpm_test.go
@@ -43,7 +43,7 @@ func (u UnmarshalFailsTester) Unmarshal(_ models.ProposedEntry) error {
 	return errors.New("error")
 }
 
-func (u UnmarshalFailsTester) Verifier() (pki.PublicKey, error) {
+func (u UnmarshalFailsTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/rpm/v0.0.1/entry_test.go b/pkg/types/rpm/v0.0.1/entry_test.go
index 941f852..9b1ec7b 100644
--- a/pkg/types/rpm/v0.0.1/entry_test.go
+++ b/pkg/types/rpm/v0.0.1/entry_test.go
@@ -196,20 +196,20 @@ func TestCrossFieldValidation(t *testing.T) {
 			}
 		}
 
-		verifier, err := v.Verifier()
+		verifiers, err := v.Verifiers()
 		if tc.expectVerifierSuccess {
 			if err != nil {
 				t.Errorf("%v: unexpected error, got %v", tc.caseDesc, err)
 			} else {
 				// TODO: Improve this test once CanonicalValue returns same result as input for PGP keys
-				_, err := verifier.CanonicalValue()
+				_, err := verifiers[0].CanonicalValue()
 				if err != nil {
 					t.Errorf("%v: unexpected error getting canonical value, got %v", tc.caseDesc, err)
 				}
 			}
 		} else {
 			if err == nil {
-				s, _ := verifier.CanonicalValue()
+				s, _ := verifiers[0].CanonicalValue()
 				t.Errorf("%v: expected error for %v, got %v", tc.caseDesc, string(s), err)
 			}
 		}
diff --git a/pkg/types/test_util.go b/pkg/types/test_util.go
index 03b5b9c..529d71b 100644
--- a/pkg/types/test_util.go
+++ b/pkg/types/test_util.go
@@ -31,7 +31,7 @@ func (u BaseUnmarshalTester) NewEntry() EntryImpl {
 	return &BaseUnmarshalTester{}
 }
 
-func (u BaseUnmarshalTester) Verifier() (pki.PublicKey, error) {
+func (u BaseUnmarshalTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/tuf/tuf_test.go b/pkg/types/tuf/tuf_test.go
index 16a9fb9..2828819 100644
--- a/pkg/types/tuf/tuf_test.go
+++ b/pkg/types/tuf/tuf_test.go
@@ -39,7 +39,7 @@ func (u UnmarshalFailsTester) NewEntry() types.EntryImpl {
 	return &UnmarshalFailsTester{}
 }
 
-func (u UnmarshalFailsTester) Verifier() (pki.PublicKey, error) {
+func (u UnmarshalFailsTester) Verifiers() ([]pki.PublicKey, error) {
 	return nil, nil
 }
 
diff --git a/pkg/types/tuf/v0.0.1/entry_test.go b/pkg/types/tuf/v0.0.1/entry_test.go
index 4193c4e..d9d05cc 100644
--- a/pkg/types/tuf/v0.0.1/entry_test.go
+++ b/pkg/types/tuf/v0.0.1/entry_test.go
@@ -228,12 +228,12 @@ func TestCrossFieldValidation(t *testing.T) {
 				// Insertable on canonicalized content is variable so we skip testing it here
 			}
 
-			verifier, err := v.Verifier()
+			verifiers, err := v.Verifiers()
 			if tc.expectVerifierSuccess {
 				if err != nil {
 					t.Errorf("%v: unexpected error, got %v", tc.caseDesc, err)
 				} else {
-					pub, _ := verifier.CanonicalValue()
+					pub, _ := verifiers[0].CanonicalValue()
 					rootBytes := new(bytes.Buffer)
 					if err := json.Compact(rootBytes, keyBytes); err != nil {
 						t.Fatal(err)
@@ -244,7 +244,7 @@ func TestCrossFieldValidation(t *testing.T) {
 				}
 			} else {
 				if err == nil {
-					s, _ := verifier.CanonicalValue()
+					s, _ := verifiers[0].CanonicalValue()
 					t.Errorf("%v: expected error for %v, got %v", tc.caseDesc, string(s), err)
 				}
 			}