Skip to content

Commit

Permalink
Patch support attestation log search and bundle to payload hash check (
Browse files Browse the repository at this point in the history
…#1030)

* Patch support attestation log search and bundle to payload hash check

Signed-off-by: houdini91 <mdstrauss91@gmail.com>

* Fix lint

Signed-off-by: houdini91 <mdstrauss91@gmail.com>

* Typo

Signed-off-by: houdini91 <mdstrauss91@gmail.com>

* PR fix

Signed-off-by: houdini91 <mdstrauss91@gmail.com>

* PR add comment

Signed-off-by: houdini91 <mdstrauss91@gmail.com>

* PR fix lint

Signed-off-by: houdini91 <mdstrauss91@gmail.com>
  • Loading branch information
houdini91 authored Nov 14, 2021
1 parent fe00315 commit 5468ddc
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 8 deletions.
38 changes: 30 additions & 8 deletions pkg/cosign/tlog.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,20 +145,42 @@ func GetTlogEntry(rekorClient *client.Rekor, uuid string) (*models.LogEntryAnon,
return nil, errors.New("empty response")
}

func proposedEntry(b64Sig string, payload, pubKey []byte) ([]models.ProposedEntry, error) {
var proposedEntry []models.ProposedEntry
signature, err := base64.StdEncoding.DecodeString(b64Sig)
if err != nil {
return nil, errors.Wrap(err, "decoding base64 signature")
}

// The fact that there's no signature (or empty rather), implies
// that this is an Attestation that we're verifying.
if len(signature) == 0 {
te := intotoEntry(payload, pubKey)
entry := &models.Intoto{
APIVersion: swag.String(te.APIVersion()),
Spec: te.IntotoObj,
}
proposedEntry = []models.ProposedEntry{entry}
} else {
re := rekorEntry(payload, signature, pubKey)
entry := &models.Rekord{
APIVersion: swag.String(re.APIVersion()),
Spec: re.RekordObj,
}
proposedEntry = []models.ProposedEntry{entry}
}
return proposedEntry, nil
}

func FindTlogEntry(rekorClient *client.Rekor, b64Sig string, payload, pubKey []byte) (uuid string, index int64, err error) {
searchParams := entries.NewSearchLogQueryParams()
searchLogQuery := models.SearchLogQuery{}
signature, err := base64.StdEncoding.DecodeString(b64Sig)
proposedEntry, err := proposedEntry(b64Sig, payload, pubKey)
if err != nil {
return "", 0, errors.Wrap(err, "decoding base64 signature")
}
re := rekorEntry(payload, signature, pubKey)
entry := &models.Rekord{
APIVersion: swag.String(re.APIVersion()),
Spec: re.RekordObj,
return "", 0, err
}

searchLogQuery.SetEntries([]models.ProposedEntry{entry})
searchLogQuery.SetEntries(proposedEntry)

searchParams.SetEntry(&searchLogQuery)
resp, err := rekorClient.Entries.SearchLogQuery(searchParams)
Expand Down
66 changes: 66 additions & 0 deletions pkg/cosign/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"io"
Expand All @@ -37,6 +38,7 @@ import (
ociremote "github.com/sigstore/cosign/pkg/oci/remote"
rekor "github.com/sigstore/rekor/pkg/client"
"github.com/sigstore/rekor/pkg/generated/client"
"github.com/sigstore/rekor/pkg/generated/models"
"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature"
"github.com/sigstore/sigstore/pkg/signature/dsse"
Expand Down Expand Up @@ -426,9 +428,73 @@ func VerifyBundle(sig oci.Signature) (bool, error) {
if err := checkExpiry(cert, time.Unix(bundle.Payload.IntegratedTime, 0)); err != nil {
return false, errors.Wrap(err, "checking expiry on cert")
}

payload, err := sig.Payload()
if err != nil {
return false, errors.Wrap(err, "reading payload")
}
signature, err := sig.Base64Signature()
if err != nil {
return false, errors.Wrap(err, "reading base64signature")
}

alg, bundlehash, err := bundleHash(bundle.Payload.Body.(string), signature)
h := sha256.Sum256(payload)
payloadHash := hex.EncodeToString(h[:])

if alg != "sha256" || bundlehash != payloadHash {
return false, errors.Wrap(err, "matching bundle to payload")
}
return true, nil
}

func bundleHash(bundleBody, signature string) (string, string, error) {
var toto models.Intoto
var rekord models.Rekord
var intotoObj models.IntotoV001Schema
var rekordObj models.RekordV001Schema

bodyDecoded, err := base64.StdEncoding.DecodeString(bundleBody)
if err != nil {
return "", "", err
}

// The fact that there's no signature (or empty rather), implies
// that this is an Attestation that we're verifying.
if len(signature) == 0 {
err = json.Unmarshal(bodyDecoded, &toto)
if err != nil {
return "", "", err
}

specMarshal, err := json.Marshal(toto.Spec)
if err != nil {
return "", "", err
}
err = json.Unmarshal(specMarshal, &intotoObj)
if err != nil {
return "", "", err
}

return *intotoObj.Content.Hash.Algorithm, *intotoObj.Content.Hash.Value, nil
}

err = json.Unmarshal(bodyDecoded, &rekord)
if err != nil {
return "", "", err
}

specMarshal, err := json.Marshal(rekord.Spec)
if err != nil {
return "", "", err
}
err = json.Unmarshal(specMarshal, &rekordObj)
if err != nil {
return "", "", err
}
return *rekordObj.Data.Hash.Algorithm, *rekordObj.Data.Hash.Value, nil
}

func VerifySET(bundlePayload oci.BundlePayload, signature []byte, pub *ecdsa.PublicKey) error {
contents, err := json.Marshal(bundlePayload)
if err != nil {
Expand Down

0 comments on commit 5468ddc

Please sign in to comment.