2020-08-12 14:03:11 +00:00
|
|
|
package signature
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/ecdsa"
|
|
|
|
|
2023-03-07 10:38:56 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
|
2024-01-12 15:09:28 +00:00
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/util/pool"
|
2023-03-07 10:38:56 +00:00
|
|
|
crypto "git.frostfs.info/TrueCloudLab/frostfs-crypto"
|
2020-08-12 14:03:11 +00:00
|
|
|
)
|
|
|
|
|
2024-01-12 15:09:28 +00:00
|
|
|
const poolSliceMaxSize = 128 * 1024
|
|
|
|
|
|
|
|
var buffersPool = pool.NewBufferPool(poolSliceMaxSize)
|
|
|
|
|
2020-08-12 14:03:11 +00:00
|
|
|
type DataSource interface {
|
|
|
|
ReadSignedData([]byte) ([]byte, error)
|
2020-08-12 15:20:04 +00:00
|
|
|
SignedDataSize() int
|
2020-08-12 14:03:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type DataWithSignature interface {
|
|
|
|
DataSource
|
2022-02-22 11:25:43 +00:00
|
|
|
GetSignature() *refs.Signature
|
|
|
|
SetSignature(*refs.Signature)
|
2020-08-12 14:03:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type SignOption func(*cfg)
|
|
|
|
|
2022-02-22 11:25:43 +00:00
|
|
|
type KeySignatureHandler func(*refs.Signature)
|
2020-08-12 14:03:11 +00:00
|
|
|
|
2022-02-22 11:25:43 +00:00
|
|
|
type KeySignatureSource func() *refs.Signature
|
2020-08-12 14:03:11 +00:00
|
|
|
|
2022-02-22 11:25:43 +00:00
|
|
|
func SignDataWithHandler(key *ecdsa.PrivateKey, src DataSource, handler KeySignatureHandler, opts ...SignOption) error {
|
2020-08-12 14:03:11 +00:00
|
|
|
if key == nil {
|
2022-02-22 11:25:43 +00:00
|
|
|
return crypto.ErrEmptyPrivateKey
|
2020-08-12 14:03:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cfg := defaultCfg()
|
|
|
|
|
|
|
|
for i := range opts {
|
|
|
|
opts[i](cfg)
|
|
|
|
}
|
|
|
|
|
2024-01-12 15:09:28 +00:00
|
|
|
buffer := buffersPool.Get(uint32(src.SignedDataSize()))
|
|
|
|
defer buffersPool.Put(buffer)
|
2023-03-09 08:33:21 +00:00
|
|
|
|
2024-01-12 15:09:28 +00:00
|
|
|
data, err := src.ReadSignedData(buffer.Data)
|
2022-04-11 11:23:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-03-02 10:15:36 +00:00
|
|
|
sigData, err := sign(cfg, key, data)
|
2020-08-12 14:03:11 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-02-22 11:25:43 +00:00
|
|
|
sig := new(refs.Signature)
|
2022-03-02 10:15:36 +00:00
|
|
|
sig.SetScheme(cfg.scheme)
|
2022-02-22 11:25:43 +00:00
|
|
|
sig.SetKey(crypto.MarshalPublicKey(&key.PublicKey))
|
|
|
|
sig.SetSign(sigData)
|
|
|
|
handler(sig)
|
2020-08-12 14:03:11 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func VerifyDataWithSource(dataSrc DataSource, sigSrc KeySignatureSource, opts ...SignOption) error {
|
2024-01-12 15:09:28 +00:00
|
|
|
buffer := buffersPool.Get(uint32(dataSrc.SignedDataSize()))
|
|
|
|
defer buffersPool.Put(buffer)
|
2023-03-09 08:33:21 +00:00
|
|
|
|
2024-01-12 15:09:28 +00:00
|
|
|
data, err := dataSrc.ReadSignedData(buffer.Data)
|
2022-04-11 11:23:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2024-04-25 12:13:10 +00:00
|
|
|
return VerifyDataSlice(data, sigSrc, opts...)
|
2020-08-12 14:03:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func SignData(key *ecdsa.PrivateKey, v DataWithSignature, opts ...SignOption) error {
|
2022-02-22 11:25:43 +00:00
|
|
|
return SignDataWithHandler(key, v, v.SetSignature, opts...)
|
2020-08-12 14:03:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func VerifyData(src DataWithSignature, opts ...SignOption) error {
|
2022-02-22 11:25:43 +00:00
|
|
|
return VerifyDataWithSource(src, src.GetSignature, opts...)
|
2020-08-12 14:03:11 +00:00
|
|
|
}
|
2024-04-25 12:13:10 +00:00
|
|
|
|
|
|
|
func VerifyDataSlice(data []byte, sigSrc KeySignatureSource, opts ...SignOption) error {
|
|
|
|
cfg := defaultCfg()
|
|
|
|
|
|
|
|
for i := range opts {
|
|
|
|
opts[i](cfg)
|
|
|
|
}
|
|
|
|
|
|
|
|
return verify(cfg, data, sigSrc())
|
|
|
|
}
|