Skip to content

Commit

Permalink
Made the Hash algorithm a SignerVerifierOption
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 19, 2024
1 parent 4c4237b commit e599176
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 51 deletions.
18 changes: 17 additions & 1 deletion pkg/signature/options.go
Expand Up @@ -58,13 +58,21 @@ type VerifyOption interface {
}

type signerVerifierOpts struct {
hashFunc crypto.Hash
useED25519ph bool
rsaPSSOptions *rsa.PSSOptions
}

// SignerVerifierOption specifies options to be used when creating a SignerVerifier
type SignerVerifierOption func(*signerVerifierOpts)

// WithED25519ph specifies that the ED25519ph algorithm should be used when a ED25519 key is used

Check warning on line 69 in pkg/signature/options.go

View workflow job for this annotation

GitHub Actions / lint checks

exported: comment on exported function WithHash should be of the form "WithHash ..." (revive)
func WithHash(hashFunc crypto.Hash) SignerVerifierOption {
return func(o *signerVerifierOpts) {
o.hashFunc = hashFunc
}
}

// WithED25519ph specifies that the ED25519ph algorithm should be used when a ED25519 key is used
func WithED25519ph() SignerVerifierOption {
return func(o *signerVerifierOpts) {
Expand All @@ -79,8 +87,16 @@ func WithRSAPSS(opts *rsa.PSSOptions) SignerVerifierOption {
}
}

func GetSignerVerifierOptionHash(opts ...SignerVerifierOption) crypto.Hash {

Check warning on line 90 in pkg/signature/options.go

View workflow job for this annotation

GitHub Actions / lint checks

exported: exported function GetSignerVerifierOptionHash should have comment or be unexported (revive)
o := makeSignerVerifierOpts(opts...)
return o.hashFunc
}

func makeSignerVerifierOpts(opts ...SignerVerifierOption) *signerVerifierOpts {
o := &signerVerifierOpts{}
o := &signerVerifierOpts{
hashFunc: crypto.SHA256,
}

for _, opt := range opts {
opt(o)
}
Expand Down
24 changes: 8 additions & 16 deletions pkg/signature/signer.go
Expand Up @@ -59,30 +59,22 @@ 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) {
switch pk := privateKey.(type) {
case *rsa.PrivateKey:
return LoadRSAPKCS1v15Signer(pk, hashFunc)
case *ecdsa.PrivateKey:
return LoadECDSASigner(pk, hashFunc)
case ed25519.PrivateKey:
return LoadED25519Signer(pk)
}
return nil, errors.New("unsupported public key type")
return LoadSignerWithOpts(privateKey, WithHash(hashFunc))
}

// LoadSignerWithOpts returns a signature.Signer based on the algorithm of the private key
// provided.
func LoadSignerWithOpts(privateKey crypto.PrivateKey, hashFunc crypto.Hash, opts ...SignerVerifierOption) (Signer, error) {
func LoadSignerWithOpts(privateKey crypto.PrivateKey, opts ...SignerVerifierOption) (Signer, error) {
o := makeSignerVerifierOpts(opts...)

switch pk := privateKey.(type) {
case *rsa.PrivateKey:
if o.rsaPSSOptions != nil {
return LoadRSAPSSSigner(pk, hashFunc, o.rsaPSSOptions)
return LoadRSAPSSSigner(pk, o.hashFunc, o.rsaPSSOptions)
}
return LoadRSAPKCS1v15Signer(pk, hashFunc)
return LoadRSAPKCS1v15Signer(pk, o.hashFunc)
case *ecdsa.PrivateKey:
return LoadECDSASigner(pk, hashFunc)
return LoadECDSASigner(pk, o.hashFunc)
case ed25519.PrivateKey:
if o.useED25519ph {
return LoadED25519phSigner(pk)
Expand Down Expand Up @@ -111,8 +103,8 @@ func LoadSignerFromPEMFile(path string, hashFunc crypto.Hash, pf cryptoutils.Pas
}

// LoadSignerFromPEMFileWithOpts returns a signature.Signer based on the algorithm of the private key
// in the file. The Signer will use the hash function specified when computing digests.
func LoadSignerFromPEMFileWithOpts(path string, hashFunc crypto.Hash, pf cryptoutils.PassFunc, opts ...SignerVerifierOption) (Signer, error) {
// in the file. The Signer will use the hash function specified in the options when computing digests.
func LoadSignerFromPEMFileWithOpts(path string, pf cryptoutils.PassFunc, opts ...SignerVerifierOption) (Signer, error) {
fileBytes, err := os.ReadFile(filepath.Clean(path))
if err != nil {
return nil, err
Expand All @@ -121,5 +113,5 @@ func LoadSignerFromPEMFileWithOpts(path string, hashFunc crypto.Hash, pf cryptou
if err != nil {
return nil, err
}
return LoadSignerWithOpts(priv, hashFunc, opts...)
return LoadSignerWithOpts(priv, opts...)
}
2 changes: 1 addition & 1 deletion pkg/signature/signer_test.go
Expand Up @@ -61,7 +61,7 @@ func TestLoadEd25519phSigner(t *testing.T) {
t.Fatalf("expected ed25519.PrivateKey")
}

signer, err := LoadSignerWithOpts(edPriv, crypto.SHA512, WithED25519ph())
signer, err := LoadSignerWithOpts(edPriv, WithED25519ph(), WithHash(crypto.SHA512))
if err != nil {
t.Fatalf("unexpected error loading verifier: %v", err)
}
Expand Down
24 changes: 8 additions & 16 deletions pkg/signature/signerverifier.go
Expand Up @@ -39,30 +39,22 @@ 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) {
switch pk := privateKey.(type) {
case *rsa.PrivateKey:
return LoadRSAPKCS1v15SignerVerifier(pk, hashFunc)
case *ecdsa.PrivateKey:
return LoadECDSASignerVerifier(pk, hashFunc)
case ed25519.PrivateKey:
return LoadED25519SignerVerifier(pk)
}
return nil, errors.New("unsupported public key type")
return LoadSignerVerifierWithOpts(privateKey, 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, hashFunc crypto.Hash, opts ...SignerVerifierOption) (SignerVerifier, error) {
func LoadSignerVerifierWithOpts(privateKey crypto.PrivateKey, opts ...SignerVerifierOption) (SignerVerifier, error) {
o := makeSignerVerifierOpts(opts...)

switch pk := privateKey.(type) {
case *rsa.PrivateKey:
if o.rsaPSSOptions != nil {
return LoadRSAPSSSignerVerifier(pk, hashFunc, o.rsaPSSOptions)
return LoadRSAPSSSignerVerifier(pk, o.hashFunc, o.rsaPSSOptions)
}
return LoadRSAPKCS1v15SignerVerifier(pk, hashFunc)
return LoadRSAPKCS1v15SignerVerifier(pk, o.hashFunc)
case *ecdsa.PrivateKey:
return LoadECDSASignerVerifier(pk, hashFunc)
return LoadECDSASignerVerifier(pk, o.hashFunc)
case ed25519.PrivateKey:
if o.useED25519ph {
return LoadED25519phSignerVerifier(pk)
Expand Down Expand Up @@ -91,8 +83,8 @@ func LoadSignerVerifierFromPEMFile(path string, hashFunc crypto.Hash, pf cryptou
}

// LoadSignerVerifierFromPEMFileWithOpts returns a signature.SignerVerifier based on the algorithm of the private key
// in the file. The SignerVerifier will use the hash function specified when computing digests.
func LoadSignerVerifierFromPEMFileWithOpts(path string, hashFunc crypto.Hash, pf cryptoutils.PassFunc, opts ...SignerVerifierOption) (SignerVerifier, error) {
// in the file. The SignerVerifier will use the hash function specified in the options when computing digests.
func LoadSignerVerifierFromPEMFileWithOpts(path string, pf cryptoutils.PassFunc, opts ...SignerVerifierOption) (SignerVerifier, error) {
fileBytes, err := os.ReadFile(filepath.Clean(path))
if err != nil {
return nil, err
Expand All @@ -101,5 +93,5 @@ func LoadSignerVerifierFromPEMFileWithOpts(path string, hashFunc crypto.Hash, pf
if err != nil {
return nil, err
}
return LoadSignerVerifierWithOpts(priv, hashFunc, opts...)
return LoadSignerVerifierWithOpts(priv, opts...)
}
2 changes: 1 addition & 1 deletion pkg/signature/signerverifier_test.go
Expand Up @@ -33,7 +33,7 @@ func TestLoadRSAPSSSignerVerifier(t *testing.T) {
if err != nil {
t.Errorf("unexpected error unmarshalling private key: %v", err)
}
sv, err := LoadSignerVerifierWithOpts(privateKey, crypto.SHA256, WithED25519ph(), WithRSAPSS(opts))
sv, err := LoadSignerVerifierWithOpts(privateKey, WithHash(crypto.SHA256), WithED25519ph(), WithRSAPSS(opts))
if err != nil {
t.Errorf("unexpected error creating signer/verifier: %v", err)
}
Expand Down
24 changes: 8 additions & 16 deletions pkg/signature/verifier.go
Expand Up @@ -40,30 +40,22 @@ 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) {
switch pk := publicKey.(type) {
case *rsa.PublicKey:
return LoadRSAPKCS1v15Verifier(pk, hashFunc)
case *ecdsa.PublicKey:
return LoadECDSAVerifier(pk, hashFunc)
case ed25519.PublicKey:
return LoadED25519Verifier(pk)
}
return nil, errors.New("unsupported public key type")
return LoadVerifierWithOpts(publicKey, 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, hashFunc crypto.Hash, opts ...SignerVerifierOption) (Verifier, error) {
func LoadVerifierWithOpts(publicKey crypto.PublicKey, opts ...SignerVerifierOption) (Verifier, error) {
o := makeSignerVerifierOpts(opts...)

switch pk := publicKey.(type) {
case *rsa.PublicKey:
if o.rsaPSSOptions != nil {
return LoadRSAPSSVerifier(pk, hashFunc, o.rsaPSSOptions)
return LoadRSAPSSVerifier(pk, o.hashFunc, o.rsaPSSOptions)
}
return LoadRSAPKCS1v15Verifier(pk, hashFunc)
return LoadRSAPKCS1v15Verifier(pk, o.hashFunc)
case *ecdsa.PublicKey:
return LoadECDSAVerifier(pk, hashFunc)
return LoadECDSAVerifier(pk, o.hashFunc)
case ed25519.PublicKey:
if o.useED25519ph {
return LoadED25519phVerifier(pk)
Expand Down Expand Up @@ -122,8 +114,8 @@ func LoadVerifierFromPEMFile(path string, hashFunc crypto.Hash) (Verifier, error
}

// LoadVerifierFromPEMFileWithOpts returns a signature.Verifier based on the contents of a
// file located at path. The Verifier wil use the hash function specified when computing digests.
func LoadVerifierFromPEMFileWithOpts(path string, hashFunc crypto.Hash, opts ...SignerVerifierOption) (Verifier, error) {
// file located at path. The Verifier wil use the hash function specified in the options when computing digests.
func LoadVerifierFromPEMFileWithOpts(path string, opts ...SignerVerifierOption) (Verifier, error) {
fileBytes, err := os.ReadFile(filepath.Clean(path))
if err != nil {
return nil, err
Expand All @@ -134,5 +126,5 @@ func LoadVerifierFromPEMFileWithOpts(path string, hashFunc crypto.Hash, opts ...
return nil, err
}

return LoadVerifierWithOpts(pubKey, hashFunc, opts...)
return LoadVerifierWithOpts(pubKey, opts...)
}

0 comments on commit e599176

Please sign in to comment.