Skip to content

Commit

Permalink
update blob sign
Browse files Browse the repository at this point in the history
Signed-off-by: Patrick Zheng <[email protected]>
  • Loading branch information
Two-Hearts committed Dec 24, 2024
1 parent cefd007 commit 793fd1c
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 22 deletions.
14 changes: 9 additions & 5 deletions notation.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ var errDoneVerification = errors.New("done verification")

var reservedAnnotationPrefixes = [...]string{"io.cncf.notary"}

// SignerSignOptions contains parameters for Signer.Sign.
// SignerSignOptions contains parameters for Signer and BlobSigner.
type SignerSignOptions struct {
// SignatureMediaType is the envelope type of the signature.
// Currently, both `application/jose+json` and `application/cose` are
Expand Down Expand Up @@ -89,15 +89,18 @@ type Signer interface {
// SignBlobOptions contains parameters for notation.SignBlob.
type SignBlobOptions struct {
SignerSignOptions

// ContentMediaType is the media-type of the blob being signed.
ContentMediaType string

// UserMetadata contains key-value pairs that are added to the signature
// payload
UserMetadata map[string]string
}

// BlobDescriptorGenerator creates descriptor using the digest Algorithm.
// Below is the example of minimal descriptor, it must contain mediatype, digest and size of the artifact
// Below is the example of minimal descriptor, it must contain mediatype,
// digest and size of the artifact.
//
// {
// "mediaType": "application/octet-stream",
Expand All @@ -110,8 +113,8 @@ type BlobDescriptorGenerator func(digest.Algorithm) (ocispec.Descriptor, error)
// The interface allows signing with local or remote keys,
// and packing in various signature formats.
type BlobSigner interface {
// SignBlob signs the descriptor returned by genDesc ,
// and returns the signature and SignerInfo
// SignBlob signs the descriptor returned by genDesc, and returns the
// signature and SignerInfo.
SignBlob(ctx context.Context, genDesc BlobDescriptorGenerator, opts SignerSignOptions) ([]byte, *signature.SignerInfo, error)
}

Expand Down Expand Up @@ -200,7 +203,8 @@ func Sign(ctx context.Context, signer Signer, repo registry.Repository, signOpts
return targetDesc, nil
}

// SignBlob signs the arbitrary data and returns the signature
// SignBlob signs the arbitrary data from blobReader and returns
// the signature and SignerInfo.
func SignBlob(ctx context.Context, signer BlobSigner, blobReader io.Reader, signBlobOpts SignBlobOptions) ([]byte, *signature.SignerInfo, error) {
// sanity checks
if err := validateSignArguments(signer, signBlobOpts.SignerSignOptions); err != nil {
Expand Down
13 changes: 8 additions & 5 deletions signer/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ import (
)

// PluginSigner signs artifacts and generates signatures.
// It implements notation.Signer
//
// It implements notation.Signer and notation.BlobSigner.
type PluginSigner struct {
plugin plugin.SignPlugin
keyID string
Expand All @@ -49,16 +50,17 @@ var algorithms = map[crypto.Hash]digest.Algorithm{
crypto.SHA512: digest.SHA512,
}

// NewFromPlugin creates a notation.Signer that signs artifacts and generates
// NewFromPlugin creates a PluginSigner that signs artifacts and generates
// signatures by delegating the one or more operations to the named plugin,
// as defined in https://github.com/notaryproject/notaryproject/blob/main/specs/plugin-extensibility.md#signing-interfaces.
//
// Deprecated: NewFromPlugin function exists for historical compatibility and should not be used.
// To create PluginSigner, use NewPluginSigner() function.
func NewFromPlugin(plugin plugin.SignPlugin, keyID string, pluginConfig map[string]string) (notation.Signer, error) {
return NewPluginSigner(plugin, keyID, pluginConfig)
}

// NewPluginSigner creates a notation.Signer that signs artifacts and generates
// NewPluginSigner creates a PluginSigner that signs artifacts and generates
// signatures by delegating the one or more operations to the named plugin,
// as defined in https://github.com/notaryproject/notaryproject/blob/main/specs/plugin-extensibility.md#signing-interfaces.
func NewPluginSigner(plugin plugin.SignPlugin, keyID string, pluginConfig map[string]string) (*PluginSigner, error) {
Expand All @@ -82,7 +84,7 @@ func (s *PluginSigner) PluginAnnotations() map[string]string {
}

// Sign signs the artifact described by its descriptor and returns the
// marshalled envelope.
// signature and SignerInfo.
func (s *PluginSigner) Sign(ctx context.Context, desc ocispec.Descriptor, opts notation.SignerSignOptions) ([]byte, *signature.SignerInfo, error) {
logger := log.GetLogger(ctx)
mergedConfig := s.mergeConfig(opts.PluginConfig)
Expand Down Expand Up @@ -116,7 +118,8 @@ func (s *PluginSigner) Sign(ctx context.Context, desc ocispec.Descriptor, opts n
return nil, nil, fmt.Errorf("plugin does not have signing capabilities")
}

// SignBlob signs the arbitrary data and returns the marshalled envelope.
// SignBlob signs the descriptor returned by genDesc, and returns the
// signature and SignerInfo.
func (s *PluginSigner) SignBlob(ctx context.Context, descGenFunc notation.BlobDescriptorGenerator, opts notation.SignerSignOptions) ([]byte, *signature.SignerInfo, error) {
logger := log.GetLogger(ctx)
mergedConfig := s.mergeConfig(opts.PluginConfig)
Expand Down
11 changes: 11 additions & 0 deletions signer/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,17 @@ func (p *mockPlugin) GenerateEnvelope(ctx context.Context, req *proto.GenerateEn
return &proto.GenerateEnvelopeResponse{}, nil
}

func TestPluginSignerImpl(t *testing.T) {
p := &PluginSigner{}
if _, ok := interface{}(p).(notation.Signer); !ok {
t.Fatal("PluginSigner does not implement notation.Signer")
}

if _, ok := interface{}(p).(notation.BlobSigner); !ok {
t.Fatal("PluginSigner does not implement notation.BlobSigner")
}
}

func TestNewFromPluginFailed(t *testing.T) {
tests := map[string]struct {
pl plugin.SignPlugin
Expand Down
28 changes: 16 additions & 12 deletions signer/signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,21 @@ import (
// signingAgent is the unprotected header field used by signature.
const signingAgent = "notation-go/1.3.0+unreleased"

// GenericSigner implements notation.Signer and embeds signature.Signer
// GenericSigner implements notation.Signer and notation.BlobSigner.
// It embeds signature.Signer.
type GenericSigner struct {
signer signature.Signer
}

// New returns a builtinSigner given key and cert chain
// New returns a notation.Signer given key and cert chain.
//
// Deprecated: New function exists for historical compatibility and should not be used.
// To create GenericSigner, use NewGenericSigner() function.
func New(key crypto.PrivateKey, certChain []*x509.Certificate) (notation.Signer, error) {
return NewGenericSigner(key, certChain)
}

// NewGenericSigner returns a builtinSigner given key and cert chain
// NewGenericSigner returns a builtinSigner given key and cert chain.
func NewGenericSigner(key crypto.PrivateKey, certChain []*x509.Certificate) (*GenericSigner, error) {
localSigner, err := signature.NewLocalSigner(certChain, key)
if err != nil {
Expand All @@ -59,12 +61,13 @@ func NewGenericSigner(key crypto.PrivateKey, certChain []*x509.Certificate) (*Ge
}, nil
}

// NewFromFiles returns a builtinSigner given key and certChain paths.
// NewFromFiles returns a notation.Signer given key and certChain paths.
func NewFromFiles(keyPath, certChainPath string) (notation.Signer, error) {
return NewGenericSignerFromFiles(keyPath, certChainPath)
}

// NewGenericSignerFromFiles returns a builtinSigner given key and certChain paths.
// NewGenericSignerFromFiles returns a builtinSigner given key and certChain
// paths.
func NewGenericSignerFromFiles(keyPath, certChainPath string) (*GenericSigner, error) {
if keyPath == "" {
return nil, errors.New("key path not specified")
Expand Down Expand Up @@ -96,7 +99,7 @@ func NewGenericSignerFromFiles(keyPath, certChainPath string) (*GenericSigner, e
}

// Sign signs the artifact described by its descriptor and returns the
// marshalled envelope.
// signature and SignerInfo.
func (s *GenericSigner) Sign(ctx context.Context, desc ocispec.Descriptor, opts notation.SignerSignOptions) ([]byte, *signature.SignerInfo, error) {
logger := log.GetLogger(ctx)
logger.Debugf("Generic signing for %v in signature media type %v", desc.Digest, opts.SignatureMediaType)
Expand Down Expand Up @@ -172,29 +175,30 @@ func (s *GenericSigner) Sign(ctx context.Context, desc ocispec.Descriptor, opts
return sig, &envContent.SignerInfo, nil
}

// SignBlob signs the descriptor returned by blobGen and returns the marshalled envelope
func (s *GenericSigner) SignBlob(ctx context.Context, descGenFunc notation.BlobDescriptorGenerator, opts notation.SignerSignOptions) ([]byte, *signature.SignerInfo, error) {
// SignBlob signs the descriptor returned by genDesc, and returns the
// signature and SignerInfo.
func (s *GenericSigner) SignBlob(ctx context.Context, genDesc notation.BlobDescriptorGenerator, opts notation.SignerSignOptions) ([]byte, *signature.SignerInfo, error) {
logger := log.GetLogger(ctx)
logger.Debugf("Generic blob signing for signature media type %v", opts.SignatureMediaType)
logger.Debugf("Generic blob signing for signature media type %s", opts.SignatureMediaType)

ks, err := s.signer.KeySpec()
if err != nil {
return nil, nil, err
}

desc, err := getDescriptor(ks, descGenFunc)
desc, err := getDescriptor(ks, genDesc)
if err != nil {
return nil, nil, err
}

return s.Sign(ctx, desc, opts)
}

func getDescriptor(ks signature.KeySpec, descGenFunc notation.BlobDescriptorGenerator) (ocispec.Descriptor, error) {
func getDescriptor(ks signature.KeySpec, genDesc notation.BlobDescriptorGenerator) (ocispec.Descriptor, error) {
digestAlg, ok := algorithms[ks.SignatureAlgorithm().Hash()]
if !ok {
return ocispec.Descriptor{}, fmt.Errorf("unknown hashing algo %v", ks.SignatureAlgorithm().Hash())
}

return descGenFunc(digestAlg)
return genDesc(digestAlg)
}
11 changes: 11 additions & 0 deletions signer/signer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,17 @@ func testSignerFromFile(t *testing.T, keyCert *keyCertPair, envelopeType, dir st
basicVerification(t, sig, envelopeType, keyCert.certs[len(keyCert.certs)-1], nil)
}

func TestGenericSignerImpl(t *testing.T) {
g := &GenericSigner{}
if _, ok := interface{}(g).(notation.Signer); !ok {
t.Fatal("GenericSigner does not implement notation.Signer")
}

if _, ok := interface{}(g).(notation.BlobSigner); !ok {
t.Fatal("GenericSigner does not implement notation.BlobSigner")
}
}

func TestNewFromFiles(t *testing.T) {
// sign with key
dir := t.TempDir()
Expand Down

0 comments on commit 793fd1c

Please sign in to comment.