diff --git a/bearer/bearer.go b/bearer/bearer.go index 86ebfd3a..198d72bd 100644 --- a/bearer/bearer.go +++ b/bearer/bearer.go @@ -1,7 +1,6 @@ package bearer import ( - "crypto/ecdsa" "errors" "fmt" @@ -9,7 +8,6 @@ import ( "github.com/nspcc-dev/neofs-api-go/v2/refs" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" - neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/user" ) @@ -245,7 +243,7 @@ func (b Token) AssertUser(id user.ID) bool { return !b.targetUserSet || b.targetUser.Equals(id) } -// Sign calculates and writes signature of the Token data using issuer's secret. +// Sign calculates and writes signature of the Token data using issuer's signer. // Returns signature calculation errors. // // Sign MUST be called if Token is going to be transmitted over @@ -255,10 +253,10 @@ func (b Token) AssertUser(id user.ID) bool { // expected to be calculated as a final stage of Token formation. // // See also VerifySignature, Issuer. -func (b *Token) Sign(key ecdsa.PrivateKey) error { +func (b *Token) Sign(signer neofscrypto.Signer) error { var sig neofscrypto.Signature - err := sig.Calculate(neofsecdsa.Signer(key), b.signedData()) + err := sig.Calculate(signer, b.signedData()) if err != nil { return err } @@ -360,9 +358,8 @@ func ResolveIssuer(b Token) (usr user.ID) { binKey := b.SigningKeyBytes() if len(binKey) != 0 { - var key neofsecdsa.PublicKey - if key.Decode(binKey) == nil { - user.IDFromKey(&usr, ecdsa.PublicKey(key)) + if err := user.IDFromKey(&usr, binKey); err != nil { + usr = user.ID{} } } diff --git a/bearer/bearer_test.go b/bearer/bearer_test.go index 53b002e3..aa7c02c9 100644 --- a/bearer/bearer_test.go +++ b/bearer/bearer_test.go @@ -261,11 +261,11 @@ func TestToken_Sign(t *testing.T) { k, err := keys.NewPrivateKey() require.NoError(t, err) + signer := neofsecdsa.Signer(k.PrivateKey) - key := k.PrivateKey val = bearertest.Token() - require.NoError(t, val.Sign(key)) + require.NoError(t, val.Sign(signer)) require.True(t, val.VerifySignature()) @@ -365,6 +365,7 @@ func TestToken_ReadFromV2(t *testing.T) { func TestResolveIssuer(t *testing.T) { k, err := keys.NewPrivateKey() require.NoError(t, err) + signer := neofsecdsa.Signer(k.PrivateKey) var val bearer.Token @@ -381,10 +382,10 @@ func TestResolveIssuer(t *testing.T) { require.Zero(t, bearer.ResolveIssuer(val)) - require.NoError(t, val.Sign(k.PrivateKey)) + require.NoError(t, val.Sign(signer)) var usr user.ID - user.IDFromKey(&usr, k.PrivateKey.PublicKey) + require.NoError(t, user.IDFromSigner(&usr, signer)) require.Equal(t, usr, bearer.ResolveIssuer(val)) } diff --git a/client/client.go b/client/client.go index bea46f6d..dd5a8eaf 100644 --- a/client/client.go +++ b/client/client.go @@ -2,7 +2,6 @@ package client import ( "context" - "crypto/ecdsa" "crypto/tls" "errors" "time" @@ -10,6 +9,7 @@ import ( v2accounting "github.com/nspcc-dev/neofs-api-go/v2/accounting" "github.com/nspcc-dev/neofs-api-go/v2/rpc" "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" ) // Client represents virtual connection to the NeoFS network to communicate @@ -148,19 +148,19 @@ func (c *Client) Close() error { type PrmInit struct { resolveNeoFSErrors bool - key ecdsa.PrivateKey + signer neofscrypto.Signer cbRespInfo func(ResponseMetaInfo) error netMagic uint64 } -// SetDefaultPrivateKey sets Client private key to be used for the protocol +// SetDefaultSigner sets Client private signer to be used for the protocol // communication by default. // -// Required for operations without custom key parametrization (see corresponding Prm* docs). -func (x *PrmInit) SetDefaultPrivateKey(key ecdsa.PrivateKey) { - x.key = key +// Required for operations without custom signer parametrization (see corresponding Prm* docs). +func (x *PrmInit) SetDefaultSigner(signer neofscrypto.Signer) { + x.signer = signer } // ResolveNeoFSFailures makes the Client to resolve failure statuses of the diff --git a/client/client_test.go b/client/client_test.go index a9f10018..2e8e9305 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -8,6 +8,8 @@ import ( "testing" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" + neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/stretchr/testify/require" ) @@ -16,11 +18,14 @@ File contains common functionality used for client package testing. */ var key, _ = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) +var signer neofscrypto.Signer var statusErr apistatus.ServerInternal func init() { statusErr.SetMessage("test status error") + + signer = neofsecdsa.SignerRFC6979(*key) } func assertStatusErr(tb testing.TB, res interface{ Status() apistatus.Status }) { @@ -30,7 +35,7 @@ func assertStatusErr(tb testing.TB, res interface{ Status() apistatus.Status }) func newClient(server neoFSAPIServer) *Client { var prm PrmInit - prm.SetDefaultPrivateKey(*key) + prm.SetDefaultSigner(signer) var c Client c.Init(prm) diff --git a/client/common.go b/client/common.go index f0e33d58..21a50fa1 100644 --- a/client/common.go +++ b/client/common.go @@ -1,14 +1,13 @@ package client import ( - "crypto/ecdsa" "fmt" "github.com/nspcc-dev/neofs-api-go/v2/refs" "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" v2session "github.com/nspcc-dev/neofs-api-go/v2/session" - "github.com/nspcc-dev/neofs-api-go/v2/signature" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" "github.com/nspcc-dev/neofs-sdk-go/version" ) @@ -75,6 +74,7 @@ const ( panicMsgMissingContext = "missing context" panicMsgMissingContainer = "missing container" panicMsgMissingObject = "missing object" + panicMsgOwnerExtract = "extract owner failed" ) // groups all the details required to send a single request and process a response to it. @@ -91,8 +91,8 @@ type contextCall struct { // ================================================== // shared parameters which are set uniformly on all calls - // request signing key - key ecdsa.PrivateKey + // request signer + signer neofscrypto.Signer // callback prior to processing the response by the client callbackResp func(ResponseMetaInfo) error @@ -112,7 +112,7 @@ type contextCall struct { // structure of the call result statusRes resCommon - // request to be signed with a key and sent + // request to be signed with a signer and sent req request // function to send a request (unary) and receive a response @@ -187,7 +187,7 @@ func (x *contextCall) writeRequest() bool { x.req.SetVerificationHeader(nil) // sign the request - x.err = signServiceMessage(&x.key, x.req) + x.err = signServiceMessage(x.signer, x.req) if x.err != nil { x.err = fmt.Errorf("sign request: %w", x.err) return false @@ -226,7 +226,7 @@ func (x *contextCall) processResponse() bool { // while verification needs marshaling // verify response signature - x.err = signature.VerifyServiceMessage(x.resp) + x.err = verifyServiceMessage(x.resp) if x.err != nil { x.err = fmt.Errorf("invalid response signature: %w", x.err) return false @@ -250,7 +250,7 @@ func (x *contextCall) processResponse() bool { // processResponse verifies response signature and converts status to an error if needed. func (c *Client) processResponse(resp responseV2) (apistatus.Status, error) { - err := signature.VerifyServiceMessage(resp) + err := verifyServiceMessage(resp) if err != nil { return nil, fmt.Errorf("invalid response signature: %w", err) } @@ -328,7 +328,7 @@ func (x *contextCall) processCall() bool { // initializes static cross-call parameters inherited from client. func (c *Client) initCallContext(ctx *contextCall) { - ctx.key = c.prm.key + ctx.signer = c.prm.signer ctx.resolveAPIFailures = c.prm.resolveNeoFSErrors ctx.callbackResp = c.prm.cbRespInfo ctx.netMagic = c.prm.netMagic diff --git a/client/container.go b/client/container.go index 09246f4b..c4a88bd1 100644 --- a/client/container.go +++ b/client/container.go @@ -13,7 +13,6 @@ import ( "github.com/nspcc-dev/neofs-sdk-go/container" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" - neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/session" "github.com/nspcc-dev/neofs-sdk-go/user" @@ -53,7 +52,7 @@ func (x *PrmContainerPut) SetSigner(signer neofscrypto.Signer) { // // Session is optional, if set the following requirements apply: // - session operation MUST be session.VerbContainerPut (ForVerb) -// - token MUST be signed using private key of the owner of the container to be saved +// - token MUST be signed using private signer of the owner of the container to be saved func (x *PrmContainerPut) WithinSession(s session.Container) { x.session = s x.sessionSet = true @@ -74,7 +73,7 @@ func (x ResContainerPut) ID() cid.ID { } func (c *Client) defaultSigner() neofscrypto.Signer { - return neofsecdsa.SignerRFC6979(c.prm.key) + return c.prm.signer } // ContainerPut sends request to save container in NeoFS. @@ -104,7 +103,7 @@ func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResCon panic(panicMsgMissingContainer) } - // TODO: check private key is set before forming the request + // TODO: check private signer is set before forming the request // sign container var cnr v2container.Container prm.cnr.WriteToV2(&cnr) @@ -657,7 +656,7 @@ func (x *PrmContainerSetEACL) SetSigner(signer neofscrypto.Signer) { // - if particular container is specified (ApplyOnlyTo), it MUST equal the container // for which extended ACL is going to be set // - session operation MUST be session.VerbContainerSetEACL (ForVerb) -// - token MUST be signed using private key of the owner of the container to be saved +// - token MUST be signed using private signer of the owner of the container to be saved func (x *PrmContainerSetEACL) WithinSession(s session.Container) { x.session = s x.sessionSet = true diff --git a/client/doc.go b/client/doc.go index 35a3a075..5c096d69 100644 --- a/client/doc.go +++ b/client/doc.go @@ -11,7 +11,7 @@ Create client instance: Initialize client state: var prm client.PrmInit - prm.SetDefaultPrivateKey(key) + prm.SetDefaultSigner(signer) // ... c.Init(prm) @@ -20,7 +20,7 @@ Connect to the NeoFS server: var prm client.PrmDial prm.SetServerURI("localhost:8080") - prm.SetDefaultPrivateKey(key) + prm.SetDefaultSigner(signer) // ... err := c.Dial(prm) diff --git a/client/example_container_put_test.go b/client/example_container_put_test.go index 52084cbc..63fc87b2 100644 --- a/client/example_container_put_test.go +++ b/client/example_container_put_test.go @@ -11,6 +11,7 @@ import ( "github.com/nspcc-dev/neofs-sdk-go/container" "github.com/nspcc-dev/neofs-sdk-go/container/acl" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/user" ) @@ -25,13 +26,17 @@ func ExampleClient_ContainerPut() { panic(err) } - // decode account from user's key - user.IDFromKey(&accountID, key.PrivateKey.PublicKey) + signer := neofsecdsa.SignerRFC6979(key.PrivateKey) + + // decode account from user's signer + if err = user.IDFromSigner(&accountID, signer); err != nil { + panic(err) + } // prepare client var prmInit client.PrmInit - prmInit.SetDefaultPrivateKey(key.PrivateKey) // private key for request signing - prmInit.ResolveNeoFSFailures() // enable erroneous status parsing + prmInit.SetDefaultSigner(signer) // private signer for request signing + prmInit.ResolveNeoFSFailures() // enable erroneous status parsing var c client.Client c.Init(prmInit) diff --git a/client/netmap.go b/client/netmap.go index 89289359..656a50c9 100644 --- a/client/netmap.go +++ b/client/netmap.go @@ -247,7 +247,7 @@ func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResN req.SetBody(&body) c.prepareRequest(&req, &meta) - err := signServiceMessage(&c.prm.key, &req) + err := signServiceMessage(c.prm.signer, &req) if err != nil { return nil, fmt.Errorf("sign request: %w", err) } diff --git a/client/netmap_test.go b/client/netmap_test.go index aba9db51..5a17703d 100644 --- a/client/netmap_test.go +++ b/client/netmap_test.go @@ -8,7 +8,6 @@ import ( v2netmap "github.com/nspcc-dev/neofs-api-go/v2/netmap" "github.com/nspcc-dev/neofs-api-go/v2/session" - "github.com/nspcc-dev/neofs-api-go/v2/signature" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" "github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/stretchr/testify/require" @@ -26,7 +25,7 @@ type serverNetMap struct { } func (x *serverNetMap) netMapSnapshot(ctx context.Context, req v2netmap.SnapshotRequest) (*v2netmap.SnapshotResponse, error) { - err := signature.VerifyServiceMessage(&req) + err := verifyServiceMessage(&req) if err != nil { return nil, err } @@ -52,7 +51,7 @@ func (x *serverNetMap) netMapSnapshot(ctx context.Context, req v2netmap.Snapshot resp.SetMetaHeader(&meta) if x.signResponse { - err = signServiceMessage(key, &resp) + err = signServiceMessage(signer, &resp) if err != nil { panic(fmt.Sprintf("sign response: %v", err)) } diff --git a/client/object_delete.go b/client/object_delete.go index 721bfa5c..be2a52ad 100644 --- a/client/object_delete.go +++ b/client/object_delete.go @@ -2,7 +2,6 @@ package client import ( "context" - "crypto/ecdsa" "fmt" "github.com/nspcc-dev/neofs-api-go/v2/acl" @@ -14,6 +13,7 @@ import ( "github.com/nspcc-dev/neofs-sdk-go/bearer" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "github.com/nspcc-dev/neofs-sdk-go/session" ) @@ -27,7 +27,7 @@ type PrmObjectDelete struct { addr v2refs.Address keySet bool - key ecdsa.PrivateKey + signer neofscrypto.Signer } // WithinSession specifies session within which object should be read. @@ -72,11 +72,11 @@ func (x *PrmObjectDelete) ByID(id oid.ID) { x.addr.SetObjectID(&idV2) } -// UseKey specifies private key to sign the requests. -// If key is not provided, then Client default key is used. -func (x *PrmObjectDelete) UseKey(key ecdsa.PrivateKey) { +// UseSigner specifies private signer to sign the requests. +// If signer is not provided, then Client default signer is used. +func (x *PrmObjectDelete) UseSigner(signer neofscrypto.Signer) { x.keySet = true - x.key = key + x.signer = signer } // WithXHeaders specifies list of extended headers (string key-value pairs) @@ -140,12 +140,12 @@ func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObj req.SetBody(&prm.body) c.prepareRequest(&req, &prm.meta) - key := c.prm.key - if prm.keySet { - key = prm.key + signer := prm.signer + if signer == nil { + signer = c.prm.signer } - err := signServiceMessage(&key, &req) + err := signServiceMessage(signer, &req) if err != nil { return nil, fmt.Errorf("sign request: %w", err) } diff --git a/client/object_get.go b/client/object_get.go index 1949be79..95dcb9f8 100644 --- a/client/object_get.go +++ b/client/object_get.go @@ -2,7 +2,6 @@ package client import ( "context" - "crypto/ecdsa" "errors" "fmt" "io" @@ -16,6 +15,7 @@ import ( "github.com/nspcc-dev/neofs-sdk-go/bearer" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" "github.com/nspcc-dev/neofs-sdk-go/object" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "github.com/nspcc-dev/neofs-sdk-go/session" @@ -91,7 +91,7 @@ func (x *prmObjectRead) ByID(id oid.ID) { type PrmObjectGet struct { prmObjectRead - key *ecdsa.PrivateKey + signer neofscrypto.Signer } // ResObjectGet groups the final result values of ObjectGetInit operation. @@ -119,10 +119,10 @@ type ObjectReader struct { remainingPayloadLen int } -// UseKey specifies private key to sign the requests. -// If key is not provided, then Client default key is used. -func (x *PrmObjectGet) UseKey(key ecdsa.PrivateKey) { - x.key = &key +// UseSigner specifies private signer to sign the requests. +// If signer is not provided, then Client default signer is used. +func (x *PrmObjectGet) UseSigner(signer neofscrypto.Signer) { + x.signer = signer } // ReadHeader reads header of the object. Result means success. @@ -320,12 +320,12 @@ func (c *Client) ObjectGetInit(ctx context.Context, prm PrmObjectGet) (*ObjectRe req.SetBody(&body) c.prepareRequest(&req, &prm.meta) - key := prm.key - if key == nil { - key = &c.prm.key + signer := prm.signer + if signer == nil { + signer = c.prm.signer } - err := signServiceMessage(key, &req) + err := signServiceMessage(signer, &req) if err != nil { return nil, fmt.Errorf("sign request: %w", err) } @@ -350,15 +350,13 @@ func (c *Client) ObjectGetInit(ctx context.Context, prm PrmObjectGet) (*ObjectRe type PrmObjectHead struct { prmObjectRead - keySet bool - key ecdsa.PrivateKey + signer neofscrypto.Signer } -// UseKey specifies private key to sign the requests. -// If key is not provided, then Client default key is used. -func (x *PrmObjectHead) UseKey(key ecdsa.PrivateKey) { - x.keySet = true - x.key = key +// UseSigner specifies private signer to sign the requests. +// If signer is not provided, then Client default signer is used. +func (x *PrmObjectHead) UseSigner(signer neofscrypto.Signer) { + x.signer = signer } // ResObjectHead groups resulting values of ObjectHead operation. @@ -431,13 +429,13 @@ func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectH req.SetBody(&body) c.prepareRequest(&req, &prm.meta) - key := c.prm.key - if prm.keySet { - key = prm.key + signer := prm.signer + if signer == nil { + signer = c.prm.signer } // sign the request - err := signServiceMessage(&key, &req) + err := signServiceMessage(signer, &req) if err != nil { return nil, fmt.Errorf("sign request: %w", err) } @@ -475,7 +473,7 @@ func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectH type PrmObjectRange struct { prmObjectRead - key *ecdsa.PrivateKey + signer neofscrypto.Signer rng v2object.Range } @@ -492,10 +490,10 @@ func (x *PrmObjectRange) SetLength(ln uint64) { x.rng.SetLength(ln) } -// UseKey specifies private key to sign the requests. -// If key is not provided, then Client default key is used. -func (x *PrmObjectRange) UseKey(key ecdsa.PrivateKey) { - x.key = &key +// UseSigner specifies private signer to sign the requests. +// If signer is not provided, then Client default signer is used. +func (x *PrmObjectRange) UseSigner(signer neofscrypto.Signer) { + x.signer = signer } // ResObjectRange groups the final result values of ObjectRange operation. @@ -690,12 +688,12 @@ func (c *Client) ObjectRangeInit(ctx context.Context, prm PrmObjectRange) (*Obje req.SetBody(&body) c.prepareRequest(&req, &prm.meta) - key := prm.key - if key == nil { - key = &c.prm.key + signer := prm.signer + if signer == nil { + signer = c.prm.signer } - err := signServiceMessage(key, &req) + err := signServiceMessage(signer, &req) if err != nil { return nil, fmt.Errorf("sign request: %w", err) } diff --git a/client/object_hash.go b/client/object_hash.go index e5a20080..0e487ba7 100644 --- a/client/object_hash.go +++ b/client/object_hash.go @@ -2,7 +2,6 @@ package client import ( "context" - "crypto/ecdsa" "fmt" "github.com/nspcc-dev/neofs-api-go/v2/acl" @@ -14,6 +13,7 @@ import ( "github.com/nspcc-dev/neofs-sdk-go/bearer" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "github.com/nspcc-dev/neofs-sdk-go/session" ) @@ -28,15 +28,13 @@ type PrmObjectHash struct { addr v2refs.Address - keySet bool - key ecdsa.PrivateKey + signer neofscrypto.Signer } -// UseKey specifies private key to sign the requests. -// If key is not provided, then Client default key is used. -func (x *PrmObjectHash) UseKey(key ecdsa.PrivateKey) { - x.keySet = true - x.key = key +// UseSigner specifies private signer to sign the requests. +// If signer is not provided, then Client default signer is used. +func (x *PrmObjectHash) UseSigner(signer neofscrypto.Signer) { + x.signer = signer } // MarkLocal tells the server to execute the operation locally. @@ -186,12 +184,12 @@ func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectH c.prepareRequest(&req, &prm.meta) req.SetBody(&prm.body) - key := c.prm.key - if prm.keySet { - key = prm.key + signer := prm.signer + if signer == nil { + signer = c.prm.signer } - err := signServiceMessage(&key, &req) + err := signServiceMessage(signer, &req) if err != nil { return nil, fmt.Errorf("sign request: %w", err) } diff --git a/client/object_put.go b/client/object_put.go index 2d10863c..ce5cf8cc 100644 --- a/client/object_put.go +++ b/client/object_put.go @@ -2,7 +2,6 @@ package client import ( "context" - "crypto/ecdsa" "errors" "fmt" "io" @@ -14,6 +13,7 @@ import ( v2session "github.com/nspcc-dev/neofs-api-go/v2/session" "github.com/nspcc-dev/neofs-sdk-go/bearer" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" "github.com/nspcc-dev/neofs-sdk-go/object" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "github.com/nspcc-dev/neofs-sdk-go/session" @@ -22,7 +22,7 @@ import ( // PrmObjectPutInit groups parameters of ObjectPutInit operation. type PrmObjectPutInit struct { copyNum uint32 - key *ecdsa.PrivateKey + signer neofscrypto.Signer meta v2session.RequestMetaHeader } @@ -56,9 +56,9 @@ type ObjectWriter struct { Close() error } - key *ecdsa.PrivateKey - res ResObjectPut - err error + signer neofscrypto.Signer + res ResObjectPut + err error chunkCalled bool @@ -68,10 +68,10 @@ type ObjectWriter struct { partChunk v2object.PutObjectPartChunk } -// UseKey specifies private key to sign the requests. -// If key is not provided, then Client default key is used. -func (x *PrmObjectPutInit) UseKey(key ecdsa.PrivateKey) { - x.key = &key +// UseSigner specifies private signer to sign the requests. +// If signer is not provided, then Client default signer is used. +func (x *PrmObjectPutInit) UseSigner(signer neofscrypto.Signer) { + x.signer = signer } // WithBearerToken attaches bearer token to be used for the operation. @@ -116,7 +116,7 @@ func (x *ObjectWriter) WriteHeader(hdr object.Object) bool { x.req.GetBody().SetObjectPart(&x.partInit) x.req.SetVerificationHeader(nil) - x.err = signServiceMessage(x.key, &x.req) + x.err = signServiceMessage(x.signer, &x.req) if x.err != nil { x.err = fmt.Errorf("sign message: %w", x.err) return false @@ -158,7 +158,7 @@ func (x *ObjectWriter) WritePayloadChunk(chunk []byte) bool { x.partChunk.SetChunk(chunk[:ln]) x.req.SetVerificationHeader(nil) - x.err = signServiceMessage(x.key, &x.req) + x.err = signServiceMessage(x.signer, &x.req) if x.err != nil { x.err = fmt.Errorf("sign message: %w", x.err) return false @@ -250,9 +250,9 @@ func (c *Client) ObjectPutInit(ctx context.Context, prm PrmObjectPutInit) (*Obje return nil, fmt.Errorf("open stream: %w", err) } - w.key = &c.prm.key - if prm.key != nil { - w.key = prm.key + w.signer = prm.signer + if w.signer == nil { + w.signer = c.prm.signer } w.cancelCtxStream = cancel w.client = c diff --git a/client/object_search.go b/client/object_search.go index 3fc495c1..1880e0fa 100644 --- a/client/object_search.go +++ b/client/object_search.go @@ -2,7 +2,6 @@ package client import ( "context" - "crypto/ecdsa" "errors" "fmt" "io" @@ -16,6 +15,7 @@ import ( "github.com/nspcc-dev/neofs-sdk-go/bearer" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" "github.com/nspcc-dev/neofs-sdk-go/object" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "github.com/nspcc-dev/neofs-sdk-go/session" @@ -25,7 +25,7 @@ import ( type PrmObjectSearch struct { meta v2session.RequestMetaHeader - key *ecdsa.PrivateKey + signer neofscrypto.Signer cnrSet bool cnrID cid.ID @@ -69,10 +69,10 @@ func (x *PrmObjectSearch) WithXHeaders(hs ...string) { writeXHeadersToMeta(hs, &x.meta) } -// UseKey specifies private key to sign the requests. -// If key is not provided, then Client default key is used. -func (x *PrmObjectSearch) UseKey(key ecdsa.PrivateKey) { - x.key = &key +// UseSigner specifies private signer to sign the requests. +// If signer is not provided, then Client default signer is used. +func (x *PrmObjectSearch) UseSigner(signer neofscrypto.Signer) { + x.signer = signer } // InContainer specifies the container in which to look for objects. @@ -241,12 +241,12 @@ func (c *Client) ObjectSearchInit(ctx context.Context, prm PrmObjectSearch) (*Ob req.SetBody(&body) c.prepareRequest(&req, &prm.meta) - key := prm.key - if key == nil { - key = &c.prm.key + signer := prm.signer + if signer == nil { + signer = c.prm.signer } - err := signServiceMessage(key, &req) + err := signServiceMessage(signer, &req) if err != nil { return nil, fmt.Errorf("sign request: %w", err) } diff --git a/client/object_search_test.go b/client/object_search_test.go index d5c19fd7..6b89dbc7 100644 --- a/client/object_search_test.go +++ b/client/object_search_test.go @@ -1,7 +1,6 @@ package client import ( - "crypto/ecdsa" "errors" "fmt" "io" @@ -10,6 +9,8 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" v2object "github.com/nspcc-dev/neofs-api-go/v2/object" "github.com/nspcc-dev/neofs-api-go/v2/refs" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" + neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test" "github.com/stretchr/testify/require" @@ -85,7 +86,7 @@ func TestObjectIterate(t *testing.T) { p, resp := testListReaderResponse(t) var actual []oid.ID - resp.stream = &singleStreamResponder{key: p, idList: [][]oid.ID{ids}} + resp.stream = &singleStreamResponder{signer: p, idList: [][]oid.ID{ids}} require.NoError(t, resp.Iterate(func(id oid.ID) bool { actual = append(actual, id) return len(actual) == 2 @@ -108,27 +109,27 @@ func TestObjectIterate(t *testing.T) { }) } -func testListReaderResponse(t *testing.T) (*ecdsa.PrivateKey, *ObjectListReader) { +func testListReaderResponse(t *testing.T) (neofscrypto.Signer, *ObjectListReader) { p, err := keys.NewPrivateKey() require.NoError(t, err) - return &p.PrivateKey, &ObjectListReader{ + return neofsecdsa.Signer(p.PrivateKey), &ObjectListReader{ cancelCtxStream: func() {}, client: &Client{}, tail: nil, } } -func newSearchStream(key *ecdsa.PrivateKey, endError error, idList ...[]oid.ID) *singleStreamResponder { +func newSearchStream(signer neofscrypto.Signer, endError error, idList ...[]oid.ID) *singleStreamResponder { return &singleStreamResponder{ - key: key, + signer: signer, endError: endError, idList: idList, } } type singleStreamResponder struct { - key *ecdsa.PrivateKey + signer neofscrypto.Signer n int endError error idList [][]oid.ID @@ -153,7 +154,7 @@ func (s *singleStreamResponder) Read(resp *v2object.SearchResponse) error { } resp.SetBody(&body) - err := signServiceMessage(s.key, resp) + err := signServiceMessage(s.signer, resp) if err != nil { panic(fmt.Errorf("error: %w", err)) } diff --git a/client/session.go b/client/session.go index 66875a21..c7465dca 100644 --- a/client/session.go +++ b/client/session.go @@ -2,12 +2,12 @@ package client import ( "context" - "crypto/ecdsa" "github.com/nspcc-dev/neofs-api-go/v2/refs" rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc" "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" v2session "github.com/nspcc-dev/neofs-api-go/v2/session" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" "github.com/nspcc-dev/neofs-sdk-go/user" ) @@ -17,8 +17,7 @@ type PrmSessionCreate struct { exp uint64 - keySet bool - key ecdsa.PrivateKey + signer neofscrypto.Signer } // SetExp sets number of the last NepFS epoch in the lifetime of the session after which it will be expired. @@ -26,11 +25,10 @@ func (x *PrmSessionCreate) SetExp(exp uint64) { x.exp = exp } -// UseKey specifies private key to sign the requests and compute token owner. -// If key is not provided, then Client default key is used. -func (x *PrmSessionCreate) UseKey(key ecdsa.PrivateKey) { - x.keySet = true - x.key = key +// UseSigner specifies private signer to sign the requests and compute token owner. +// If signer is not provided, then Client default signer is used. +func (x *PrmSessionCreate) UseSigner(signer neofscrypto.Signer) { + x.signer = signer } // ResSessionCreate groups resulting values of SessionCreate operation. @@ -83,12 +81,10 @@ func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResS panic(panicMsgMissingContext) } - ownerKey := c.prm.key.PublicKey - if prm.keySet { - ownerKey = prm.key.PublicKey - } var ownerID user.ID - user.IDFromKey(&ownerID, ownerKey) + if err := user.IDFromSigner(&ownerID, prm.signer); err != nil { + panic(panicMsgOwnerExtract) + } var ownerIDV2 refs.OwnerID ownerID.WriteToV2(&ownerIDV2) @@ -111,8 +107,9 @@ func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResS ) c.initCallContext(&cc) - if prm.keySet { - cc.key = prm.key + cc.signer = prm.signer + if cc.signer == nil { + cc.signer = c.prm.signer } cc.meta = prm.prmCommonMeta diff --git a/client/sign.go b/client/sign.go index 51409612..fdb61f9e 100644 --- a/client/sign.go +++ b/client/sign.go @@ -1,7 +1,6 @@ package client import ( - "crypto/ecdsa" "errors" "fmt" @@ -13,6 +12,7 @@ import ( "github.com/nspcc-dev/neofs-api-go/v2/reputation" "github.com/nspcc-dev/neofs-api-go/v2/session" "github.com/nspcc-dev/neofs-api-go/v2/util/signature" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" ) type serviceRequest interface { @@ -32,7 +32,7 @@ type stableMarshaler interface { StableSize() int } -type StableMarshalerWrapper struct { +type stableMarshalerWrapper struct { SM stableMarshaler } @@ -115,7 +115,7 @@ func (r *responseVerificationHeader) setOrigin(m stableMarshaler) { } } -func (s StableMarshalerWrapper) ReadSignedData(buf []byte) ([]byte, error) { +func (s stableMarshalerWrapper) ReadSignedData(buf []byte) ([]byte, error) { if s.SM != nil { return s.SM.StableMarshal(buf), nil } @@ -123,7 +123,7 @@ func (s StableMarshalerWrapper) ReadSignedData(buf []byte) ([]byte, error) { return nil, nil } -func (s StableMarshalerWrapper) SignedDataSize() int { +func (s stableMarshalerWrapper) SignedDataSize() int { if s.SM != nil { return s.SM.StableSize() } @@ -131,7 +131,8 @@ func (s StableMarshalerWrapper) SignedDataSize() int { return 0 } -func signServiceMessage(key *ecdsa.PrivateKey, msg interface{}) error { +// signServiceMessage signing request or response messages which can be sent or received from neofs endpoint. +func signServiceMessage(signer neofscrypto.Signer, msg interface{}) error { var ( body, meta, verifyOrigin stableMarshaler verifyHdr verificationHeader @@ -169,18 +170,18 @@ func signServiceMessage(key *ecdsa.PrivateKey, msg interface{}) error { if verifyOrigin == nil { // sign session message body - if err := signServiceMessagePart(key, body, verifyHdr.SetBodySignature); err != nil { + if err := signServiceMessagePart(signer, body, verifyHdr.SetBodySignature); err != nil { return fmt.Errorf("could not sign body: %w", err) } } // sign meta header - if err := signServiceMessagePart(key, meta, verifyHdr.SetMetaSignature); err != nil { + if err := signServiceMessagePart(signer, meta, verifyHdr.SetMetaSignature); err != nil { return fmt.Errorf("could not sign meta header: %w", err) } // sign verification header origin - if err := signServiceMessagePart(key, verifyOrigin, verifyHdr.SetOriginSignature); err != nil { + if err := signServiceMessagePart(signer, verifyOrigin, verifyHdr.SetOriginSignature); err != nil { return fmt.Errorf("could not sign origin of verification header: %w", err) } @@ -193,22 +194,22 @@ func signServiceMessage(key *ecdsa.PrivateKey, msg interface{}) error { return nil } -func signServiceMessagePart(key *ecdsa.PrivateKey, part stableMarshaler, sigWrite func(*refs.Signature)) error { - var sig *refs.Signature +func signServiceMessagePart(signer neofscrypto.Signer, part stableMarshaler, sigWrite func(*refs.Signature)) error { + var sig neofscrypto.Signature + var sigv2 refs.Signature - // sign part - if err := signature.SignDataWithHandler( - key, - &StableMarshalerWrapper{part}, - func(s *refs.Signature) { - sig = s - }, - ); err != nil { - return err + m := &stableMarshalerWrapper{part} + data, err := m.ReadSignedData(nil) + if err != nil { + return fmt.Errorf("ReadSignedData %w", err) } - // write part signature - sigWrite(sig) + if err = sig.Calculate(signer, data); err != nil { + return fmt.Errorf("calculate %w", err) + } + + sig.WriteToV2(&sigv2) + sigWrite(&sigv2) return nil } @@ -283,13 +284,13 @@ func verifyMatryoshkaLevel(body stableMarshaler, meta metaHeader, verify verific func verifyServiceMessagePart(part stableMarshaler, sigRdr func() *refs.Signature, buf []byte) error { return signature.VerifyDataWithSource( - &StableMarshalerWrapper{part}, + &stableMarshalerWrapper{part}, sigRdr, signature.WithBuffer(buf), ) } -func serviceMessageBody(req interface{}) stableMarshaler { +func serviceMessageBody(req any) stableMarshaler { switch v := req.(type) { default: panic(fmt.Sprintf("unsupported session message %T", req)) diff --git a/client/sign_test.go b/client/sign_test.go index 1c281117..f8af2fd5 100644 --- a/client/sign_test.go +++ b/client/sign_test.go @@ -6,6 +6,7 @@ import ( "github.com/nspcc-dev/neofs-api-go/v2/accounting" "github.com/nspcc-dev/neofs-api-go/v2/session" crypto "github.com/nspcc-dev/neofs-crypto" + neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/stretchr/testify/require" ) @@ -30,7 +31,7 @@ func TestBalanceResponse(t *testing.T) { require.NoError(t, err) // sign request - require.NoError(t, signServiceMessage(key, req)) + require.NoError(t, signServiceMessage(neofsecdsa.Signer(*key), req)) // verification must pass require.NoError(t, verifyServiceMessage(req)) @@ -41,7 +42,7 @@ func TestBalanceResponse(t *testing.T) { req.SetMetaHeader(meta) // sign request - require.NoError(t, signServiceMessage(key, req)) + require.NoError(t, signServiceMessage(neofsecdsa.Signer(*key), req)) // verification must pass require.NoError(t, verifyServiceMessage(req)) diff --git a/object/fmt.go b/object/fmt.go index 6d99ec61..ded05c10 100644 --- a/object/fmt.go +++ b/object/fmt.go @@ -2,7 +2,6 @@ package object import ( "bytes" - "crypto/ecdsa" "crypto/sha256" "errors" "fmt" @@ -96,13 +95,13 @@ func VerifyID(obj *Object) error { // CalculateAndSetSignature signs id with provided key and sets that signature to // the object. -func CalculateAndSetSignature(key ecdsa.PrivateKey, obj *Object) error { +func CalculateAndSetSignature(signer neofscrypto.Signer, obj *Object) error { oID, set := obj.ID() if !set { return errOIDNotSet } - sig, err := oID.CalculateIDSignature(key) + sig, err := oID.CalculateIDSignature(signer) if err != nil { return err } @@ -132,12 +131,12 @@ func (o *Object) VerifyIDSignature() bool { } // SetIDWithSignature sets object identifier and signature. -func SetIDWithSignature(key ecdsa.PrivateKey, obj *Object) error { +func SetIDWithSignature(signer neofscrypto.Signer, obj *Object) error { if err := CalculateAndSetID(obj); err != nil { return fmt.Errorf("could not set identifier: %w", err) } - if err := CalculateAndSetSignature(key, obj); err != nil { + if err := CalculateAndSetSignature(signer, obj); err != nil { return fmt.Errorf("could not set signature: %w", err) } @@ -145,10 +144,10 @@ func SetIDWithSignature(key ecdsa.PrivateKey, obj *Object) error { } // SetVerificationFields calculates and sets all verification fields of the object. -func SetVerificationFields(key ecdsa.PrivateKey, obj *Object) error { +func SetVerificationFields(signer neofscrypto.Signer, obj *Object) error { CalculateAndSetPayloadChecksum(obj) - return SetIDWithSignature(key, obj) + return SetIDWithSignature(signer, obj) } // CheckVerificationFields checks all verification fields of the object. diff --git a/object/fmt_test.go b/object/fmt_test.go index b7470807..dab931b3 100644 --- a/object/fmt_test.go +++ b/object/fmt_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/stretchr/testify/require" ) @@ -19,7 +20,7 @@ func TestVerificationFields(t *testing.T) { p, err := keys.NewPrivateKey() require.NoError(t, err) - require.NoError(t, SetVerificationFields(p.PrivateKey, obj)) + require.NoError(t, SetVerificationFields(neofsecdsa.Signer(p.PrivateKey), obj)) require.NoError(t, CheckVerificationFields(obj)) diff --git a/object/id/id.go b/object/id/id.go index a7edb8c4..ab923b8f 100644 --- a/object/id/id.go +++ b/object/id/id.go @@ -1,14 +1,12 @@ package oid import ( - "crypto/ecdsa" "crypto/sha256" "fmt" "github.com/mr-tron/base58" "github.com/nspcc-dev/neofs-api-go/v2/refs" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" - neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" ) // ID represents NeoFS object identifier in a container. @@ -117,7 +115,7 @@ func (id ID) String() string { } // CalculateIDSignature signs object id with provided key. -func (id ID) CalculateIDSignature(key ecdsa.PrivateKey) (neofscrypto.Signature, error) { +func (id ID) CalculateIDSignature(signer neofscrypto.Signer) (neofscrypto.Signature, error) { data, err := id.Marshal() if err != nil { return neofscrypto.Signature{}, fmt.Errorf("marshal ID: %w", err) @@ -125,7 +123,7 @@ func (id ID) CalculateIDSignature(key ecdsa.PrivateKey) (neofscrypto.Signature, var sig neofscrypto.Signature - return sig, sig.Calculate(neofsecdsa.Signer(key), data) + return sig, sig.Calculate(signer, data) } // Marshal marshals ID into a protobuf binary form. diff --git a/pool/cache_test.go b/pool/cache_test.go index 1d425c67..7a59558e 100644 --- a/pool/cache_test.go +++ b/pool/cache_test.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/session" sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test" "github.com/stretchr/testify/require" @@ -28,7 +29,7 @@ func TestSessionCache_GetUnmodifiedToken(t *testing.T) { require.True(t, ok) check(t, value, "before sign") - err = value.Sign(pk.PrivateKey) + err = value.Sign(neofsecdsa.Signer(pk.PrivateKey)) require.NoError(t, err) value, ok = cache.Get(key) diff --git a/pool/doc.go b/pool/doc.go index b7d54eb4..ace8a04c 100644 --- a/pool/doc.go +++ b/pool/doc.go @@ -11,7 +11,7 @@ This InitParameters will make pool use 192.168.130.71 node while it is healthy. : var prm pool.InitParameters - prm.SetKey(key) + prm.SetSigner(signer) prm.AddNode(NewNodeParam(1, "192.168.130.71", 1)) prm.AddNode(NewNodeParam(2, "192.168.130.72", 9)) prm.AddNode(NewNodeParam(2, "192.168.130.73", 1)) diff --git a/pool/mock_test.go b/pool/mock_test.go index f0cb661b..c0f35897 100644 --- a/pool/mock_test.go +++ b/pool/mock_test.go @@ -2,7 +2,6 @@ package pool import ( "context" - "crypto/ecdsa" "errors" "github.com/google/uuid" @@ -12,7 +11,7 @@ import ( apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" "github.com/nspcc-dev/neofs-sdk-go/container" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" - neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" "github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/object" @@ -21,7 +20,7 @@ import ( ) type mockClient struct { - key ecdsa.PrivateKey + signer neofscrypto.Signer clientStatusMonitor errorOnDial bool @@ -31,9 +30,9 @@ type mockClient struct { stOnGetObject apistatus.Status } -func newMockClient(addr string, key ecdsa.PrivateKey) *mockClient { +func newMockClient(addr string, signer neofscrypto.Signer) *mockClient { return &mockClient{ - key: key, + signer: signer, clientStatusMonitor: newClientStatusMonitor(addr, 10), } } @@ -65,11 +64,13 @@ func (m *mockClient) statusOnGetObject(st apistatus.Status) { m.stOnGetObject = st } -func newToken(key ecdsa.PrivateKey) *session.Object { +func newToken(signer neofscrypto.Signer) *session.Object { var tok session.Object tok.SetID(uuid.New()) - pk := neofsecdsa.PublicKey(key.PublicKey) - tok.SetAuthKey(&pk) + + public := signer.Public() + + tok.SetAuthKey(public) return &tok } @@ -159,7 +160,7 @@ func (m *mockClient) sessionCreate(context.Context, prmCreateSession) (resCreate return resCreateSession{}, m.handleError(nil, errors.New("error")) } - tok := newToken(m.key) + tok := newToken(m.signer) var v2tok sessionv2.Token tok.WriteToV2(&v2tok) diff --git a/pool/pool.go b/pool/pool.go index 2f2f1ab8..a5007318 100644 --- a/pool/pool.go +++ b/pool/pool.go @@ -3,7 +3,6 @@ package pool import ( "bytes" "context" - "crypto/ecdsa" "errors" "fmt" "io" @@ -14,13 +13,13 @@ import ( "time" "github.com/google/uuid" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neofs-sdk-go/accounting" "github.com/nspcc-dev/neofs-sdk-go/bearer" sdkClient "github.com/nspcc-dev/neofs-sdk-go/client" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" "github.com/nspcc-dev/neofs-sdk-go/container" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/netmap" @@ -227,7 +226,7 @@ type clientWrapper struct { // wrapperPrm is params to create clientWrapper. type wrapperPrm struct { address string - key ecdsa.PrivateKey + signer neofscrypto.Signer dialTimeout time.Duration streamTimeout time.Duration errorThreshold uint32 @@ -240,9 +239,9 @@ func (x *wrapperPrm) setAddress(address string) { x.address = address } -// setKey sets sdkClient.Client private key to be used for the protocol communication by default. -func (x *wrapperPrm) setKey(key ecdsa.PrivateKey) { - x.key = key +// setSigner sets sdkClient.Client private signer to be used for the protocol communication by default. +func (x *wrapperPrm) setSigner(signer neofscrypto.Signer) { + x.signer = signer } // setDialTimeout sets the timeout for connection to be established. @@ -275,7 +274,7 @@ func (x *wrapperPrm) setResponseInfoCallback(f func(sdkClient.ResponseMetaInfo) func newWrapper(prm wrapperPrm) *clientWrapper { var cl sdkClient.Client var prmInit sdkClient.PrmInit - prmInit.SetDefaultPrivateKey(prm.key) + prmInit.SetDefaultSigner(prm.signer) prmInit.SetResponseInfoCallback(prm.responseInfoCallback) cl.Init(prmInit) @@ -324,7 +323,7 @@ func (c *clientWrapper) restartIfUnhealthy(ctx context.Context) (healthy, change var cl sdkClient.Client var prmInit sdkClient.PrmInit - prmInit.SetDefaultPrivateKey(c.prm.key) + prmInit.SetDefaultSigner(c.prm.signer) prmInit.SetResponseInfoCallback(c.prm.responseInfoCallback) cl.Init(prmInit) @@ -619,8 +618,8 @@ func (c *clientWrapper) objectPut(ctx context.Context, prm PrmObjectPut) (oid.ID if prm.stoken != nil { cliPrm.WithinSession(*prm.stoken) } - if prm.key != nil { - cliPrm.UseKey(*prm.key) + if prm.signer != nil { + cliPrm.UseSigner(prm.signer) } if prm.btoken != nil { cliPrm.WithBearerToken(*prm.btoken) @@ -709,8 +708,8 @@ func (c *clientWrapper) objectDelete(ctx context.Context, prm PrmObjectDelete) e cliPrm.WithBearerToken(*prm.btoken) } - if prm.key != nil { - cliPrm.UseKey(*prm.key) + if prm.signer != nil { + cliPrm.UseSigner(prm.signer) } start := time.Now() @@ -745,8 +744,8 @@ func (c *clientWrapper) objectGet(ctx context.Context, prm PrmObjectGet) (ResGet cliPrm.WithBearerToken(*prm.btoken) } - if prm.key != nil { - cliPrm.UseKey(*prm.key) + if prm.signer != nil { + cliPrm.UseSigner(prm.signer) } var res ResGetObject @@ -801,8 +800,8 @@ func (c *clientWrapper) objectHead(ctx context.Context, prm PrmObjectHead) (obje cliPrm.WithBearerToken(*prm.btoken) } - if prm.key != nil { - cliPrm.UseKey(*prm.key) + if prm.signer != nil { + cliPrm.UseSigner(prm.signer) } var obj object.Object @@ -845,8 +844,8 @@ func (c *clientWrapper) objectRange(ctx context.Context, prm PrmObjectRange) (Re cliPrm.WithBearerToken(*prm.btoken) } - if prm.key != nil { - cliPrm.UseKey(*prm.key) + if prm.signer != nil { + cliPrm.UseSigner(prm.signer) } start := time.Now() @@ -884,8 +883,8 @@ func (c *clientWrapper) objectSearch(ctx context.Context, prm PrmObjectSearch) ( cliPrm.WithBearerToken(*prm.btoken) } - if prm.key != nil { - cliPrm.UseKey(*prm.key) + if prm.signer != nil { + cliPrm.UseSigner(prm.signer) } res, err := cl.ObjectSearchInit(ctx, cliPrm) @@ -905,7 +904,7 @@ func (c *clientWrapper) sessionCreate(ctx context.Context, prm prmCreateSession) var cliPrm sdkClient.PrmSessionCreate cliPrm.SetExp(prm.exp) - cliPrm.UseKey(prm.key) + cliPrm.UseSigner(prm.signer) start := time.Now() res, err := cl.SessionCreate(ctx, cliPrm) @@ -1022,7 +1021,7 @@ type RequestInfo struct { // InitParameters contains values used to initialize connection Pool. type InitParameters struct { - key *ecdsa.PrivateKey + signer neofscrypto.Signer logger *zap.Logger nodeDialTimeout time.Duration nodeStreamTimeout time.Duration @@ -1036,9 +1035,9 @@ type InitParameters struct { clientBuilder clientBuilder } -// SetKey specifies default key to be used for the protocol communication by default. -func (x *InitParameters) SetKey(key *ecdsa.PrivateKey) { - x.key = key +// SetSigner specifies default signer to be used for the protocol communication by default. +func (x *InitParameters) SetSigner(signer neofscrypto.Signer) { + x.signer = signer } // SetLogger specifies logger. @@ -1209,15 +1208,15 @@ func (x *prmContext) useVerb(verb session.ObjectVerb) { } type prmCommon struct { - key *ecdsa.PrivateKey + signer neofscrypto.Signer btoken *bearer.Token stoken *session.Object } -// UseKey specifies private key to sign the requests. -// If key is not provided, then Pool default key is used. -func (x *prmCommon) UseKey(key *ecdsa.PrivateKey) { - x.key = key +// UseSigner specifies private signer to sign the requests. +// If signer is not provided, then Pool default signer is used. +func (x *prmCommon) UseSigner(signer neofscrypto.Signer) { + x.signer = signer } // UseBearer attaches bearer token to be used for the operation. @@ -1483,8 +1482,8 @@ func (x *PrmBalanceGet) SetAccount(id user.ID) { // prmEndpointInfo groups parameters of sessionCreate operation. type prmCreateSession struct { - exp uint64 - key ecdsa.PrivateKey + exp uint64 + signer neofscrypto.Signer } // setExp sets number of the last NeoFS epoch in the lifetime of the session after which it will be expired. @@ -1492,10 +1491,10 @@ func (x *prmCreateSession) setExp(exp uint64) { x.exp = exp } -// useKey specifies owner private key for session token. -// If key is not provided, then Pool default key is used. -func (x *prmCreateSession) useKey(key ecdsa.PrivateKey) { - x.key = key +// useSigner specifies owner private signer for session token. +// If signer is not provided, then Pool default signer is used. +func (x *prmCreateSession) useSigner(signer neofscrypto.Signer) { + x.signer = signer } // prmEndpointInfo groups parameters of endpointInfo operation. @@ -1534,7 +1533,7 @@ type resCreateSession struct { // See pool package overview to get some examples. type Pool struct { innerPools []*innerPool - key *ecdsa.PrivateKey + signer neofscrypto.Signer cancel context.CancelFunc closedCh chan struct{} cache *sessionCache @@ -1562,8 +1561,8 @@ const ( // NewPool creates connection pool using parameters. func NewPool(options InitParameters) (*Pool, error) { - if options.key == nil { - return nil, fmt.Errorf("missed required parameter 'Key'") + if options.signer == nil { + return nil, fmt.Errorf("missed required parameter 'Signer'") } nodesParams, err := adjustNodeParams(options.nodeParams) @@ -1579,7 +1578,7 @@ func NewPool(options InitParameters) (*Pool, error) { fillDefaultInitParams(&options, cache) pool := &Pool{ - key: options.key, + signer: options.signer, cache: cache, logger: options.logger, stokenDuration: options.sessionExpirationDuration, @@ -1619,7 +1618,7 @@ func (p *Pool) Dial(ctx context.Context) error { } var st session.Object - err := initSessionForDuration(ctx, &st, clients[j], p.rebalanceParams.sessionExpirationDuration, *p.key) + err := initSessionForDuration(ctx, &st, clients[j], p.rebalanceParams.sessionExpirationDuration, p.signer) if err != nil { clients[j].setUnhealthy() if p.logger != nil { @@ -1629,7 +1628,7 @@ func (p *Pool) Dial(ctx context.Context) error { continue } - _ = p.cache.Put(formCacheKey(addr, p.key), st) + _ = p.cache.Put(formCacheKey(addr, p.signer), st) atLeastOneHealthy = true } source := rand.NewSource(time.Now().UnixNano()) @@ -1683,7 +1682,7 @@ func fillDefaultInitParams(params *InitParameters, cache *sessionCache) { params.setClientBuilder(func(addr string) client { var prm wrapperPrm prm.setAddress(addr) - prm.setKey(*params.key) + prm.setSigner(params.signer) prm.setDialTimeout(params.nodeDialTimeout) prm.setStreamTimeout(params.nodeStreamTimeout) prm.setErrorThreshold(params.errorThreshold) @@ -1849,11 +1848,11 @@ func (p *innerPool) connection() (client, error) { return nil, errors.New("no healthy client") } -func formCacheKey(address string, key *ecdsa.PrivateKey) string { - buf := make([]byte, 33) - copy(buf, (*keys.PublicKey)(&key.PublicKey).Bytes()) +func formCacheKey(address string, signer neofscrypto.Signer) string { + b := make([]byte, signer.Public().MaxEncodedSize()) + signer.Public().Encode(b) - return address + string(buf) + return address + string(b) } func (p *Pool) checkSessionTokenErr(err error, address string) bool { @@ -1869,7 +1868,7 @@ func (p *Pool) checkSessionTokenErr(err error, address string) bool { return false } -func initSessionForDuration(ctx context.Context, dst *session.Object, c client, dur uint64, ownerKey ecdsa.PrivateKey) error { +func initSessionForDuration(ctx context.Context, dst *session.Object, c client, dur uint64, signer neofscrypto.Signer) error { ni, err := c.networkInfo(ctx, prmNetworkInfo{}) if err != nil { return err @@ -1885,7 +1884,7 @@ func initSessionForDuration(ctx context.Context, dst *session.Object, c client, } var prm prmCreateSession prm.setExp(exp) - prm.useKey(ownerKey) + prm.useSigner(signer) res, err := c.sessionCreate(ctx, prm) if err != nil { @@ -1923,7 +1922,7 @@ type callContext struct { endpoint string // request signer - key *ecdsa.PrivateKey + signer neofscrypto.Signer // flag to open default session if session token is missing sessionDefault bool @@ -1940,10 +1939,10 @@ func (p *Pool) initCallContext(ctx *callContext, cfg prmCommon, prmCtx prmContex return err } - ctx.key = cfg.key - if ctx.key == nil { - // use pool key if caller didn't specify its own - ctx.key = p.key + ctx.signer = cfg.signer + if ctx.signer == nil { + // use pool signer if caller didn't specify its own + ctx.signer = p.signer } ctx.endpoint = cp.address() @@ -1968,12 +1967,12 @@ func (p *Pool) initCallContext(ctx *callContext, cfg prmCommon, prmCtx prmContex // opens new session or uses cached one. // Must be called only on initialized callContext with set sessionTarget. func (p *Pool) openDefaultSession(ctx *callContext) error { - cacheKey := formCacheKey(ctx.endpoint, ctx.key) + cacheKey := formCacheKey(ctx.endpoint, ctx.signer) tok, ok := p.cache.Get(cacheKey) if !ok { // init new session - err := initSessionForDuration(ctx, &tok, ctx.client, p.stokenDuration, *ctx.key) + err := initSessionForDuration(ctx, &tok, ctx.client, p.stokenDuration, ctx.signer) if err != nil { return fmt.Errorf("session API client: %w", err) } @@ -1990,7 +1989,7 @@ func (p *Pool) openDefaultSession(ctx *callContext) error { } // sign the token - if err := tok.Sign(*ctx.key); err != nil { + if err := tok.Sign(ctx.signer); err != nil { return fmt.Errorf("sign token of the opened session: %w", err) } @@ -2017,10 +2016,10 @@ func (p *Pool) call(ctx *callContext, f func() error) error { return err } -// fillAppropriateKey use pool key if caller didn't specify its own. -func (p *Pool) fillAppropriateKey(prm *prmCommon) { - if prm.key == nil { - prm.key = p.key +// fillAppropriateSigner use pool signer if caller didn't specify its own. +func (p *Pool) fillAppropriateSigner(prm *prmCommon) { + if prm.signer == nil { + prm.signer = p.signer } } @@ -2035,7 +2034,7 @@ func (p *Pool) PutObject(ctx context.Context, prm PrmObjectPut) (oid.ID, error) prmCtx.useVerb(session.VerbObjectPut) prmCtx.useContainer(cnr) - p.fillAppropriateKey(&prm.prmCommon) + p.fillAppropriateSigner(&prm.prmCommon) var ctxCall callContext @@ -2087,7 +2086,7 @@ func (p *Pool) DeleteObject(ctx context.Context, prm PrmObjectDelete) error { } } - p.fillAppropriateKey(&prm.prmCommon) + p.fillAppropriateSigner(&prm.prmCommon) var cc callContext @@ -2148,7 +2147,7 @@ type ResGetObject struct { // // Main return value MUST NOT be processed on an erroneous return. func (p *Pool) GetObject(ctx context.Context, prm PrmObjectGet) (ResGetObject, error) { - p.fillAppropriateKey(&prm.prmCommon) + p.fillAppropriateSigner(&prm.prmCommon) var cc callContext cc.Context = ctx @@ -2171,7 +2170,7 @@ func (p *Pool) GetObject(ctx context.Context, prm PrmObjectGet) (ResGetObject, e // // Main return value MUST NOT be processed on an erroneous return. func (p *Pool) HeadObject(ctx context.Context, prm PrmObjectHead) (object.Object, error) { - p.fillAppropriateKey(&prm.prmCommon) + p.fillAppropriateSigner(&prm.prmCommon) var cc callContext @@ -2221,7 +2220,7 @@ func (x *ResObjectRange) Close() error { // // Main return value MUST NOT be processed on an erroneous return. func (p *Pool) ObjectRange(ctx context.Context, prm PrmObjectRange) (ResObjectRange, error) { - p.fillAppropriateKey(&prm.prmCommon) + p.fillAppropriateSigner(&prm.prmCommon) var cc callContext cc.Context = ctx @@ -2283,7 +2282,7 @@ func (x *ResObjectSearch) Close() { // // Main return value MUST NOT be processed on an erroneous return. func (p *Pool) SearchObjects(ctx context.Context, prm PrmObjectSearch) (ResObjectSearch, error) { - p.fillAppropriateKey(&prm.prmCommon) + p.fillAppropriateSigner(&prm.prmCommon) var cc callContext diff --git a/pool/pool_test.go b/pool/pool_test.go index 1663965d..ee8f27f2 100644 --- a/pool/pool_test.go +++ b/pool/pool_test.go @@ -2,7 +2,6 @@ package pool import ( "context" - "crypto/ecdsa" "errors" "strconv" "testing" @@ -11,6 +10,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/object" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" @@ -22,13 +22,13 @@ import ( func TestBuildPoolClientFailed(t *testing.T) { mockClientBuilder := func(addr string) client { - mockCli := newMockClient(addr, *newPrivateKey(t)) + mockCli := newMockClient(addr, newSigner(t)) mockCli.errOnDial() return mockCli } opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), nodeParams: []NodeParam{{1, "peer0", 1}}, } opts.setClientBuilder(mockClientBuilder) @@ -41,13 +41,13 @@ func TestBuildPoolClientFailed(t *testing.T) { func TestBuildPoolCreateSessionFailed(t *testing.T) { clientMockBuilder := func(addr string) client { - mockCli := newMockClient(addr, *newPrivateKey(t)) + mockCli := newMockClient(addr, newSigner(t)) mockCli.errOnCreateSession() return mockCli } opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), nodeParams: []NodeParam{{1, "peer0", 1}}, } opts.setClientBuilder(clientMockBuilder) @@ -58,10 +58,10 @@ func TestBuildPoolCreateSessionFailed(t *testing.T) { require.Error(t, err) } -func newPrivateKey(t *testing.T) *ecdsa.PrivateKey { +func newSigner(t *testing.T) neofsecdsa.Signer { p, err := keys.NewPrivateKey() require.NoError(t, err) - return &p.PrivateKey + return neofsecdsa.Signer(p.PrivateKey) } func TestBuildPoolOneNodeFailed(t *testing.T) { @@ -70,24 +70,24 @@ func TestBuildPoolOneNodeFailed(t *testing.T) { {2, "peer1", 1}, } - var clientKeys []*ecdsa.PrivateKey + var clientKeys []neofscrypto.Signer mockClientBuilder := func(addr string) client { - key := newPrivateKey(t) + key := newSigner(t) clientKeys = append(clientKeys, key) if addr == nodes[0].address { - mockCli := newMockClient(addr, *key) + mockCli := newMockClient(addr, key) mockCli.errOnEndpointInfo() return mockCli } - return newMockClient(addr, *key) + return newMockClient(addr, key) } log, err := zap.NewProduction() require.NoError(t, err) opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), clientRebalanceInterval: 1000 * time.Millisecond, logger: log, nodeParams: nodes, @@ -100,14 +100,14 @@ func TestBuildPoolOneNodeFailed(t *testing.T) { require.NoError(t, err) t.Cleanup(clientPool.Close) - expectedAuthKey := neofsecdsa.PublicKey(clientKeys[1].PublicKey) + expectedAuthKey := clientKeys[1].Public() condition := func() bool { cp, err := clientPool.connection() if err != nil { return false } - st, _ := clientPool.cache.Get(formCacheKey(cp.address(), clientPool.key)) - return st.AssertAuthKey(&expectedAuthKey) + st, _ := clientPool.cache.Get(formCacheKey(cp.address(), clientPool.signer)) + return st.AssertAuthKey(expectedAuthKey) } require.Never(t, condition, 900*time.Millisecond, 100*time.Millisecond) require.Eventually(t, condition, 3*time.Second, 300*time.Millisecond) @@ -115,20 +115,20 @@ func TestBuildPoolOneNodeFailed(t *testing.T) { func TestBuildPoolZeroNodes(t *testing.T) { opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), } _, err := NewPool(opts) require.Error(t, err) } func TestOneNode(t *testing.T) { - key1 := newPrivateKey(t) + key1 := newSigner(t) mockClientBuilder := func(addr string) client { - return newMockClient(addr, *key1) + return newMockClient(addr, key1) } opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), nodeParams: []NodeParam{{1, "peer0", 1}}, } opts.setClientBuilder(mockClientBuilder) @@ -141,21 +141,21 @@ func TestOneNode(t *testing.T) { cp, err := pool.connection() require.NoError(t, err) - st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key)) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.signer)) expectedAuthKey := neofsecdsa.PublicKey(key1.PublicKey) require.True(t, st.AssertAuthKey(&expectedAuthKey)) } func TestTwoNodes(t *testing.T) { - var clientKeys []*ecdsa.PrivateKey + var clientKeys []neofscrypto.Signer mockClientBuilder := func(addr string) client { - key := newPrivateKey(t) + key := newSigner(t) clientKeys = append(clientKeys, key) - return newMockClient(addr, *key) + return newMockClient(addr, key) } opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), nodeParams: []NodeParam{ {1, "peer0", 1}, {1, "peer1", 1}, @@ -171,14 +171,14 @@ func TestTwoNodes(t *testing.T) { cp, err := pool.connection() require.NoError(t, err) - st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key)) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.signer)) require.True(t, assertAuthKeyForAny(st, clientKeys)) } -func assertAuthKeyForAny(st session.Object, clientKeys []*ecdsa.PrivateKey) bool { +func assertAuthKeyForAny(st session.Object, clientKeys []neofscrypto.Signer) bool { for _, key := range clientKeys { - expectedAuthKey := neofsecdsa.PublicKey(key.PublicKey) - if st.AssertAuthKey(&expectedAuthKey) { + expectedAuthKey := key.Public() + if st.AssertAuthKey(expectedAuthKey) { return true } } @@ -191,23 +191,23 @@ func TestOneOfTwoFailed(t *testing.T) { {9, "peer1", 1}, } - var clientKeys []*ecdsa.PrivateKey + var clientKeys []neofscrypto.Signer mockClientBuilder := func(addr string) client { - key := newPrivateKey(t) + key := newSigner(t) clientKeys = append(clientKeys, key) if addr == nodes[0].address { - return newMockClient(addr, *key) + return newMockClient(addr, key) } - mockCli := newMockClient(addr, *key) + mockCli := newMockClient(addr, key) mockCli.errOnEndpointInfo() mockCli.errOnNetworkInfo() return mockCli } opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), nodeParams: nodes, clientRebalanceInterval: 200 * time.Millisecond, } @@ -226,23 +226,23 @@ func TestOneOfTwoFailed(t *testing.T) { for i := 0; i < 5; i++ { cp, err := pool.connection() require.NoError(t, err) - st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key)) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.signer)) require.True(t, assertAuthKeyForAny(st, clientKeys)) } } func TestTwoFailed(t *testing.T) { - var clientKeys []*ecdsa.PrivateKey + var clientKeys []neofscrypto.Signer mockClientBuilder := func(addr string) client { - key := newPrivateKey(t) + key := newSigner(t) clientKeys = append(clientKeys, key) - mockCli := newMockClient(addr, *key) + mockCli := newMockClient(addr, key) mockCli.errOnEndpointInfo() return mockCli } opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), nodeParams: []NodeParam{ {1, "peer0", 1}, {1, "peer1", 1}, @@ -266,17 +266,17 @@ func TestTwoFailed(t *testing.T) { } func TestSessionCache(t *testing.T) { - key := newPrivateKey(t) + key := newSigner(t) expectedAuthKey := neofsecdsa.PublicKey(key.PublicKey) mockClientBuilder := func(addr string) client { - mockCli := newMockClient(addr, *key) + mockCli := newMockClient(addr, key) mockCli.statusOnGetObject(apistatus.SessionTokenNotFound{}) return mockCli } opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), nodeParams: []NodeParam{ {1, "peer0", 1}, }, @@ -296,7 +296,7 @@ func TestSessionCache(t *testing.T) { // cache must contain session token cp, err := pool.connection() require.NoError(t, err) - st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key)) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.signer)) require.True(t, st.AssertAuthKey(&expectedAuthKey)) var prm PrmObjectGet @@ -309,7 +309,7 @@ func TestSessionCache(t *testing.T) { // cache must not contain session token cp, err = pool.connection() require.NoError(t, err) - _, ok := pool.cache.Get(formCacheKey(cp.address(), pool.key)) + _, ok := pool.cache.Get(formCacheKey(cp.address(), pool.signer)) require.False(t, ok) var prm2 PrmObjectPut @@ -321,7 +321,7 @@ func TestSessionCache(t *testing.T) { // cache must contain session token cp, err = pool.connection() require.NoError(t, err) - st, _ = pool.cache.Get(formCacheKey(cp.address(), pool.key)) + st, _ = pool.cache.Get(formCacheKey(cp.address(), pool.signer)) require.True(t, st.AssertAuthKey(&expectedAuthKey)) } @@ -331,22 +331,22 @@ func TestPriority(t *testing.T) { {2, "peer1", 100}, } - var clientKeys []*ecdsa.PrivateKey + var clientKeys []neofscrypto.Signer mockClientBuilder := func(addr string) client { - key := newPrivateKey(t) + key := newSigner(t) clientKeys = append(clientKeys, key) if addr == nodes[0].address { - mockCli := newMockClient(addr, *key) + mockCli := newMockClient(addr, key) mockCli.errOnEndpointInfo() return mockCli } - return newMockClient(addr, *key) + return newMockClient(addr, key) } opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), nodeParams: nodes, clientRebalanceInterval: 1500 * time.Millisecond, } @@ -361,20 +361,20 @@ func TestPriority(t *testing.T) { require.NoError(t, err) t.Cleanup(pool.Close) - expectedAuthKey1 := neofsecdsa.PublicKey(clientKeys[0].PublicKey) + expectedAuthKey1 := clientKeys[0].Public() firstNode := func() bool { cp, err := pool.connection() require.NoError(t, err) - st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key)) - return st.AssertAuthKey(&expectedAuthKey1) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.signer)) + return st.AssertAuthKey(expectedAuthKey1) } - expectedAuthKey2 := neofsecdsa.PublicKey(clientKeys[1].PublicKey) + expectedAuthKey2 := clientKeys[1].Public() secondNode := func() bool { cp, err := pool.connection() require.NoError(t, err) - st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key)) - return st.AssertAuthKey(&expectedAuthKey2) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.signer)) + return st.AssertAuthKey(expectedAuthKey2) } require.Never(t, secondNode, time.Second, 200*time.Millisecond) @@ -383,15 +383,15 @@ func TestPriority(t *testing.T) { } func TestSessionCacheWithKey(t *testing.T) { - key := newPrivateKey(t) + key := newSigner(t) expectedAuthKey := neofsecdsa.PublicKey(key.PublicKey) mockClientBuilder := func(addr string) client { - return newMockClient(addr, *key) + return newMockClient(addr, key) } opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), nodeParams: []NodeParam{ {1, "peer0", 1}, }, @@ -410,13 +410,13 @@ func TestSessionCacheWithKey(t *testing.T) { // cache must contain session token cp, err := pool.connection() require.NoError(t, err) - st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.key)) + st, _ := pool.cache.Get(formCacheKey(cp.address(), pool.signer)) require.True(t, st.AssertAuthKey(&expectedAuthKey)) var prm PrmObjectDelete prm.SetAddress(oid.Address{}) - anonKey := newPrivateKey(t) - prm.UseKey(anonKey) + anonKey := newSigner(t) + prm.UseSigner(anonKey) err = pool.DeleteObject(ctx, prm) require.NoError(t, err) @@ -426,12 +426,12 @@ func TestSessionCacheWithKey(t *testing.T) { func TestSessionTokenOwner(t *testing.T) { mockClientBuilder := func(addr string) client { - key := newPrivateKey(t) - return newMockClient(addr, *key) + key := newSigner(t) + return newMockClient(addr, key) } opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), nodeParams: []NodeParam{ {1, "peer0", 1}, }, @@ -447,12 +447,12 @@ func TestSessionTokenOwner(t *testing.T) { require.NoError(t, err) t.Cleanup(p.Close) - anonKey := newPrivateKey(t) + anonKey := newSigner(t) var anonOwner user.ID - user.IDFromKey(&anonOwner, anonKey.PublicKey) + require.NoError(t, user.IDFromSigner(&anonOwner, anonKey)) var prm prmCommon - prm.UseKey(anonKey) + prm.UseSigner(anonKey) var prmCtx prmContext prmCtx.useDefaultSession() @@ -472,7 +472,7 @@ func TestSessionTokenOwner(t *testing.T) { } func TestWaitPresence(t *testing.T) { - mockCli := newMockClient("", *newPrivateKey(t)) + mockCli := newMockClient("", newSigner(t)) t.Run("context canceled", func(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) @@ -620,23 +620,23 @@ func TestSwitchAfterErrorThreshold(t *testing.T) { errorThreshold := 5 - var clientKeys []*ecdsa.PrivateKey + var clientKeys []neofscrypto.Signer mockClientBuilder := func(addr string) client { - key := newPrivateKey(t) + key := newSigner(t) clientKeys = append(clientKeys, key) if addr == nodes[0].address { - mockCli := newMockClient(addr, *key) + mockCli := newMockClient(addr, key) mockCli.setThreshold(uint32(errorThreshold)) mockCli.statusOnGetObject(apistatus.ServerInternal{}) return mockCli } - return newMockClient(addr, *key) + return newMockClient(addr, key) } opts := InitParameters{ - key: newPrivateKey(t), + signer: newSigner(t), nodeParams: nodes, clientRebalanceInterval: 30 * time.Second, } diff --git a/pool/sampler_test.go b/pool/sampler_test.go index 5ea23260..45f8e189 100644 --- a/pool/sampler_test.go +++ b/pool/sampler_test.go @@ -50,10 +50,10 @@ func TestHealthyReweight(t *testing.T) { cache, err := newCache() require.NoError(t, err) - client1 := newMockClient(names[0], *newPrivateKey(t)) + client1 := newMockClient(names[0], newSigner(t)) client1.errOnDial() - client2 := newMockClient(names[1], *newPrivateKey(t)) + client2 := newMockClient(names[1], newSigner(t)) inner := &innerPool{ sampler: newSampler(weights, rand.NewSource(0)), @@ -62,7 +62,7 @@ func TestHealthyReweight(t *testing.T) { p := &Pool{ innerPools: []*innerPool{inner}, cache: cache, - key: newPrivateKey(t), + signer: newSigner(t), rebalanceParams: rebalanceParameters{nodesParams: []*nodesParam{{weights: weights}}}, } @@ -81,7 +81,7 @@ func TestHealthyReweight(t *testing.T) { // enabled first node again inner.lock.Lock() - inner.clients[0] = newMockClient(names[0], *newPrivateKey(t)) + inner.clients[0] = newMockClient(names[0], newSigner(t)) inner.lock.Unlock() p.updateInnerNodesHealth(context.TODO(), 0, buffer) @@ -104,8 +104,8 @@ func TestHealthyNoReweight(t *testing.T) { inner := &innerPool{ sampler: sampl, clients: []client{ - newMockClient(names[0], *newPrivateKey(t)), - newMockClient(names[1], *newPrivateKey(t)), + newMockClient(names[0], newSigner(t)), + newMockClient(names[1], newSigner(t)), }, } p := &Pool{ diff --git a/session/common.go b/session/common.go index ce9d2ca8..0f91cb71 100644 --- a/session/common.go +++ b/session/common.go @@ -2,7 +2,6 @@ package session import ( "bytes" - "crypto/ecdsa" "errors" "fmt" @@ -10,7 +9,6 @@ import ( "github.com/nspcc-dev/neofs-api-go/v2/refs" "github.com/nspcc-dev/neofs-api-go/v2/session" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" - neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/user" ) @@ -155,13 +153,16 @@ func (x commonData) signedData(w contextWriter) []byte { return x.fillBody(w).StableMarshal(nil) } -func (x *commonData) sign(key ecdsa.PrivateKey, w contextWriter) error { - user.IDFromKey(&x.issuer, key.PublicKey) +func (x *commonData) sign(signer neofscrypto.Signer, w contextWriter) error { + if err := user.IDFromSigner(&x.issuer, signer); err != nil { + return err + } + x.issuerSet = true var sig neofscrypto.Signature - err := sig.Calculate(neofsecdsa.Signer(key), x.signedData(w)) + err := sig.Calculate(signer, x.signedData(w)) if err != nil { return err } diff --git a/session/container.go b/session/container.go index 29773a7f..31a60e82 100644 --- a/session/container.go +++ b/session/container.go @@ -1,7 +1,6 @@ package session import ( - "crypto/ecdsa" "errors" "fmt" @@ -136,8 +135,8 @@ func (x *Container) UnmarshalJSON(data []byte) error { // expected to be calculated as a final stage of Container formation. // // See also VerifySignature. -func (x *Container) Sign(key ecdsa.PrivateKey) error { - return x.sign(key, x.writeContext) +func (x *Container) Sign(signer neofscrypto.Signer) error { + return x.sign(signer, x.writeContext) } // VerifySignature checks if Container signature is presented and valid. diff --git a/session/container_test.go b/session/container_test.go index 2d4c66bd..45c9b23d 100644 --- a/session/container_test.go +++ b/session/container_test.go @@ -12,7 +12,6 @@ import ( v2session "github.com/nspcc-dev/neofs-api-go/v2/session" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" - neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/session" sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test" "github.com/nspcc-dev/neofs-sdk-go/user" @@ -56,7 +55,7 @@ func TestContainerProtocolV2(t *testing.T) { // Session key signer := randSigner() - authKey := neofsecdsa.PublicKey(signer.PublicKey) + authKey := signer.Public() binAuthKey := make([]byte, authKey.MaxEncodedSize()) binAuthKey = binAuthKey[:authKey.Encode(binAuthKey)] restoreAuthKey := func() { @@ -173,7 +172,7 @@ func TestContainerProtocolV2(t *testing.T) { }, restore: restoreAuthKey, assert: func(val session.Container) { - require.True(t, val.AssertAuthKey(&authKey)) + require.True(t, val.AssertAuthKey(authKey)) }, breakSign: func(m *v2session.Token) { body := m.GetBody() @@ -271,7 +270,7 @@ func TestContainer_WriteToV2(t *testing.T) { require.NoError(t, val.Sign(signer)) var usr user.ID - user.IDFromKey(&usr, signer.PublicKey) + require.NoError(t, user.IDFromSigner(&usr, signer)) var usrV2 refs.OwnerID usr.WriteToV2(&usrV2) @@ -516,7 +515,7 @@ func TestIssuedBy(t *testing.T) { signer = randSigner() ) - user.IDFromKey(&issuer, signer.PublicKey) + require.NoError(t, user.IDFromSigner(&issuer, signer)) require.False(t, session.IssuedBy(token, issuer)) @@ -534,7 +533,7 @@ func TestContainer_Issuer(t *testing.T) { var issuer user.ID - user.IDFromKey(&issuer, signer.PublicKey) + require.NoError(t, user.IDFromSigner(&issuer, signer)) require.True(t, token.Issuer().Equals(issuer)) } @@ -556,14 +555,14 @@ func TestContainer_VerifyDataSignature(t *testing.T) { rand.Read(data) var sig neofscrypto.Signature - require.NoError(t, sig.Calculate(neofsecdsa.SignerRFC6979(signer), data)) + require.NoError(t, sig.Calculate(signer, data)) var sigV2 refs.Signature sig.WriteToV2(&sigV2) require.False(t, tok.VerifySessionDataSignature(data, sigV2.GetSign())) - tok.SetAuthKey((*neofsecdsa.PublicKeyRFC6979)(&signer.PublicKey)) + tok.SetAuthKey(signer.Public()) require.True(t, tok.VerifySessionDataSignature(data, sigV2.GetSign())) require.False(t, tok.VerifySessionDataSignature(append(data, 1), sigV2.GetSign())) require.False(t, tok.VerifySessionDataSignature(data, append(sigV2.GetSign(), 1))) diff --git a/session/object.go b/session/object.go index 88569515..3f832e0a 100644 --- a/session/object.go +++ b/session/object.go @@ -1,13 +1,13 @@ package session import ( - "crypto/ecdsa" "errors" "fmt" "github.com/nspcc-dev/neofs-api-go/v2/refs" "github.com/nspcc-dev/neofs-api-go/v2/session" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" ) @@ -162,8 +162,8 @@ func (x *Object) UnmarshalJSON(data []byte) error { // expected to be calculated as a final stage of Object formation. // // See also VerifySignature. -func (x *Object) Sign(key ecdsa.PrivateKey) error { - return x.sign(key, x.writeContext) +func (x *Object) Sign(signer neofscrypto.Signer) error { + return x.sign(signer, x.writeContext) } // VerifySignature checks if Object signature is presented and valid. diff --git a/session/object_test.go b/session/object_test.go index fe60c78f..891b36c7 100644 --- a/session/object_test.go +++ b/session/object_test.go @@ -1,7 +1,6 @@ package session_test import ( - "crypto/ecdsa" "fmt" "math" "math/rand" @@ -23,18 +22,17 @@ import ( "github.com/stretchr/testify/require" ) -func randSigner() ecdsa.PrivateKey { +func randSigner() neofscrypto.Signer { k, err := keys.NewPrivateKey() if err != nil { panic(fmt.Sprintf("generate private key: %v", err)) } - return k.PrivateKey + return neofsecdsa.SignerRFC6979(k.PrivateKey) } func randPublicKey() neofscrypto.PublicKey { - k := randSigner().PublicKey - return (*neofsecdsa.PublicKey)(&k) + return randSigner().Public() } func TestObjectProtocolV2(t *testing.T) { @@ -73,7 +71,7 @@ func TestObjectProtocolV2(t *testing.T) { // Session key signer := randSigner() - authKey := neofsecdsa.PublicKey(signer.PublicKey) + authKey := signer.Public() binAuthKey := make([]byte, authKey.MaxEncodedSize()) binAuthKey = binAuthKey[:authKey.Encode(binAuthKey)] restoreAuthKey := func() { @@ -195,7 +193,7 @@ func TestObjectProtocolV2(t *testing.T) { }, restore: restoreAuthKey, assert: func(val session.Object) { - require.True(t, val.AssertAuthKey(&authKey)) + require.True(t, val.AssertAuthKey(authKey)) }, breakSign: func(m *v2session.Token) { body := m.GetBody() @@ -298,7 +296,7 @@ func TestObject_WriteToV2(t *testing.T) { require.NoError(t, val.Sign(signer)) var usr user.ID - user.IDFromKey(&usr, signer.PublicKey) + require.NoError(t, user.IDFromSigner(&usr, signer)) var usrV2 refs.OwnerID usr.WriteToV2(&usrV2) @@ -634,7 +632,7 @@ func TestObject_Issuer(t *testing.T) { var issuer user.ID - user.IDFromKey(&issuer, signer.PublicKey) + require.NoError(t, user.IDFromSigner(&issuer, signer)) require.True(t, token.Issuer().Equals(issuer)) } diff --git a/session/test/session.go b/session/test/session.go index 95c5d805..fbca0673 100644 --- a/session/test/session.go +++ b/session/test/session.go @@ -8,12 +8,13 @@ import ( "github.com/google/uuid" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test" "github.com/nspcc-dev/neofs-sdk-go/session" ) -var p ecdsa.PrivateKey +var signer neofscrypto.Signer func init() { k, err := keys.NewPrivateKey() @@ -21,7 +22,7 @@ func init() { panic(err) } - p = k.PrivateKey + signer = neofsecdsa.SignerRFC6979(k.PrivateKey) } // Container returns random session.Container. @@ -52,7 +53,7 @@ func Container() *session.Container { func ContainerSigned() *session.Container { tok := Container() - err := tok.Sign(p) + err := tok.Sign(signer) if err != nil { panic(err) } @@ -89,7 +90,7 @@ func Object() *session.Object { func ObjectSigned() *session.Object { tok := Object() - err := tok.Sign(p) + err := tok.Sign(signer) if err != nil { panic(err) } diff --git a/user/test/id.go b/user/test/id.go index adf9d0c0..c6a11ac6 100644 --- a/user/test/id.go +++ b/user/test/id.go @@ -2,6 +2,7 @@ package usertest import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" "github.com/nspcc-dev/neofs-sdk-go/user" ) @@ -13,7 +14,9 @@ func ID() *user.ID { } var x user.ID - user.IDFromKey(&x, key.PrivateKey.PublicKey) + if err = user.IDFromSigner(&x, neofsecdsa.Signer(key.PrivateKey)); err != nil { + return nil + } return &x } diff --git a/user/util.go b/user/util.go index ddd9657a..e51314fb 100644 --- a/user/util.go +++ b/user/util.go @@ -1,12 +1,29 @@ package user import ( - "crypto/ecdsa" + "fmt" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" + neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" ) // IDFromKey forms the ID using script hash calculated for the given key. -func IDFromKey(id *ID, key ecdsa.PublicKey) { - id.SetScriptHash((*keys.PublicKey)(&key).GetScriptHash()) +func IDFromKey(id *ID, key []byte) error { + var pk keys.PublicKey + if err := pk.DecodeBytes(key); err != nil { + return fmt.Errorf("IDFromKey %v", err) + } + + id.SetScriptHash(pk.GetScriptHash()) + return nil +} + +// IDFromSigner forms the ID using script hash calculated for the given key. +func IDFromSigner(id *ID, signer neofscrypto.Signer) error { + public := signer.Public() + + key := make([]byte, public.MaxEncodedSize()) + key = key[:public.Encode(key)] + + return IDFromKey(id, key) } diff --git a/user/util_test.go b/user/util_test.go index 437d4490..cf48973b 100644 --- a/user/util_test.go +++ b/user/util_test.go @@ -1,7 +1,6 @@ package user_test import ( - "crypto/ecdsa" "crypto/elliptic" "encoding/hex" "testing" @@ -18,7 +17,7 @@ func TestIDFromKey(t *testing.T) { var id user.ID - user.IDFromKey(&id, ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}) + user.IDFromKey(&id, rawPub) require.Equal(t, "NNLi44dJNXtDNSBkofB48aTVYtb1zZrNEs", id.EncodeToString()) }