From f749b9ce590ab45c97a1c7da245932c6ef299356 Mon Sep 17 00:00:00 2001 From: Andrew Gillis Date: Thu, 31 Oct 2024 12:54:53 -0400 Subject: [PATCH] Fix intoto statement marshal/unmarshal (see in-toto/attestation#363) Signed-off-by: Andrew Gillis --- pkg/verify/signed_entity.go | 43 +++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/pkg/verify/signed_entity.go b/pkg/verify/signed_entity.go index ca696fc..47e110b 100644 --- a/pkg/verify/signed_entity.go +++ b/pkg/verify/signed_entity.go @@ -17,6 +17,7 @@ package verify import ( "crypto/x509" "encoding/asn1" + "encoding/json" "errors" "fmt" "io" @@ -26,6 +27,7 @@ import ( "github.com/sigstore/sigstore-go/pkg/fulcio/certificate" "github.com/sigstore/sigstore-go/pkg/root" "github.com/sigstore/sigstore/pkg/cryptoutils" + "google.golang.org/protobuf/encoding/protojson" ) const ( @@ -222,6 +224,8 @@ type VerificationResult struct { VerifiedIdentity *CertificateIdentity `json:"verifiedIdentity,omitempty"` } + + type SignatureVerificationResult struct { PublicKeyID *[]byte `json:"publicKeyId,omitempty"` Certificate *certificate.Summary `json:"certificate,omitempty"` @@ -239,6 +243,45 @@ func NewVerificationResult() *VerificationResult { } } +// verificationResultRawStatement is a helper struct to marshal/unmarshal +// It is used because in_toto.Statement is a protobuf message and we want to +// store it as a raw message so we can use protojson to marshal/unmarshal it +// +// See https://github.com/in-toto/attestation/issues/363 +type verificationResultRawStatement struct { + MediaType string `json:"mediaType"` + Statement json.RawMessage `json:"statement,omitempty"` + Signature *SignatureVerificationResult `json:"signature,omitempty"` + VerifiedTimestamps []TimestampVerificationResult `json:"verifiedTimestamps"` + VerifiedIdentity *CertificateIdentity `json:"verifiedIdentity,omitempty"` +} + +func (b *VerificationResult) MarshalJSON() ([]byte, error) { + statement, err := protojson.Marshal(b.Statement) + if err != nil { + return nil, err + } + return json.Marshal(&verificationResultRawStatement{ + MediaType: b.MediaType, + Statement: statement, + Signature: b.Signature, + VerifiedTimestamps: b.VerifiedTimestamps, + VerifiedIdentity: b.VerifiedIdentity, + }) +} + +func (b *VerificationResult) UnmarshalJSON(data []byte) error { + var aux verificationResultRawStatement + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + b.MediaType = aux.MediaType + b.Signature = aux.Signature + b.VerifiedTimestamps = aux.VerifiedTimestamps + b.VerifiedIdentity = aux.VerifiedIdentity + return protojson.Unmarshal(aux.Statement, b.Statement) +} + type PolicyOption func(*PolicyConfig) error type ArtifactPolicyOption func(*PolicyConfig) error