github.com/TrueCloudLab/frostfs-api-go/v2@v2.0.0-20230228134343-196241c4e79a/util/signature/options.go (about)

     1  package signature
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"encoding/base64"
     6  	"fmt"
     7  
     8  	"github.com/TrueCloudLab/frostfs-api-go/v2/refs"
     9  	"github.com/TrueCloudLab/frostfs-api-go/v2/util/signature/walletconnect"
    10  	crypto "github.com/TrueCloudLab/frostfs-crypto"
    11  )
    12  
    13  type cfg struct {
    14  	schemeFixed bool
    15  	scheme      refs.SignatureScheme
    16  	buffer      []byte
    17  }
    18  
    19  func defaultCfg() *cfg {
    20  	return new(cfg)
    21  }
    22  
    23  func verify(cfg *cfg, data []byte, sig *refs.Signature) error {
    24  	if !cfg.schemeFixed {
    25  		cfg.scheme = sig.GetScheme()
    26  	}
    27  
    28  	pub := crypto.UnmarshalPublicKey(sig.GetKey())
    29  	if pub == nil {
    30  		return crypto.ErrEmptyPublicKey
    31  	}
    32  
    33  	switch cfg.scheme {
    34  	case refs.ECDSA_SHA512:
    35  		return crypto.Verify(pub, data, sig.GetSign())
    36  	case refs.ECDSA_RFC6979_SHA256:
    37  		return crypto.VerifyRFC6979(pub, data, sig.GetSign())
    38  	case refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT:
    39  		buf := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
    40  		base64.StdEncoding.Encode(buf, data)
    41  		if !walletconnect.Verify(pub, buf, sig.GetSign()) {
    42  			return crypto.ErrInvalidSignature
    43  		}
    44  		return nil
    45  	default:
    46  		return fmt.Errorf("unsupported signature scheme %s", cfg.scheme)
    47  	}
    48  }
    49  
    50  func sign(cfg *cfg, key *ecdsa.PrivateKey, data []byte) ([]byte, error) {
    51  	switch cfg.scheme {
    52  	case refs.ECDSA_SHA512:
    53  		return crypto.Sign(key, data)
    54  	case refs.ECDSA_RFC6979_SHA256:
    55  		return crypto.SignRFC6979(key, data)
    56  	case refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT:
    57  		buf := make([]byte, base64.StdEncoding.EncodedLen(len(data)))
    58  		base64.StdEncoding.Encode(buf, data)
    59  		return walletconnect.Sign(key, buf)
    60  	default:
    61  		panic(fmt.Sprintf("unsupported scheme %s", cfg.scheme))
    62  	}
    63  }
    64  
    65  func SignWithRFC6979() SignOption {
    66  	return func(c *cfg) {
    67  		c.schemeFixed = true
    68  		c.scheme = refs.ECDSA_RFC6979_SHA256
    69  	}
    70  }
    71  
    72  // WithBuffer allows providing pre-allocated buffer for signature verification.
    73  func WithBuffer(buf []byte) SignOption {
    74  	return func(c *cfg) {
    75  		c.buffer = buf
    76  	}
    77  }
    78  
    79  func SignWithWalletConnect() SignOption {
    80  	return func(c *cfg) {
    81  		c.scheme = refs.ECDSA_RFC6979_SHA256_WALLET_CONNECT
    82  	}
    83  }