[#150] util/signature: Simplify public interface

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2022-02-24 14:45:52 +03:00 committed by LeL
parent 1c7dd03cf5
commit d716765c1a
7 changed files with 68 additions and 103 deletions

View file

@ -86,13 +86,13 @@ func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResCon
// sign container // sign container
signWrapper := v2signature.StableMarshalerWrapper{SM: reqBody.GetContainer()} signWrapper := v2signature.StableMarshalerWrapper{SM: reqBody.GetContainer()}
err := sigutil.SignDataWithHandler(c.opts.key, signWrapper, func(sig *signature.Signature) { sig, err := sigutil.SignData(c.opts.key, signWrapper, sigutil.SignWithRFC6979())
reqBody.SetSignature(sig.ToV2())
}, sigutil.SignWithRFC6979())
if err != nil { if err != nil {
return nil, err return nil, err
} }
reqBody.SetSignature(sig.ToV2())
// form meta header // form meta header
var meta v2session.RequestMetaHeader var meta v2session.RequestMetaHeader
meta.SetSessionToken(prm.cnr.SessionToken().ToV2()) meta.SetSessionToken(prm.cnr.SessionToken().ToV2())
@ -393,19 +393,16 @@ func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (*
reqBody := new(v2container.DeleteRequestBody) reqBody := new(v2container.DeleteRequestBody)
reqBody.SetContainerID(prm.id.ToV2()) reqBody.SetContainerID(prm.id.ToV2())
signWrapper := delContainerSignWrapper{body: reqBody}
// sign container // sign container
err := sigutil.SignDataWithHandler(c.opts.key, sig, err := sigutil.SignData(c.opts.key, signWrapper, sigutil.SignWithRFC6979())
delContainerSignWrapper{
body: reqBody,
},
func(sig *signature.Signature) {
reqBody.SetSignature(sig.ToV2())
},
sigutil.SignWithRFC6979())
if err != nil { if err != nil {
return nil, err return nil, err
} }
reqBody.SetSignature(sig.ToV2())
// form meta header // form meta header
var meta v2session.RequestMetaHeader var meta v2session.RequestMetaHeader
@ -592,13 +589,13 @@ func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL)
// sign the eACL table // sign the eACL table
signWrapper := v2signature.StableMarshalerWrapper{SM: reqBody.GetEACL()} signWrapper := v2signature.StableMarshalerWrapper{SM: reqBody.GetEACL()}
err := sigutil.SignDataWithHandler(c.opts.key, signWrapper, func(sig *signature.Signature) { sig, err := sigutil.SignData(c.opts.key, signWrapper, sigutil.SignWithRFC6979())
reqBody.SetSignature(sig.ToV2())
}, sigutil.SignWithRFC6979())
if err != nil { if err != nil {
return nil, err return nil, err
} }
reqBody.SetSignature(sig.ToV2())
// form meta header // form meta header
var meta v2session.RequestMetaHeader var meta v2session.RequestMetaHeader
meta.SetSessionToken(prm.table.SessionToken().ToV2()) meta.SetSessionToken(prm.table.SessionToken().ToV2())

View file

@ -87,21 +87,11 @@ func VerifyID(obj *Object) error {
} }
func CalculateIDSignature(key *ecdsa.PrivateKey, id *oid.ID) (*signature.Signature, error) { func CalculateIDSignature(key *ecdsa.PrivateKey, id *oid.ID) (*signature.Signature, error) {
sig := signature.New() return sigutil.SignData(
if err := sigutil.SignDataWithHandler(
key, key,
signatureV2.StableMarshalerWrapper{ signatureV2.StableMarshalerWrapper{
SM: id.ToV2(), SM: id.ToV2(),
}, })
func(s *signature.Signature) {
*sig = *s
},
); err != nil {
return nil, err
}
return sig, nil
} }
func CalculateAndSetSignature(key *ecdsa.PrivateKey, obj *RawObject) error { func CalculateAndSetSignature(key *ecdsa.PrivateKey, obj *RawObject) error {
@ -116,11 +106,11 @@ func CalculateAndSetSignature(key *ecdsa.PrivateKey, obj *RawObject) error {
} }
func VerifyIDSignature(obj *Object) error { func VerifyIDSignature(obj *Object) error {
return sigutil.VerifyDataWithSource( return sigutil.VerifyData(
signatureV2.StableMarshalerWrapper{ signatureV2.StableMarshalerWrapper{
SM: obj.ID().ToV2(), SM: obj.ID().ToV2(),
}, },
obj.Signature, obj.Signature(),
) )
} }

View file

@ -260,13 +260,14 @@ func (x *GlobalTrust) Trust() *Trust {
func (x *GlobalTrust) Sign(key *ecdsa.PrivateKey) error { func (x *GlobalTrust) Sign(key *ecdsa.PrivateKey) error {
v2 := (*reputation.GlobalTrust)(x) v2 := (*reputation.GlobalTrust)(x)
return sigutil.SignDataWithHandler( sig, err := sigutil.SignData(key,
key, signatureV2.StableMarshalerWrapper{SM: v2.GetBody()})
signatureV2.StableMarshalerWrapper{SM: v2.GetBody()}, if err != nil {
func(sig *signature.Signature) { return err
}
v2.SetSignature(sig.ToV2()) v2.SetSignature(sig.ToV2())
}, return nil
)
} }
// VerifySignature verifies global trust signature. // VerifySignature verifies global trust signature.
@ -278,11 +279,9 @@ func (x *GlobalTrust) VerifySignature() error {
sigV2 = new(refs.Signature) sigV2 = new(refs.Signature)
} }
return sigutil.VerifyDataWithSource( return sigutil.VerifyData(
signatureV2.StableMarshalerWrapper{SM: v2.GetBody()}, signatureV2.StableMarshalerWrapper{SM: v2.GetBody()},
func() *signature.Signature { signature.NewFromV2(sigV2),
return signature.NewFromV2(sigV2)
},
) )
} }

View file

@ -168,9 +168,13 @@ func (t *Token) Sign(key *ecdsa.PrivateKey) error {
SM: tV2.GetBody(), SM: tV2.GetBody(),
} }
return sigutil.SignDataWithHandler(key, signedData, func(sig *signature.Signature) { sig, err := sigutil.SignData(key, signedData)
if err != nil {
return err
}
tV2.SetSignature(sig.ToV2()) tV2.SetSignature(sig.ToV2())
}) return nil
} }
// VerifySignature checks if token signature is // VerifySignature checks if token signature is
@ -182,7 +186,7 @@ func (t *Token) VerifySignature() bool {
SM: tV2.GetBody(), SM: tV2.GetBody(),
} }
return sigutil.VerifyDataWithSource(signedData, t.Signature) == nil return sigutil.VerifyData(signedData, t.Signature()) == nil
} }
// Signature returns Token signature. // Signature returns Token signature.

View file

@ -102,9 +102,13 @@ func (b *BearerToken) SignToken(key *ecdsa.PrivateKey) error {
signWrapper := v2signature.StableMarshalerWrapper{SM: b.token.GetBody()} signWrapper := v2signature.StableMarshalerWrapper{SM: b.token.GetBody()}
return sigutil.SignDataWithHandler(key, signWrapper, func(sig *signature.Signature) { sig, err := sigutil.SignData(key, signWrapper)
if err != nil {
return err
}
b.token.SetSignature(sig.ToV2()) b.token.SetSignature(sig.ToV2())
}) return nil
} }
func (b BearerToken) Signature() *signature.Signature { func (b BearerToken) Signature() *signature.Signature {
@ -116,12 +120,10 @@ func (b BearerToken) VerifySignature() error {
return nil return nil
} }
return sigutil.VerifyDataWithSource(
v2signature.StableMarshalerWrapper{SM: b.token.GetBody()},
func() *signature.Signature {
sigV2 := b.token.GetSignature() sigV2 := b.token.GetSignature()
return signature.NewFromV2(sigV2) return sigutil.VerifyData(
}) v2signature.StableMarshalerWrapper{SM: b.token.GetBody()},
signature.NewFromV2(sigV2))
} }
// Issuer returns owner.ID associated with the key that signed bearer token. // Issuer returns owner.ID associated with the key that signed bearer token.

View file

@ -2,9 +2,7 @@ package signature
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"crypto/elliptic"
"errors" "errors"
"fmt"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neofs-sdk-go/signature" "github.com/nspcc-dev/neofs-sdk-go/signature"
@ -23,10 +21,6 @@ type DataWithSignature interface {
type SignOption func(*cfg) type SignOption func(*cfg)
type KeySignatureHandler func(*signature.Signature)
type KeySignatureSource func() *signature.Signature
const ( const (
// PrivateKeyCompressedSize is constant with compressed size of private key (SK). // PrivateKeyCompressedSize is constant with compressed size of private key (SK).
// D coordinate stored, recover PK by formula x, y = curve.ScalarBaseMul(d,bytes). // D coordinate stored, recover PK by formula x, y = curve.ScalarBaseMul(d,bytes).
@ -50,14 +44,14 @@ var (
ErrInvalidSignature = errors.New("invalid signature") ErrInvalidSignature = errors.New("invalid signature")
) )
func SignDataWithHandler(key *ecdsa.PrivateKey, src DataSource, handler KeySignatureHandler, opts ...SignOption) error { func SignData(key *ecdsa.PrivateKey, src DataSource, opts ...SignOption) (*signature.Signature, error) {
if key == nil { if key == nil {
return ErrEmptyPrivateKey return nil, ErrEmptyPrivateKey
} }
data, err := dataForSignature(src) data, err := dataForSignature(src)
if err != nil { if err != nil {
return err return nil, err
} }
defer bytesPool.Put(&data) defer bytesPool.Put(&data)
@ -65,20 +59,17 @@ func SignDataWithHandler(key *ecdsa.PrivateKey, src DataSource, handler KeySigna
sigData, err := sign(cfg.defaultScheme, key, data) sigData, err := sign(cfg.defaultScheme, key, data)
if err != nil { if err != nil {
return err return nil, err
} }
sig := signature.New() sig := signature.New()
sig.SetKey((*keys.PublicKey)(&key.PublicKey).Bytes()) sig.SetKey((*keys.PublicKey)(&key.PublicKey).Bytes())
sig.SetSign(sigData) sig.SetSign(sigData)
sig.SetScheme(cfg.defaultScheme) sig.SetScheme(cfg.defaultScheme)
return sig, nil
handler(sig)
return nil
} }
func VerifyDataWithSource(dataSrc DataSource, sigSrc KeySignatureSource, opts ...SignOption) error { func VerifyData(dataSrc DataSource, sig *signature.Signature, opts ...SignOption) error {
data, err := dataForSignature(dataSrc) data, err := dataForSignature(dataSrc)
if err != nil { if err != nil {
return err return err
@ -87,36 +78,5 @@ func VerifyDataWithSource(dataSrc DataSource, sigSrc KeySignatureSource, opts ..
cfg := getConfig(opts...) cfg := getConfig(opts...)
sig := sigSrc() return verify(cfg, data, sig)
var pub *keys.PublicKey
if len(sig.Key()) != 0 {
pub, err = keys.NewPublicKeyFromBytes(sig.Key(), elliptic.P256())
if err != nil {
return fmt.Errorf("%w: %v", ErrInvalidPublicKey, err)
}
}
scheme := sig.Scheme()
if scheme == signature.Unspecified {
scheme = cfg.defaultScheme
}
if cfg.restrictScheme != signature.Unspecified && scheme != cfg.restrictScheme {
return fmt.Errorf("%w: unexpected signature scheme", ErrInvalidSignature)
}
return verify(
scheme,
(*ecdsa.PublicKey)(pub),
data,
sig.Sign(),
)
}
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...)
} }

View file

@ -6,6 +6,7 @@ import (
"crypto/rand" "crypto/rand"
"crypto/sha256" "crypto/sha256"
"crypto/sha512" "crypto/sha512"
"fmt"
"math/big" "math/big"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
@ -49,19 +50,31 @@ func sign(scheme signature.Scheme, key *ecdsa.PrivateKey, msg []byte) ([]byte, e
} }
} }
func verify(scheme signature.Scheme, key *ecdsa.PublicKey, msg []byte, sig []byte) error { func verify(cfg *cfg, msg []byte, sig *signature.Signature) error {
pub, err := keys.NewPublicKeyFromBytes(sig.Key(), elliptic.P256())
if err != nil {
return fmt.Errorf("%w: %v", ErrInvalidPublicKey, err)
}
scheme := sig.Scheme()
if scheme == signature.Unspecified {
scheme = cfg.defaultScheme
}
if cfg.restrictScheme != signature.Unspecified && scheme != cfg.restrictScheme {
return fmt.Errorf("%w: unexpected signature scheme", ErrInvalidSignature)
}
switch scheme { switch scheme {
case signature.ECDSAWithSHA512: case signature.ECDSAWithSHA512:
h := sha512.Sum512(msg) h := sha512.Sum512(msg)
r, s := unmarshalXY(sig) r, s := unmarshalXY(sig.Sign())
if r != nil && s != nil && ecdsa.Verify(key, h[:], r, s) { if r != nil && s != nil && ecdsa.Verify((*ecdsa.PublicKey)(pub), h[:], r, s) {
return nil return nil
} }
return ErrInvalidSignature return ErrInvalidSignature
case signature.RFC6979WithSHA256: case signature.RFC6979WithSHA256:
p := (*keys.PublicKey)(key)
h := sha256.Sum256(msg) h := sha256.Sum256(msg)
if p.Verify(sig, h[:]) { if pub.Verify(sig.Sign(), h[:]) {
return nil return nil
} }
return ErrInvalidSignature return ErrInvalidSignature