1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
package signature
import (
"encoding/json"
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
)
const (
// from sigstore/cosign/pkg/types.SimpleSigningMediaType
SigstoreSignatureMIMEType = "application/vnd.dev.cosign.simplesigning.v1+json"
// from sigstore/cosign/pkg/oci/static.SignatureAnnotationKey
SigstoreSignatureAnnotationKey = "dev.cosignproject.cosign/signature"
// from sigstore/cosign/pkg/oci/static.BundleAnnotationKey
SigstoreSETAnnotationKey = "dev.sigstore.cosign/bundle"
// from sigstore/cosign/pkg/oci/static.CertificateAnnotationKey
SigstoreCertificateAnnotationKey = "dev.sigstore.cosign/certificate"
// from sigstore/cosign/pkg/oci/static.ChainAnnotationKey
SigstoreIntermediateCertificateChainAnnotationKey = "dev.sigstore.cosign/chain"
)
// Sigstore is a github.com/cosign/cosign signature.
// For the persistent-storage format used for blobChunk(), we want
// a degree of forward compatibility against unexpected field changes
// (as has happened before), which is why this data type
// contains just a payload + annotations (including annotations
// that we don’t recognize or support), instead of individual fields
// for the known annotations.
type Sigstore struct {
untrustedMIMEType string
untrustedPayload []byte
untrustedAnnotations map[string]string
}
// sigstoreJSONRepresentation needs the files to be public, which we don’t want for
// the main Sigstore type.
type sigstoreJSONRepresentation struct {
UntrustedMIMEType string `json:"mimeType"`
UntrustedPayload []byte `json:"payload"`
UntrustedAnnotations map[string]string `json:"annotations"`
}
// SigstoreFromComponents returns a Sigstore object from its components.
func SigstoreFromComponents(untrustedMimeType string, untrustedPayload []byte, untrustedAnnotations map[string]string) Sigstore {
return Sigstore{
untrustedMIMEType: untrustedMimeType,
untrustedPayload: slices.Clone(untrustedPayload),
untrustedAnnotations: maps.Clone(untrustedAnnotations),
}
}
// sigstoreFromBlobChunk converts a Sigstore signature, as returned by Sigstore.blobChunk, into a Sigstore object.
func sigstoreFromBlobChunk(blobChunk []byte) (Sigstore, error) {
var v sigstoreJSONRepresentation
if err := json.Unmarshal(blobChunk, &v); err != nil {
return Sigstore{}, err
}
return SigstoreFromComponents(v.UntrustedMIMEType,
v.UntrustedPayload,
v.UntrustedAnnotations), nil
}
func (s Sigstore) FormatID() FormatID {
return SigstoreFormat
}
// blobChunk returns a representation of signature as a []byte, suitable for long-term storage.
// Almost everyone should use signature.Blob() instead.
func (s Sigstore) blobChunk() ([]byte, error) {
return json.Marshal(sigstoreJSONRepresentation{
UntrustedMIMEType: s.UntrustedMIMEType(),
UntrustedPayload: s.UntrustedPayload(),
UntrustedAnnotations: s.UntrustedAnnotations(),
})
}
func (s Sigstore) UntrustedMIMEType() string {
return s.untrustedMIMEType
}
func (s Sigstore) UntrustedPayload() []byte {
return slices.Clone(s.untrustedPayload)
}
func (s Sigstore) UntrustedAnnotations() map[string]string {
return maps.Clone(s.untrustedAnnotations)
}
|