package signature import ( "crypto/ecdsa" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool" crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto" ) const poolSliceMaxSize = 128 * 1024 var buffersPool = pool.NewBufferPool(poolSliceMaxSize) type DataSource interface { ReadSignedData([]byte) ([]byte, error) SignedDataSize() int } type DataWithSignature interface { DataSource GetSignature() *refs.Signature SetSignature(*refs.Signature) } type SignOption func(*cfg) type KeySignatureHandler func(*refs.Signature) type KeySignatureSource func() *refs.Signature func SignDataWithHandler(key *ecdsa.PrivateKey, src DataSource, handler KeySignatureHandler, opts ...SignOption) error { if key == nil { return crypto.ErrEmptyPrivateKey } cfg := defaultCfg() for i := range opts { opts[i](cfg) } buffer := buffersPool.Get(uint32(src.SignedDataSize())) defer buffersPool.Put(buffer) data, err := src.ReadSignedData(buffer.Data) if err != nil { return err } sigData, err := sign(cfg, key, data) if err != nil { return err } sig := new(refs.Signature) sig.SetScheme(cfg.scheme) sig.SetKey(crypto.MarshalPublicKey(&key.PublicKey)) sig.SetSign(sigData) handler(sig) return nil } func VerifyDataWithSource(dataSrc DataSource, sigSrc KeySignatureSource, opts ...SignOption) error { buffer := buffersPool.Get(uint32(dataSrc.SignedDataSize())) defer buffersPool.Put(buffer) data, err := dataSrc.ReadSignedData(buffer.Data) if err != nil { return err } return VerifyDataSlice(data, sigSrc, opts...) } func SignData(key *ecdsa.PrivateKey, v DataWithSignature, opts ...SignOption) error { return SignDataWithHandler(key, v, v.SetSignature, opts...) } func VerifyData(src DataWithSignature, opts ...SignOption) error { return VerifyDataWithSource(src, src.GetSignature, opts...) } func VerifyDataSlice(data []byte, sigSrc KeySignatureSource, opts ...SignOption) error { cfg := defaultCfg() for i := range opts { opts[i](cfg) } return verify(cfg, data, sigSrc()) }