From 9142c778c7d8dbce5c9d46465b481e007f223829 Mon Sep 17 00:00:00 2001
From: Evgenii Stratonikov <evgeniy@nspcc.ru>
Date: Mon, 31 May 2021 11:55:40 +0300
Subject: [PATCH] [#562] pkg: remove `nspcc-dev/neofs-crypto` dependency

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
---
 go.mod                                       |  1 -
 pkg/core/object/fmt.go                       | 11 ++++++++--
 pkg/core/object/fmt_test.go                  | 17 ++++++++-------
 pkg/services/object/acl/acl.go               | 12 +++++-----
 pkg/services/object/acl/classifier.go        | 23 ++++++++++++++------
 pkg/services/object/acl/eacl/v2/eacl_test.go | 12 +++++-----
 pkg/services/session/storage/executor.go     | 13 ++++-------
 7 files changed, 51 insertions(+), 38 deletions(-)

diff --git a/go.mod b/go.mod
index c01cb2ab2..391d3b204 100644
--- a/go.mod
+++ b/go.mod
@@ -14,7 +14,6 @@ require (
 	github.com/nspcc-dev/hrw v1.0.9
 	github.com/nspcc-dev/neo-go v0.95.1
 	github.com/nspcc-dev/neofs-api-go v1.27.1
-	github.com/nspcc-dev/neofs-crypto v0.3.0
 	github.com/nspcc-dev/neofs-sdk-go v0.0.0-20210520210714-9dee13f0d556
 	github.com/nspcc-dev/tzhash v1.4.0
 	github.com/panjf2000/ants/v2 v2.3.0
diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go
index 81a9e2650..e12aaed56 100644
--- a/pkg/core/object/fmt.go
+++ b/pkg/core/object/fmt.go
@@ -2,15 +2,17 @@ package object
 
 import (
 	"bytes"
+	"crypto/ecdsa"
+	"crypto/elliptic"
 	"errors"
 	"fmt"
 	"strconv"
 
+	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
 	"github.com/nspcc-dev/neofs-api-go/pkg/object"
 	"github.com/nspcc-dev/neofs-api-go/pkg/owner"
 	"github.com/nspcc-dev/neofs-api-go/pkg/storagegroup"
 	objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
-	crypto "github.com/nspcc-dev/neofs-crypto"
 	"github.com/nspcc-dev/neofs-node/pkg/core/netmap"
 )
 
@@ -106,7 +108,12 @@ func (v *FormatValidator) validateSignatureKey(obj *Object) error {
 }
 
 func (v *FormatValidator) checkOwnerKey(id *owner.ID, key []byte) error {
-	wallet, err := owner.NEO3WalletFromPublicKey(crypto.UnmarshalPublicKey(key))
+	pub, err := keys.NewPublicKeyFromBytes(key, elliptic.P256())
+	if err != nil {
+		return err
+	}
+
+	wallet, err := owner.NEO3WalletFromPublicKey((*ecdsa.PublicKey)(pub))
 	if err != nil {
 		// TODO: check via NeoFSID
 		return err
diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go
index 2d41b1ed9..0fbb4ce5b 100644
--- a/pkg/core/object/fmt_test.go
+++ b/pkg/core/object/fmt_test.go
@@ -8,13 +8,13 @@ import (
 	"strconv"
 	"testing"
 
+	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
 	cidtest "github.com/nspcc-dev/neofs-api-go/pkg/container/id/test"
 	"github.com/nspcc-dev/neofs-api-go/pkg/object"
 	"github.com/nspcc-dev/neofs-api-go/pkg/owner"
 	sessiontest "github.com/nspcc-dev/neofs-api-go/pkg/session/test"
 	"github.com/nspcc-dev/neofs-api-go/pkg/storagegroup"
 	objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
-	"github.com/nspcc-dev/neofs-node/pkg/util/test"
 	"github.com/stretchr/testify/require"
 )
 
@@ -65,7 +65,8 @@ func TestFormatValidator_Validate(t *testing.T) {
 		}),
 	)
 
-	ownerKey := test.DecodeKey(-1)
+	ownerKey, err := keys.NewPrivateKey()
+	require.NoError(t, err)
 
 	t.Run("nil input", func(t *testing.T) {
 		require.Error(t, v.Validate(nil))
@@ -93,7 +94,7 @@ func TestFormatValidator_Validate(t *testing.T) {
 	})
 
 	t.Run("correct w/ session token", func(t *testing.T) {
-		w, err := owner.NEO3WalletFromPublicKey(&ownerKey.PublicKey)
+		w, err := owner.NEO3WalletFromPublicKey((*ecdsa.PublicKey)(ownerKey.PublicKey()))
 		require.NoError(t, err)
 
 		tok := sessiontest.Generate()
@@ -104,15 +105,15 @@ func TestFormatValidator_Validate(t *testing.T) {
 		obj.SetSessionToken(sessiontest.Generate())
 		obj.SetOwnerID(tok.OwnerID())
 
-		require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK()))
+		require.NoError(t, object.SetIDWithSignature(&ownerKey.PrivateKey, obj.SDK()))
 
 		require.NoError(t, v.Validate(obj.Object()))
 	})
 
 	t.Run("correct w/o session token", func(t *testing.T) {
-		obj := blankValidObject(t, ownerKey)
+		obj := blankValidObject(t, &ownerKey.PrivateKey)
 
-		require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK()))
+		require.NoError(t, object.SetIDWithSignature(&ownerKey.PrivateKey, obj.SDK()))
 
 		require.NoError(t, v.Validate(obj.Object()))
 	})
@@ -187,7 +188,7 @@ func TestFormatValidator_Validate(t *testing.T) {
 
 	t.Run("expiration", func(t *testing.T) {
 		fn := func(val string) *Object {
-			obj := blankValidObject(t, ownerKey)
+			obj := blankValidObject(t, &ownerKey.PrivateKey)
 
 			a := object.NewAttribute()
 			a.SetKey(objectV2.SysAttributeExpEpoch)
@@ -195,7 +196,7 @@ func TestFormatValidator_Validate(t *testing.T) {
 
 			obj.SetAttributes(a)
 
-			require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK()))
+			require.NoError(t, object.SetIDWithSignature(&ownerKey.PrivateKey, obj.SDK()))
 
 			return obj.Object()
 		}
diff --git a/pkg/services/object/acl/acl.go b/pkg/services/object/acl/acl.go
index 5765079ce..da2da5a4d 100644
--- a/pkg/services/object/acl/acl.go
+++ b/pkg/services/object/acl/acl.go
@@ -6,6 +6,7 @@ import (
 	"errors"
 	"fmt"
 
+	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
 	acl "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
 	cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
 	objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
@@ -16,7 +17,6 @@ import (
 	"github.com/nspcc-dev/neofs-api-go/v2/refs"
 	"github.com/nspcc-dev/neofs-api-go/v2/session"
 	v2signature "github.com/nspcc-dev/neofs-api-go/v2/signature"
-	crypto "github.com/nspcc-dev/neofs-crypto"
 	core "github.com/nspcc-dev/neofs-node/pkg/core/container"
 	"github.com/nspcc-dev/neofs-node/pkg/core/netmap"
 	"github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine"
@@ -589,7 +589,7 @@ func stickyBitCheck(info requestInfo, owner *owner.ID) bool {
 		return true
 	}
 
-	requestSenderKey := crypto.UnmarshalPublicKey(info.senderKey)
+	requestSenderKey := unmarshalPublicKey(info.senderKey)
 
 	return isOwnerFromKey(owner, requestSenderKey)
 }
@@ -726,7 +726,7 @@ func isValidBearer(reqInfo requestInfo, st netmap.State) bool {
 	}
 
 	// 3. Then check if container owner signed this token.
-	tokenIssuerKey := crypto.UnmarshalPublicKey(token.GetSignature().GetKey())
+	tokenIssuerKey := unmarshalPublicKey(token.GetSignature().GetKey())
 	if !isOwnerFromKey(reqInfo.cnrOwner, tokenIssuerKey) {
 		// todo: in this case we can issue all owner keys from neofs.id and check once again
 		return false
@@ -735,7 +735,7 @@ func isValidBearer(reqInfo requestInfo, st netmap.State) bool {
 	// 4. Then check if request sender has rights to use this token.
 	tokenOwnerField := owner.NewIDFromV2(token.GetBody().GetOwnerID())
 	if tokenOwnerField != nil { // see bearer token owner field description
-		requestSenderKey := crypto.UnmarshalPublicKey(reqInfo.senderKey)
+		requestSenderKey := unmarshalPublicKey(reqInfo.senderKey)
 		if !isOwnerFromKey(tokenOwnerField, requestSenderKey) {
 			// todo: in this case we can issue all owner keys from neofs.id and check once again
 			return false
@@ -754,12 +754,12 @@ func isValidLifetime(lifetime *bearer.TokenLifetime, epoch uint64) bool {
 	return epoch >= lifetime.GetNbf() && epoch <= lifetime.GetExp()
 }
 
-func isOwnerFromKey(id *owner.ID, key *ecdsa.PublicKey) bool {
+func isOwnerFromKey(id *owner.ID, key *keys.PublicKey) bool {
 	if id == nil || key == nil {
 		return false
 	}
 
-	wallet, err := owner.NEO3WalletFromPublicKey(key)
+	wallet, err := owner.NEO3WalletFromPublicKey((*ecdsa.PublicKey)(key))
 	if err != nil {
 		return false
 	}
diff --git a/pkg/services/object/acl/classifier.go b/pkg/services/object/acl/classifier.go
index 574c6a960..881ad06f8 100644
--- a/pkg/services/object/acl/classifier.go
+++ b/pkg/services/object/acl/classifier.go
@@ -3,8 +3,10 @@ package acl
 import (
 	"bytes"
 	"crypto/ecdsa"
+	"crypto/elliptic"
 	"fmt"
 
+	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
 	"github.com/nspcc-dev/neofs-api-go/pkg"
 	acl "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
 	"github.com/nspcc-dev/neofs-api-go/pkg/container"
@@ -15,7 +17,6 @@ import (
 	bearer "github.com/nspcc-dev/neofs-api-go/v2/acl"
 	"github.com/nspcc-dev/neofs-api-go/v2/session"
 	v2signature "github.com/nspcc-dev/neofs-api-go/v2/signature"
-	crypto "github.com/nspcc-dev/neofs-crypto"
 	core "github.com/nspcc-dev/neofs-node/pkg/core/netmap"
 	"go.uber.org/zap"
 )
@@ -61,7 +62,7 @@ func (c SenderClassifier) Classify(
 		return 0, false, nil, err
 	}
 
-	ownerKeyInBytes := crypto.MarshalPublicKey(ownerKey)
+	ownerKeyInBytes := ownerKey.Bytes()
 
 	// todo: get owner from neofs.id if present
 
@@ -94,7 +95,7 @@ func (c SenderClassifier) Classify(
 	return acl.RoleOthers, false, ownerKeyInBytes, nil
 }
 
-func requestOwner(req metaWithToken) (*owner.ID, *ecdsa.PublicKey, error) {
+func requestOwner(req metaWithToken) (*owner.ID, *keys.PublicKey, error) {
 	if req.vheader == nil {
 		return nil, nil, fmt.Errorf("%w: nil verification header", ErrMalformedRequest)
 	}
@@ -111,8 +112,8 @@ func requestOwner(req metaWithToken) (*owner.ID, *ecdsa.PublicKey, error) {
 		return nil, nil, fmt.Errorf("%w: nil at body signature", ErrMalformedRequest)
 	}
 
-	key := crypto.UnmarshalPublicKey(bodySignature.Key())
-	neo3wallet, err := owner.NEO3WalletFromPublicKey(key)
+	key := unmarshalPublicKey(bodySignature.Key())
+	neo3wallet, err := owner.NEO3WalletFromPublicKey((*ecdsa.PublicKey)(key))
 	if err != nil {
 		return nil, nil, fmt.Errorf("can't create neo3 wallet: %w", err)
 	}
@@ -196,7 +197,7 @@ func lookupKeyInContainer(
 	return false, nil
 }
 
-func ownerFromToken(token *session.SessionToken) (*owner.ID, *ecdsa.PublicKey, error) {
+func ownerFromToken(token *session.SessionToken) (*owner.ID, *keys.PublicKey, error) {
 	// 1. First check signature of session token.
 	signWrapper := v2signature.StableMarshalerWrapper{SM: token.GetBody()}
 	if err := signature.VerifyDataWithSource(signWrapper, func() (key, sig []byte) {
@@ -207,7 +208,7 @@ func ownerFromToken(token *session.SessionToken) (*owner.ID, *ecdsa.PublicKey, e
 	}
 
 	// 2. Then check if session token owner issued the session token
-	tokenIssuerKey := crypto.UnmarshalPublicKey(token.GetSignature().GetKey())
+	tokenIssuerKey := unmarshalPublicKey(token.GetSignature().GetKey())
 	tokenOwner := owner.NewIDFromV2(token.GetBody().GetOwnerID())
 
 	if !isOwnerFromKey(tokenOwner, tokenIssuerKey) {
@@ -217,3 +218,11 @@ func ownerFromToken(token *session.SessionToken) (*owner.ID, *ecdsa.PublicKey, e
 
 	return tokenOwner, tokenIssuerKey, nil
 }
+
+func unmarshalPublicKey(bs []byte) *keys.PublicKey {
+	pub, err := keys.NewPublicKeyFromBytes(bs, elliptic.P256())
+	if err != nil {
+		return nil
+	}
+	return pub
+}
diff --git a/pkg/services/object/acl/eacl/v2/eacl_test.go b/pkg/services/object/acl/eacl/v2/eacl_test.go
index 75827a5fa..6c16e784a 100644
--- a/pkg/services/object/acl/eacl/v2/eacl_test.go
+++ b/pkg/services/object/acl/eacl/v2/eacl_test.go
@@ -1,20 +1,20 @@
 package v2
 
 import (
+	"crypto/ecdsa"
 	"crypto/rand"
 	"crypto/sha256"
 	"testing"
 
+	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
 	"github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
 	cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
 	cidtest "github.com/nspcc-dev/neofs-api-go/pkg/container/id/test"
 	objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object"
 	objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
 	"github.com/nspcc-dev/neofs-api-go/v2/session"
-	crypto "github.com/nspcc-dev/neofs-crypto"
 	"github.com/nspcc-dev/neofs-node/pkg/core/object"
 	eacl2 "github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl"
-	"github.com/nspcc-dev/neofs-node/pkg/util/test"
 	"github.com/stretchr/testify/require"
 )
 
@@ -111,14 +111,16 @@ func TestHeadRequest(t *testing.T) {
 
 	table := new(eacl.Table)
 
-	senderKey := test.DecodeKey(-1).PublicKey
+	priv, err := keys.NewPrivateKey()
+	require.NoError(t, err)
+	senderKey := priv.PublicKey()
 
 	r := eacl.NewRecord()
 	r.SetOperation(eacl.OperationHead)
 	r.SetAction(eacl.ActionDeny)
 	r.AddFilter(eacl.HeaderFromObject, eacl.MatchStringEqual, attrKey, attrVal)
 	r.AddFilter(eacl.HeaderFromRequest, eacl.MatchStringEqual, xKey, xVal)
-	eacl.AddFormedTarget(r, eacl.RoleUnknown, senderKey)
+	eacl.AddFormedTarget(r, eacl.RoleUnknown, (ecdsa.PublicKey)(*senderKey))
 
 	table.AddRecord(r)
 
@@ -132,7 +134,7 @@ func TestHeadRequest(t *testing.T) {
 	unit := new(eacl2.ValidationUnit).
 		WithContainerID(cid).
 		WithOperation(eacl.OperationHead).
-		WithSenderKey(crypto.MarshalPublicKey(&senderKey)).
+		WithSenderKey(senderKey.Bytes()).
 		WithHeaderSource(
 			NewMessageHeaderSource(
 				WithObjectStorage(lStorage),
diff --git a/pkg/services/session/storage/executor.go b/pkg/services/session/storage/executor.go
index fc152f288..ebb7af7c0 100644
--- a/pkg/services/session/storage/executor.go
+++ b/pkg/services/session/storage/executor.go
@@ -2,16 +2,13 @@ package storage
 
 import (
 	"context"
-	"crypto/ecdsa"
-	"crypto/elliptic"
-	"crypto/rand"
 	"fmt"
 
 	"github.com/google/uuid"
 	"github.com/mr-tron/base58"
+	"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
 	"github.com/nspcc-dev/neofs-api-go/pkg/owner"
 	"github.com/nspcc-dev/neofs-api-go/v2/session"
-	crypto "github.com/nspcc-dev/neofs-crypto"
 )
 
 func (s *TokenStore) Create(ctx context.Context, body *session.CreateRequestBody) (*session.CreateResponseBody, error) {
@@ -30,7 +27,7 @@ func (s *TokenStore) Create(ctx context.Context, body *session.CreateRequestBody
 		return nil, fmt.Errorf("could not marshal token ID: %w", err)
 	}
 
-	sk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
+	sk, err := keys.NewPrivateKey()
 	if err != nil {
 		return nil, err
 	}
@@ -40,16 +37,14 @@ func (s *TokenStore) Create(ctx context.Context, body *session.CreateRequestBody
 		tokenID: base58.Encode(uidBytes),
 		ownerID: base58.Encode(ownerBytes),
 	}] = &PrivateToken{
-		sessionKey: sk,
+		sessionKey: &sk.PrivateKey,
 		exp:        body.GetExpiration(),
 	}
 	s.mtx.Unlock()
 
 	res := new(session.CreateResponseBody)
 	res.SetID(uidBytes)
-	res.SetSessionKey(
-		crypto.MarshalPublicKey(&sk.PublicKey),
-	)
+	res.SetSessionKey(sk.PublicKey().Bytes())
 
 	return res, nil
 }