From 070f83e924cc837178a09b2b4d1089562c8f23da Mon Sep 17 00:00:00 2001 From: Bob Callaway <bobcallaway@users.noreply.github.com> Date: Wed, 6 Oct 2021 12:49:06 -0400 Subject: [PATCH] Canonicalize JSON before inserting into trillian (#445) Each of the supported types has a Canonicalize() method that generates a JSON representation of the entry. If the golang library were to make a change to the order of keys when marshalling an object, it would cause a duplicate entry in the log for a semantically equivalent object. This change simply transforms the JSON into RFC8785-compliant canonicalized JSON protecting against any changes in JSON libraries going forward. Signed-off-by: Bob Callaway <bob.callaway@gmail.com> --- pkg/api/entries.go | 4 ++-- pkg/types/entries.go | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/pkg/api/entries.go b/pkg/api/entries.go index 17769e2..883e20a 100644 --- a/pkg/api/entries.go +++ b/pkg/api/entries.go @@ -148,7 +148,7 @@ func createLogEntry(params entries.CreateLogEntryParams) (models.LogEntry, middl if err != nil { return nil, handleRekorAPIError(params, http.StatusBadRequest, err, fmt.Sprintf(validationError, err)) } - leaf, err := entry.Canonicalize(ctx) + leaf, err := types.CanonicalizeEntry(ctx, entry) if err != nil { if _, ok := (err).(types.ValidationError); ok { return nil, handleRekorAPIError(params, http.StatusBadRequest, err, fmt.Sprintf(validationError, err)) @@ -315,7 +315,7 @@ func SearchLogQueryHandler(params entries.SearchLogQueryParams) middleware.Respo return err } - leaf, err := entry.Canonicalize(httpReqCtx) + leaf, err := types.CanonicalizeEntry(httpReqCtx, entry) if err != nil { code = http.StatusInternalServerError return err diff --git a/pkg/types/entries.go b/pkg/types/entries.go index 42a9bb8..e046482 100644 --- a/pkg/types/entries.go +++ b/pkg/types/entries.go @@ -23,6 +23,7 @@ import ( "net/url" "reflect" + "github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer" "github.com/go-openapi/strfmt" "github.com/mitchellh/mapstructure" "github.com/sigstore/rekor/pkg/generated/models" @@ -105,6 +106,17 @@ func DecodeEntry(input, output interface{}) error { return dec.Decode(input) } +// CanonicalizeEntry returns the entry marshalled in JSON according to the +// canonicalization rules of RFC8785 to protect against any changes in golang's JSON +// marshalling logic that may reorder elements +func CanonicalizeEntry(ctx context.Context, entry EntryImpl) ([]byte, error) { + canonicalEntry, err := entry.Canonicalize(ctx) + if err != nil { + return nil, err + } + return jsoncanonicalizer.Transform(canonicalEntry) +} + // ArtifactProperties provide a consistent struct for passing values from // CLI flags to the type+version specific CreateProposeEntry() methods type ArtifactProperties struct { -- GitLab