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

     1  package signature
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  
     6  	"github.com/TrueCloudLab/frostfs-api-go/v2/refs"
     7  	crypto "github.com/TrueCloudLab/frostfs-crypto"
     8  )
     9  
    10  type DataSource interface {
    11  	ReadSignedData([]byte) ([]byte, error)
    12  	SignedDataSize() int
    13  }
    14  
    15  type DataWithSignature interface {
    16  	DataSource
    17  	GetSignature() *refs.Signature
    18  	SetSignature(*refs.Signature)
    19  }
    20  
    21  type SignOption func(*cfg)
    22  
    23  type KeySignatureHandler func(*refs.Signature)
    24  
    25  type KeySignatureSource func() *refs.Signature
    26  
    27  func SignDataWithHandler(key *ecdsa.PrivateKey, src DataSource, handler KeySignatureHandler, opts ...SignOption) error {
    28  	if key == nil {
    29  		return crypto.ErrEmptyPrivateKey
    30  	}
    31  
    32  	cfg := defaultCfg()
    33  
    34  	for i := range opts {
    35  		opts[i](cfg)
    36  	}
    37  
    38  	data, err := readSignedData(cfg, src)
    39  	if err != nil {
    40  		return err
    41  	}
    42  
    43  	sigData, err := sign(cfg, key, data)
    44  	if err != nil {
    45  		return err
    46  	}
    47  
    48  	sig := new(refs.Signature)
    49  	sig.SetScheme(cfg.scheme)
    50  	sig.SetKey(crypto.MarshalPublicKey(&key.PublicKey))
    51  	sig.SetSign(sigData)
    52  	handler(sig)
    53  
    54  	return nil
    55  }
    56  
    57  func VerifyDataWithSource(dataSrc DataSource, sigSrc KeySignatureSource, opts ...SignOption) error {
    58  	cfg := defaultCfg()
    59  
    60  	for i := range opts {
    61  		opts[i](cfg)
    62  	}
    63  
    64  	data, err := readSignedData(cfg, dataSrc)
    65  	if err != nil {
    66  		return err
    67  	}
    68  
    69  	return verify(cfg, data, sigSrc())
    70  }
    71  
    72  func SignData(key *ecdsa.PrivateKey, v DataWithSignature, opts ...SignOption) error {
    73  	return SignDataWithHandler(key, v, v.SetSignature, opts...)
    74  }
    75  
    76  func VerifyData(src DataWithSignature, opts ...SignOption) error {
    77  	return VerifyDataWithSource(src, src.GetSignature, opts...)
    78  }
    79  
    80  func readSignedData(cfg *cfg, src DataSource) ([]byte, error) {
    81  	size := src.SignedDataSize()
    82  	if cfg.buffer == nil || cap(cfg.buffer) < size {
    83  		cfg.buffer = make([]byte, size)
    84  	} else {
    85  		cfg.buffer = cfg.buffer[:size]
    86  	}
    87  	return src.ReadSignedData(cfg.buffer)
    88  }