Notation Blob Verification

Option 1 (Preferred as disccussed)

type BlobVerifierVerifyOptions struct {
	// SignatureMediaType is the envelope type of the signature.
	// Currently only `application/jose+json` and `application/cose` are
	// supported.
	SignatureMediaType string

	// PluginConfig is a map of plugin configs.
	PluginConfig map[string]string

	// UserMetadata contains key-value pairs that must be present in the
	// signature.
	UserMetadata map[string]string
}

type BlobVerifier interface {
	VerifyBlob(ctx context.Context, descGenFunc BlobDescriptorGenerator, signature []byte, opts BlobVerifierVerifyOptions) (*VerificationOutcome, error)
}

type BlobDescriptorGenerator func(digest.Algorithm) (ocispec.Descriptor, error)


type BlobVerifyOptions struct {
	BlobVerifierVerifyOptions
    
	// ContentMediaType is the media-type type of the content being verified.
	ContentMediaType string
}

func VerifyBlob(ctx context.Context, verifier Verifier, blobReader io.Reader, signature []byte, verifyBlobOpts BlobVerifyOptions) (ocispec.Descriptor, []*VerificationOutcome, error)

The idea here was that in BlobVerifier implementation we will compare the descriptor returned by BlobDescriptorGenerator with the descriptor in the signature. However, this approach doesn't work because we cannot create the correct descriptor from the blob (io.reader) since we don't know the blob's media type and user defined metadata. The blob media type and user metadata are optional parameters in Notation, and users can choose not to pass them during verification.

Selectively comparing descriptor fields is not accurate because the BlobVerifier's VerifyBlob method gives the impression that we are comparing the complete descriptor.

Option 2

// same as BlobVerifierVerifyOptions but we want to keep it seperate because
// both can evolve independently
type BlobVerifierOptions struct {
	// SignatureMediaType is the envelope type of the signature.
	// Currently only `application/jose+json` and `application/cose` are
	// supported.
	SignatureMediaType string

	// ContentMediaType is the media-type type of the content being verified.
	ContentMediaType string

	// PluginConfig is a map of plugin configs.
	PluginConfig map[string]string

	// UserMetadata contains key-value pairs that must be present in the
	// signature.
	UserMetadata map[string]string
}

type BlobVerifier interface {
	VerifyBlob(ctx context.Context, blobReader io.Reader, signature []byte, opts BlobVerifierOptions) (*VerificationOutcome, error)
}
type BlobDescriptorGenerator func(digest.Algorithm) (ocispec.Descriptor, error)


type BlobVerifierVerifyOptions struct {
	// SignatureMediaType is the envelope type of the signature.
	// Currently only `application/jose+json` and `application/cose` are
	// supported.
	SignatureMediaType string

	// ContentMediaType is the media-type type of the content being verified.
	ContentMediaType string

	// PluginConfig is a map of plugin configs.
	PluginConfig map[string]string

	// UserMetadata contains key-value pairs that must be present in the
	// signature.
	UserMetadata map[string]string
}

func VerifyBlob(ctx context.Context, verifier Verifier, blobReader io.Reader, signatures [][]byte, verifyBlobOpts BlobVerifierVerifyOptions) (ocispec.Descriptor, []*VerificationOutcome, error)

The idea here is that BlobVerifier implementation will calculate hash out of blob and compare the hash with the hash stored in signature descriptor. And yes, we will also support comparing on mediatype and user defined metata if user choose to pass them in verify command.

Option 3 (by Patrick)

type BlobVerifierVerifyOptions struct {
	// SignatureMediaType is the envelope type of the signature.
	// Currently only `application/jose+json` and `application/cose` are
	// supported.
	SignatureMediaType string

	// PluginConfig is a map of plugin configs.
	PluginConfig map[string]string

	// UserMetadata contains key-value pairs that must be present in the
	// signature.
	UserMetadata map[string]string
    
        // TrustPolicyName is the name of trust policy picked by caller.
        // If empty, the global trust policy will be used.
        // This is mainly for non-CLI notation-go users, who do not have a UI to
        // specify trust policy name directly.
	TrustPolicyName string
}

type BlobVerifier interface {
	VerifyBlob(ctx context.Context, descGenFunc BlobDescriptorGenerator, signature []byte, opts BlobVerifierVerifyOptions) (*VerificationOutcome, error)
}

type BlobDescriptorGenerator func(digest.Algorithm) (ocispec.Descriptor, error)


type BlobVerifyOptions struct {
	BlobVerifierVerifyOptions
    
	// ContentMediaType is the media-type type of the content being verified.
	ContentMediaType string
}

func VerifyBlob(ctx context.Context, verifier Verifier, blobReader io.Reader, signature []byte, verifyBlobOpts BlobVerifyOptions) (ocispec.Descriptor, []*VerificationOutcome, error)

An improvement based on option 1. Added TrustPolicyName field to BlobVerifierVerifyOptions.