*: demand RFC6979 signer where appropriate

It's needed for container operations, therefore default ones for client and
pool have to be of this type as well. And it's easier to check for it before
usage.

Fixes #209.

Signed-off-by: Roman Khimov <roman@nspcc.ru>
This commit is contained in:
Roman Khimov 2023-05-22 17:05:44 +03:00
parent 2e18c3c16d
commit e99e9537a2
7 changed files with 78 additions and 27 deletions

View file

@ -4,6 +4,7 @@ import (
"context"
"crypto/tls"
"errors"
"fmt"
"time"
v2accounting "github.com/nspcc-dev/neofs-api-go/v2/accounting"
@ -49,11 +50,19 @@ type Client struct {
server neoFSAPIServer
}
var errNonNeoSigner = fmt.Errorf("%w: expected ECDSA_DETERMINISTIC_SHA256 scheme", neofscrypto.ErrIncorrectSigner)
// New creates an instance of Client initialized with the given parameters.
//
// See docs of [PrmInit] methods for details. See also [Client.Dial]/[Client.Close].
//
// Returned errors:
// - [neofscrypto.ErrIncorrectSigner]
func New(prm PrmInit) (*Client, error) {
var c = new(Client)
if prm.signer != nil && prm.signer.Scheme() != neofscrypto.ECDSA_DETERMINISTIC_SHA256 {
return nil, errNonNeoSigner
}
c.prm = prm
return c, nil
}

View file

@ -406,6 +406,7 @@ func (x *PrmContainerDelete) WithinSession(tok session.Container) {
//
// Return errors:
// - [ErrMissingContainer]
// - [neofscrypto.ErrIncorrectSigner]
//
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) error {
@ -429,6 +430,9 @@ func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) er
signer = c.defaultSigner()
}
if signer.Scheme() != neofscrypto.ECDSA_DETERMINISTIC_SHA256 {
return errNonNeoSigner
}
err := sig.Calculate(signer, data)
if err != nil {
return fmt.Errorf("calculate signature: %w", err)
@ -622,6 +626,7 @@ func (x *PrmContainerSetEACL) WithinSession(s session.Container) {
// Return errors:
// - [ErrMissingEACL]
// - [ErrMissingEACLContainer]
// - [neofscrypto.ErrIncorrectSigner]
//
// Context is required and must not be nil. It is used for network communication.
func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL) error {
@ -645,6 +650,10 @@ func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL)
signer = c.defaultSigner()
}
if signer.Scheme() != neofscrypto.ECDSA_DETERMINISTIC_SHA256 {
return errNonNeoSigner
}
err := sig.Calculate(signer, eaclV2.StableMarshal(nil))
if err != nil {
return fmt.Errorf("calculate signature: %w", err)

View file

@ -481,7 +481,13 @@ func ReadDomain(cnr Container) (res Domain) {
// can be used.
//
// See also VerifySignature.
//
// Returned errors:
// - [neofscrypto.ErrIncorrectSigner]
func CalculateSignature(dst *neofscrypto.Signature, cnr Container, signer neofscrypto.Signer) error {
if signer.Scheme() != neofscrypto.ECDSA_DETERMINISTIC_SHA256 {
return fmt.Errorf("%w: expected ECDSA_DETERMINISTIC_SHA256 scheme", neofscrypto.ErrIncorrectSigner)
}
return dst.Calculate(signer, cnr.Marshal())
}

View file

@ -336,6 +336,7 @@ func TestCalculateSignature(t *testing.T) {
var sig neofscrypto.Signature
require.Error(t, container.CalculateSignature(&sig, val, test.RandomSigner(t)))
require.NoError(t, container.CalculateSignature(&sig, val, test.RandomSignerRFC6979(t)))
var msg refs.Signature

View file

@ -1,11 +1,18 @@
package neofscrypto
import (
"errors"
"fmt"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
)
// ErrIncorrectSigner is returned from function when the signer passed to it
// is incompatible with the function requirements. This variable is intended
// to be used as documentation and for [errors.Is] purposes and MUST NOT be
// changed.
var ErrIncorrectSigner = errors.New("incorrect signer")
// Scheme represents digital signature algorithm with fixed cryptographic hash function.
//
// Negative values are reserved and depend on context (e.g. unsupported scheme).

View file

@ -1535,10 +1535,16 @@ const (
)
// NewPool creates connection pool using parameters.
//
// Returned errors:
// - [neofscrypto.ErrIncorrectSigner]
func NewPool(options InitParameters) (*Pool, error) {
if options.signer == nil {
return nil, fmt.Errorf("missed required parameter 'Signer'")
}
if options.signer.Scheme() != neofscrypto.ECDSA_DETERMINISTIC_SHA256 {
return nil, fmt.Errorf("%w: expected ECDSA_DETERMINISTIC_SHA256 scheme", neofscrypto.ErrIncorrectSigner)
}
nodesParams, err := adjustNodeParams(options.nodeParams)
if err != nil {

View file

@ -25,7 +25,7 @@ func TestBuildPoolClientFailed(t *testing.T) {
return nil, errors.New("oops")
}
mockClientBuilder2 := func(addr string) (client, error) {
mockCli := newMockClient(addr, test.RandomSigner(t))
mockCli := newMockClient(addr, test.RandomSignerRFC6979(t))
mockCli.errOnDial()
return mockCli, nil
}
@ -36,7 +36,7 @@ func TestBuildPoolClientFailed(t *testing.T) {
} {
t.Run(name, func(t *testing.T) {
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
nodeParams: []NodeParam{{1, "peer0", 1}},
}
opts.setClientBuilder(b)
@ -51,13 +51,13 @@ func TestBuildPoolClientFailed(t *testing.T) {
func TestBuildPoolCreateSessionFailed(t *testing.T) {
clientMockBuilder := func(addr string) (client, error) {
mockCli := newMockClient(addr, test.RandomSigner(t))
mockCli := newMockClient(addr, test.RandomSignerRFC6979(t))
mockCli.errOnCreateSession()
return mockCli, nil
}
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
nodeParams: []NodeParam{{1, "peer0", 1}},
}
opts.setClientBuilder(clientMockBuilder)
@ -76,7 +76,7 @@ func TestBuildPoolOneNodeFailed(t *testing.T) {
var clientKeys []neofscrypto.Signer
mockClientBuilder := func(addr string) (client, error) {
key := test.RandomSigner(t)
key := test.RandomSignerRFC6979(t)
clientKeys = append(clientKeys, key)
if addr == nodes[0].address {
@ -91,7 +91,7 @@ func TestBuildPoolOneNodeFailed(t *testing.T) {
log, err := zap.NewProduction()
require.NoError(t, err)
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
clientRebalanceInterval: 1000 * time.Millisecond,
logger: log,
nodeParams: nodes,
@ -118,6 +118,19 @@ func TestBuildPoolOneNodeFailed(t *testing.T) {
}
func TestBuildPoolZeroNodes(t *testing.T) {
opts := InitParameters{
signer: test.RandomSignerRFC6979(t),
}
_, err := NewPool(opts)
require.Error(t, err)
}
func TestBuildPoolNoSigner(t *testing.T) {
_, err := NewPool(InitParameters{})
require.Error(t, err)
}
func TestBuildPoolWrongSigner(t *testing.T) {
opts := InitParameters{
signer: test.RandomSigner(t),
}
@ -126,13 +139,13 @@ func TestBuildPoolZeroNodes(t *testing.T) {
}
func TestOneNode(t *testing.T) {
key1 := test.RandomSigner(t)
key1 := test.RandomSignerRFC6979(t)
mockClientBuilder := func(addr string) (client, error) {
return newMockClient(addr, key1), nil
}
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
nodeParams: []NodeParam{{1, "peer0", 1}},
}
opts.setClientBuilder(mockClientBuilder)
@ -152,13 +165,13 @@ func TestOneNode(t *testing.T) {
func TestTwoNodes(t *testing.T) {
var clientKeys []neofscrypto.Signer
mockClientBuilder := func(addr string) (client, error) {
key := test.RandomSigner(t)
key := test.RandomSignerRFC6979(t)
clientKeys = append(clientKeys, key)
return newMockClient(addr, key), nil
}
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
nodeParams: []NodeParam{
{1, "peer0", 1},
{1, "peer1", 1},
@ -196,7 +209,7 @@ func TestOneOfTwoFailed(t *testing.T) {
var clientKeys []neofscrypto.Signer
mockClientBuilder := func(addr string) (client, error) {
key := test.RandomSigner(t)
key := test.RandomSignerRFC6979(t)
clientKeys = append(clientKeys, key)
if addr == nodes[0].address {
@ -210,7 +223,7 @@ func TestOneOfTwoFailed(t *testing.T) {
}
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
nodeParams: nodes,
clientRebalanceInterval: 200 * time.Millisecond,
}
@ -237,7 +250,7 @@ func TestOneOfTwoFailed(t *testing.T) {
func TestTwoFailed(t *testing.T) {
var clientKeys []neofscrypto.Signer
mockClientBuilder := func(addr string) (client, error) {
key := test.RandomSigner(t)
key := test.RandomSignerRFC6979(t)
clientKeys = append(clientKeys, key)
mockCli := newMockClient(addr, key)
mockCli.errOnEndpointInfo()
@ -245,7 +258,7 @@ func TestTwoFailed(t *testing.T) {
}
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
nodeParams: []NodeParam{
{1, "peer0", 1},
{1, "peer1", 1},
@ -269,7 +282,7 @@ func TestTwoFailed(t *testing.T) {
}
func TestSessionCache(t *testing.T) {
key := test.RandomSigner(t)
key := test.RandomSignerRFC6979(t)
mockClientBuilder := func(addr string) (client, error) {
mockCli := newMockClient(addr, key)
@ -278,7 +291,7 @@ func TestSessionCache(t *testing.T) {
}
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
nodeParams: []NodeParam{
{1, "peer0", 1},
},
@ -335,7 +348,7 @@ func TestPriority(t *testing.T) {
var clientKeys []neofscrypto.Signer
mockClientBuilder := func(addr string) (client, error) {
key := test.RandomSigner(t)
key := test.RandomSignerRFC6979(t)
clientKeys = append(clientKeys, key)
if addr == nodes[0].address {
@ -348,7 +361,7 @@ func TestPriority(t *testing.T) {
}
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
nodeParams: nodes,
clientRebalanceInterval: 1500 * time.Millisecond,
}
@ -385,14 +398,14 @@ func TestPriority(t *testing.T) {
}
func TestSessionCacheWithKey(t *testing.T) {
key := test.RandomSigner(t)
key := test.RandomSignerRFC6979(t)
mockClientBuilder := func(addr string) (client, error) {
return newMockClient(addr, key), nil
}
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
nodeParams: []NodeParam{
{1, "peer0", 1},
},
@ -416,7 +429,7 @@ func TestSessionCacheWithKey(t *testing.T) {
var prm PrmObjectDelete
prm.SetAddress(oid.Address{})
anonKey := test.RandomSigner(t)
anonKey := test.RandomSignerRFC6979(t)
prm.UseSigner(anonKey)
err = pool.DeleteObject(ctx, prm)
@ -427,12 +440,12 @@ func TestSessionCacheWithKey(t *testing.T) {
func TestSessionTokenOwner(t *testing.T) {
mockClientBuilder := func(addr string) (client, error) {
key := test.RandomSigner(t)
key := test.RandomSignerRFC6979(t)
return newMockClient(addr, key), nil
}
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
nodeParams: []NodeParam{
{1, "peer0", 1},
},
@ -448,7 +461,7 @@ func TestSessionTokenOwner(t *testing.T) {
require.NoError(t, err)
t.Cleanup(p.Close)
anonKey := test.RandomSigner(t)
anonKey := test.RandomSignerRFC6979(t)
var anonOwner user.ID
require.NoError(t, user.IDFromSigner(&anonOwner, anonKey))
@ -473,7 +486,7 @@ func TestSessionTokenOwner(t *testing.T) {
}
func TestWaitPresence(t *testing.T) {
mockCli := newMockClient("", test.RandomSigner(t))
mockCli := newMockClient("", test.RandomSignerRFC6979(t))
t.Run("context canceled", func(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
@ -612,7 +625,7 @@ func TestSwitchAfterErrorThreshold(t *testing.T) {
var clientKeys []neofscrypto.Signer
mockClientBuilder := func(addr string) (client, error) {
key := test.RandomSigner(t)
key := test.RandomSignerRFC6979(t)
clientKeys = append(clientKeys, key)
if addr == nodes[0].address {
@ -626,7 +639,7 @@ func TestSwitchAfterErrorThreshold(t *testing.T) {
}
opts := InitParameters{
signer: test.RandomSigner(t),
signer: test.RandomSignerRFC6979(t),
nodeParams: nodes,
clientRebalanceInterval: 30 * time.Second,
}