diff --git a/pkg/rekor/rekor.go b/pkg/rekor/rekor.go index cead30e8..3404ea55 100644 --- a/pkg/rekor/rekor.go +++ b/pkg/rekor/rekor.go @@ -25,7 +25,6 @@ import ( "encoding/pem" "errors" "fmt" - "strings" "github.com/go-openapi/runtime" "github.com/go-openapi/strfmt" @@ -113,14 +112,13 @@ func (c *Client) get(ctx context.Context, data []byte, cert *x509.Certificate) ( h := sha256.New() h.Write(data) hash := hex.EncodeToString(h.Sum(nil)) - fmt.Println("PAYLOAD HASH", hash) pem, err := cryptoutils.MarshalCertificateToPEM(cert) if err != nil { return nil, err } - uuids, err := c.findTLogEntriesByPayloadAndPK(ctx, data, pem) + uuids, err := c.findTLogEntriesByPK(ctx, pem) if err != nil { return nil, err } @@ -139,7 +137,7 @@ func (c *Client) get(ctx context.Context, data []byte, cert *x509.Certificate) ( // Verify that the cert used in the tlog matches the cert // used to sign the data. - tlogCerts, err := extractCerts(e) + tlogCerts, err := extractCertsForHash(e, hash) if err != nil { fmt.Println("could not extract cert", err) continue @@ -154,16 +152,14 @@ func (c *Client) get(ctx context.Context, data []byte, cert *x509.Certificate) ( return nil, errors.New("could not find matching tlog entry") } -// findTLogEntriesByPayloadAndPK is roughly equivalent to cosign.FindTLogEntriesByPayload, -// but also filters by the public key used. -func (c *Client) findTLogEntriesByPayloadAndPK(ctx context.Context, payload, pubKey []byte) (uuids []string, err error) { +// findTLogEntriesByPK is roughly equivalent to cosign.FindTLogEntriesByPayload, +// but only filters by the public key used. Earlier, this filtered on both the +// payload and the public key, but returned uuids of entries that matched +// either. +func (c *Client) findTLogEntriesByPK(ctx context.Context, pubKey []byte) (uuids []string, err error) { params := index.NewSearchIndexParamsWithContext(ctx) params.Query = &models.SearchIndex{} - h := sha256.New() - h.Write(payload) - params.Query.Hash = fmt.Sprintf("sha256:%s", strings.ToLower(hex.EncodeToString(h.Sum(nil)))) - params.Query.PublicKey = &models.SearchIndexPublicKey{ Content: strfmt.Base64(pubKey), Format: swag.String(models.SearchIndexPublicKeyFormatX509), @@ -193,9 +189,10 @@ func (c *Client) Verify(ctx context.Context, commitSHA string, cert *x509.Certif return e, cosign.VerifyTLogEntryOffline(ctx, e, c.publicKeys) } -// extractCerts is taken from cosign's cmd/cosign/cli/verify/verify_blob.go. +// extractCertsForHash is taken from cosign's +// cmd/cosign/cli/verify/verify_blob.go. // TODO: Refactor this into a shared lib. -func extractCerts(e *models.LogEntryAnon) ([]*x509.Certificate, error) { +func extractCertsForHash(e *models.LogEntryAnon, hash string) ([]*x509.Certificate, error) { b, err := base64.StdEncoding.DecodeString(e.Body.(string)) if err != nil { return nil, err @@ -211,15 +208,19 @@ func extractCerts(e *models.LogEntryAnon) ([]*x509.Certificate, error) { return nil, err } - var publicKeyB64 []byte + var ( + publicKeyB64 []byte + certHash string + ) switch e := eimpl.(type) { case *rekord_v001.V001Entry: + certHash = *e.RekordObj.Data.Hash.Value publicKeyB64, err = e.RekordObj.Signature.PublicKey.Content.MarshalText() if err != nil { return nil, err } case *hashedrekord_v001.V001Entry: - fmt.Println("HASH", *e.HashedRekordObj.Data.Hash.Value) + certHash = *e.HashedRekordObj.Data.Hash.Value publicKeyB64, err = e.HashedRekordObj.Signature.PublicKey.Content.MarshalText() if err != nil { return nil, err @@ -228,6 +229,10 @@ func extractCerts(e *models.LogEntryAnon) ([]*x509.Certificate, error) { return nil, errors.New("unexpected tlog entry type") } + if certHash != hash { + return nil, fmt.Errorf("hashes don't match") + } + publicKey, err := base64.StdEncoding.DecodeString(string(publicKeyB64)) if err != nil { return nil, err