Skip to content

Commit

Permalink
Moved LoadOption into pkg/signature/options
Browse files Browse the repository at this point in the history
Signed-off-by: Riccardo Schirone <riccardo.schirone@trailofbits.com>
  • Loading branch information
ret2libc committed Jan 29, 2024
1 parent be71bbf commit cff4abc
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 93 deletions.
8 changes: 8 additions & 0 deletions pkg/signature/options.go
Expand Up @@ -18,6 +18,7 @@ package signature
import (
"context"
"crypto"
"crypto/rsa"
"io"

"github.com/sigstore/sigstore/pkg/signature/options"
Expand Down Expand Up @@ -55,3 +56,10 @@ type VerifyOption interface {
RPCOption
MessageOption
}

// LoadOption specifies options to be used when creating a Signer/Verifier
type LoadOption interface {
ApplyHash(*crypto.Hash)
ApplyED25519ph(*bool)
ApplyRSAPSS(**rsa.PSSOptions)
}
68 changes: 68 additions & 0 deletions pkg/signature/options/loadoptions.go
@@ -0,0 +1,68 @@
//
// Copyright 2024 The Sigstore Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package options

import (
"crypto"
"crypto/rsa"
)

type RequestHash struct {

Check warning on line 23 in pkg/signature/options/loadoptions.go

View workflow job for this annotation

GitHub Actions / lint checks

exported: exported type RequestHash should have comment or be unexported (revive)
NoOpOptionImpl
hashFunc crypto.Hash
}

// ApplyHash sets the hash as requested by the functional option
func (r RequestHash) ApplyHash(hash *crypto.Hash) {
*hash = r.hashFunc
}

// WithHash specifies that the given hash function should be used when loading a signer or verifier
func WithHash(hash crypto.Hash) RequestHash {
return RequestHash{hashFunc: hash}
}

type RequestED25519ph struct {

Check warning on line 38 in pkg/signature/options/loadoptions.go

View workflow job for this annotation

GitHub Actions / lint checks

exported: exported type RequestED25519ph should have comment or be unexported (revive)
NoOpOptionImpl
useED25519ph bool
}

// ApplyED25519ph sets the ED25519ph flag as requested by the functional option
func (r RequestED25519ph) ApplyED25519ph(useED25519ph *bool) {
*useED25519ph = r.useED25519ph
}

// WithED25519ph specifies that the ED25519ph algorithm should be used when a ED25519 key is used
func WithED25519ph() RequestED25519ph {
return RequestED25519ph{useED25519ph: true}
}

type RequestPSSOptions struct {

Check warning on line 53 in pkg/signature/options/loadoptions.go

View workflow job for this annotation

GitHub Actions / lint checks

exported: exported type RequestPSSOptions should have comment or be unexported (revive)
NoOpOptionImpl
opts *rsa.PSSOptions
}

// ApplyRSAPSS sets the RSAPSS options as requested by the functional option
func (r RequestPSSOptions) ApplyRSAPSS(opts **rsa.PSSOptions) {
*opts = r.opts
}

// WithRSAPSS specifies that the RSAPSS algorithm should be used when a RSA key is used
// Note that the RSA PSSOptions contains an hash algorithm, which will override
// the hash function specified with WithHash.
func WithRSAPSS(opts *rsa.PSSOptions) RequestPSSOptions {
return RequestPSSOptions{opts: opts}
}
10 changes: 10 additions & 0 deletions pkg/signature/options/noop.go
Expand Up @@ -18,6 +18,7 @@ package options
import (
"context"
"crypto"
"crypto/rsa"
"io"
)

Expand Down Expand Up @@ -47,3 +48,12 @@ func (NoOpOptionImpl) ApplyKeyVersion(_ *string) {}

// ApplyKeyVersionUsed is a no-op required to fully implement the requisite interfaces
func (NoOpOptionImpl) ApplyKeyVersionUsed(_ **string) {}

// ApplyHash is a no-op required to fully implement the requisite interfaces
func (NoOpOptionImpl) ApplyHash(_ *crypto.Hash) {}

// ApplyED25519ph is a no-op required to fully implement the requisite interfaces
func (NoOpOptionImpl) ApplyED25519ph(_ *bool) {}

// ApplyRSAPSS is a no-op required to fully implement the requisite interfaces
func (NoOpOptionImpl) ApplyRSAPSS(_ **rsa.PSSOptions) {}
22 changes: 15 additions & 7 deletions pkg/signature/signer.go
Expand Up @@ -30,6 +30,7 @@ import (
_ "crypto/sha512"

"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature/options"

// these ensure we have the implementations loaded
_ "golang.org/x/crypto/sha3"
Expand Down Expand Up @@ -59,24 +60,31 @@ func (s SignerOpts) HashFunc() crypto.Hash {
// If privateKey is an RSA key, a RSAPKCS1v15Signer will be returned. If a
// RSAPSSSigner is desired instead, use the LoadRSAPSSSigner() method directly.
func LoadSigner(privateKey crypto.PrivateKey, hashFunc crypto.Hash) (Signer, error) {
return LoadSignerWithOpts(privateKey, WithHash(hashFunc))
return LoadSignerWithOpts(privateKey, options.WithHash(hashFunc))
}

// LoadSignerWithOpts returns a signature.Signer based on the algorithm of the private key
// provided.
func LoadSignerWithOpts(privateKey crypto.PrivateKey, opts ...LoadOption) (Signer, error) {
o := makeSignerVerifierOpts(opts...)
var rsaPSSOptions *rsa.PSSOptions
var hashFunc crypto.Hash = crypto.SHA256

Check warning on line 70 in pkg/signature/signer.go

View workflow job for this annotation

GitHub Actions / lint checks

var-declaration: should omit type crypto.Hash from declaration of var hashFunc; it will be inferred from the right-hand side (revive)
var useED25519ph bool
for _, o := range opts {
o.ApplyED25519ph(&useED25519ph)
o.ApplyHash(&hashFunc)
o.ApplyRSAPSS(&rsaPSSOptions)
}

switch pk := privateKey.(type) {
case *rsa.PrivateKey:
if o.rsaPSSOptions != nil {
return LoadRSAPSSSigner(pk, o.hashFunc, o.rsaPSSOptions)
if rsaPSSOptions != nil {
return LoadRSAPSSSigner(pk, hashFunc, rsaPSSOptions)
}
return LoadRSAPKCS1v15Signer(pk, o.hashFunc)
return LoadRSAPKCS1v15Signer(pk, hashFunc)
case *ecdsa.PrivateKey:
return LoadECDSASigner(pk, o.hashFunc)
return LoadECDSASigner(pk, hashFunc)
case ed25519.PrivateKey:
if o.useED25519ph {
if useED25519ph {
return LoadED25519phSigner(pk)
}
return LoadED25519Signer(pk)
Expand Down
3 changes: 2 additions & 1 deletion pkg/signature/signer_test.go
Expand Up @@ -22,6 +22,7 @@ import (
"testing"

"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature/options"
)

func TestLoadEd25519Signer(t *testing.T) {
Expand Down Expand Up @@ -61,7 +62,7 @@ func TestLoadEd25519phSigner(t *testing.T) {
t.Fatalf("expected ed25519.PrivateKey")
}

signer, err := LoadSignerWithOpts(edPriv, WithED25519ph(), WithHash(crypto.SHA512))
signer, err := LoadSignerWithOpts(edPriv, options.WithED25519ph(), options.WithHash(crypto.SHA512))
if err != nil {
t.Fatalf("unexpected error loading verifier: %v", err)
}
Expand Down
22 changes: 15 additions & 7 deletions pkg/signature/signerverifier.go
Expand Up @@ -25,6 +25,7 @@ import (
"path/filepath"

"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature/options"
)

// SignerVerifier creates and verifies digital signatures over a message using a specified key pair
Expand All @@ -39,24 +40,31 @@ type SignerVerifier interface {
// If privateKey is an RSA key, a RSAPKCS1v15SignerVerifier will be returned. If a
// RSAPSSSignerVerifier is desired instead, use the LoadRSAPSSSignerVerifier() method directly.
func LoadSignerVerifier(privateKey crypto.PrivateKey, hashFunc crypto.Hash) (SignerVerifier, error) {
return LoadSignerVerifierWithOpts(privateKey, WithHash(hashFunc))
return LoadSignerVerifierWithOpts(privateKey, options.WithHash(hashFunc))
}

// LoadSignerVerifierWithOpts returns a signature.SignerVerifier based on the
// algorithm of the private key provided and the user's choice.
func LoadSignerVerifierWithOpts(privateKey crypto.PrivateKey, opts ...LoadOption) (SignerVerifier, error) {
o := makeSignerVerifierOpts(opts...)
var rsaPSSOptions *rsa.PSSOptions
var hashFunc crypto.Hash = crypto.SHA256

Check warning on line 50 in pkg/signature/signerverifier.go

View workflow job for this annotation

GitHub Actions / lint checks

var-declaration: should omit type crypto.Hash from declaration of var hashFunc; it will be inferred from the right-hand side (revive)
var useED25519ph bool
for _, o := range opts {
o.ApplyED25519ph(&useED25519ph)
o.ApplyHash(&hashFunc)
o.ApplyRSAPSS(&rsaPSSOptions)
}

switch pk := privateKey.(type) {
case *rsa.PrivateKey:
if o.rsaPSSOptions != nil {
return LoadRSAPSSSignerVerifier(pk, o.hashFunc, o.rsaPSSOptions)
if rsaPSSOptions != nil {
return LoadRSAPSSSignerVerifier(pk, hashFunc, rsaPSSOptions)
}
return LoadRSAPKCS1v15SignerVerifier(pk, o.hashFunc)
return LoadRSAPKCS1v15SignerVerifier(pk, hashFunc)
case *ecdsa.PrivateKey:
return LoadECDSASignerVerifier(pk, o.hashFunc)
return LoadECDSASignerVerifier(pk, hashFunc)
case ed25519.PrivateKey:
if o.useED25519ph {
if useED25519ph {
return LoadED25519phSignerVerifier(pk)
}
return LoadED25519SignerVerifier(pk)
Expand Down
70 changes: 0 additions & 70 deletions pkg/signature/signerverifier_options.go

This file was deleted.

3 changes: 2 additions & 1 deletion pkg/signature/signerverifier_test.go
Expand Up @@ -22,6 +22,7 @@ import (
"testing"

"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature/options"
)

func TestLoadRSAPSSSignerVerifier(t *testing.T) {
Expand All @@ -33,7 +34,7 @@ func TestLoadRSAPSSSignerVerifier(t *testing.T) {
if err != nil {
t.Errorf("unexpected error unmarshalling private key: %v", err)
}
sv, err := LoadSignerVerifierWithOpts(privateKey, WithHash(crypto.SHA256), WithED25519ph(), WithRSAPSS(opts))
sv, err := LoadSignerVerifierWithOpts(privateKey, options.WithHash(crypto.SHA256), options.WithED25519ph(), options.WithRSAPSS(opts))
if err != nil {
t.Errorf("unexpected error creating signer/verifier: %v", err)
}
Expand Down
22 changes: 15 additions & 7 deletions pkg/signature/verifier.go
Expand Up @@ -26,6 +26,7 @@ import (
"path/filepath"

"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature/options"
)

// Verifier verifies the digital signature using a specified public key
Expand All @@ -40,24 +41,31 @@ type Verifier interface {
// If publicKey is an RSA key, a RSAPKCS1v15Verifier will be returned. If a
// RSAPSSVerifier is desired instead, use the LoadRSAPSSVerifier() method directly.
func LoadVerifier(publicKey crypto.PublicKey, hashFunc crypto.Hash) (Verifier, error) {
return LoadVerifierWithOpts(publicKey, WithHash(hashFunc))
return LoadVerifierWithOpts(publicKey, options.WithHash(hashFunc))
}

// LoadVerifierWithOpts returns a signature.Verifier based on the algorithm of the public key
// provided that will use the hash function specified when computing digests.
func LoadVerifierWithOpts(publicKey crypto.PublicKey, opts ...LoadOption) (Verifier, error) {
o := makeSignerVerifierOpts(opts...)
var rsaPSSOptions *rsa.PSSOptions
var hashFunc crypto.Hash = crypto.SHA256

Check warning on line 51 in pkg/signature/verifier.go

View workflow job for this annotation

GitHub Actions / lint checks

var-declaration: should omit type crypto.Hash from declaration of var hashFunc; it will be inferred from the right-hand side (revive)
var useED25519ph bool
for _, o := range opts {
o.ApplyED25519ph(&useED25519ph)
o.ApplyHash(&hashFunc)
o.ApplyRSAPSS(&rsaPSSOptions)
}

switch pk := publicKey.(type) {
case *rsa.PublicKey:
if o.rsaPSSOptions != nil {
return LoadRSAPSSVerifier(pk, o.hashFunc, o.rsaPSSOptions)
if rsaPSSOptions != nil {
return LoadRSAPSSVerifier(pk, hashFunc, rsaPSSOptions)
}
return LoadRSAPKCS1v15Verifier(pk, o.hashFunc)
return LoadRSAPKCS1v15Verifier(pk, hashFunc)
case *ecdsa.PublicKey:
return LoadECDSAVerifier(pk, o.hashFunc)
return LoadECDSAVerifier(pk, hashFunc)
case ed25519.PublicKey:
if o.useED25519ph {
if useED25519ph {
return LoadED25519phVerifier(pk)
}
return LoadED25519Verifier(pk)
Expand Down

0 comments on commit cff4abc

Please sign in to comment.