Set external signer for requests payload (#398)

close #373
This commit is contained in:
Roman Khimov 2023-04-20 14:48:09 +03:00 committed by GitHub
commit 16daed8140
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 85 additions and 8 deletions

View file

@ -28,6 +28,8 @@ type PrmContainerPut struct {
sessionSet bool
session session.Container
signer neofscrypto.Signer
}
// SetContainer sets structured information about new NeoFS container.
@ -37,6 +39,13 @@ func (x *PrmContainerPut) SetContainer(cnr container.Container) {
x.cnrSet = true
}
// SetSigner sets signer to sign request payload.
// Signer's scheme MUST be neofscrypto.ECDSA_DETERMINISTIC_SHA256. For example, you can use neofsecdsa.SignerRFC6979.
// Optional parameter: defaults to internal Client signer.
func (x *PrmContainerPut) SetSigner(signer neofscrypto.Signer) {
x.signer = signer
}
// WithinSession specifies session within which container should be saved.
//
// Creator of the session acquires the authorship of the request. This affects
@ -64,6 +73,10 @@ func (x ResContainerPut) ID() cid.ID {
return x.id
}
func (c *Client) defaultSigner() neofscrypto.Signer {
return neofsecdsa.SignerRFC6979(c.prm.key)
}
// ContainerPut sends request to save container in NeoFS.
//
// Exactly one return value is non-nil. By default, server status is returned in res structure.
@ -97,8 +110,12 @@ func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResCon
prm.cnr.WriteToV2(&cnr)
var sig neofscrypto.Signature
signer := prm.signer
if signer == nil {
signer = c.defaultSigner()
}
err := container.CalculateSignature(&sig, prm.cnr, c.prm.key)
err := container.CalculateSignature(&sig, prm.cnr, signer)
if err != nil {
return nil, fmt.Errorf("calculate container signature: %w", err)
}
@ -375,6 +392,8 @@ type PrmContainerDelete struct {
tokSet bool
tok session.Container
signer neofscrypto.Signer
}
// SetContainer sets identifier of the NeoFS container to be removed.
@ -384,6 +403,13 @@ func (x *PrmContainerDelete) SetContainer(id cid.ID) {
x.idSet = true
}
// SetSigner sets signer to sign request payload.
// Signer's scheme MUST be neofscrypto.ECDSA_DETERMINISTIC_SHA256. For example, you can use neofsecdsa.SignerRFC6979.
// Optional parameter: defaults to internal Client signer.
func (x *PrmContainerDelete) SetSigner(signer neofscrypto.Signer) {
x.signer = signer
}
// WithinSession specifies session within which container should be removed.
//
// Creator of the session acquires the authorship of the request.
@ -439,8 +465,12 @@ func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (*
data := cidV2.GetValue()
var sig neofscrypto.Signature
signer := prm.signer
if signer == nil {
signer = c.defaultSigner()
}
err := sig.Calculate(neofsecdsa.SignerRFC6979(c.prm.key), data)
err := sig.Calculate(signer, data)
if err != nil {
return nil, fmt.Errorf("calculate signature: %w", err)
}
@ -599,6 +629,8 @@ type PrmContainerSetEACL struct {
sessionSet bool
session session.Container
signer neofscrypto.Signer
}
// SetTable sets eACL table structure to be set for the container.
@ -608,6 +640,13 @@ func (x *PrmContainerSetEACL) SetTable(table eacl.Table) {
x.tableSet = true
}
// SetSigner sets signer to sign request payload.
// Signer's scheme MUST be neofscrypto.ECDSA_DETERMINISTIC_SHA256. For example, you can use neofsecdsa.SignerRFC6979.
// Optional parameter: defaults to internal Client signer.
func (x *PrmContainerSetEACL) SetSigner(signer neofscrypto.Signer) {
x.signer = signer
}
// WithinSession specifies session within which extended ACL of the container
// should be saved.
//
@ -665,8 +704,12 @@ func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL)
eaclV2 := prm.table.ToV2()
var sig neofscrypto.Signature
signer := prm.signer
if signer == nil {
signer = c.defaultSigner()
}
err := sig.Calculate(neofsecdsa.SignerRFC6979(c.prm.key), eaclV2.StableMarshal(nil))
err := sig.Calculate(signer, eaclV2.StableMarshal(nil))
if err != nil {
return nil, fmt.Errorf("calculate signature: %w", err)
}

View file

@ -1,7 +1,6 @@
package container
import (
"crypto/ecdsa"
"crypto/sha256"
"errors"
"fmt"
@ -15,7 +14,6 @@ import (
"github.com/nspcc-dev/neofs-sdk-go/container/acl"
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/netmap"
subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id"
"github.com/nspcc-dev/neofs-sdk-go/user"
@ -481,8 +479,8 @@ func ReadDomain(cnr Container) (res Domain) {
// will most likely break the signature.
//
// See also VerifySignature.
func CalculateSignature(dst *neofscrypto.Signature, cnr Container, signer ecdsa.PrivateKey) error {
return dst.Calculate(neofsecdsa.SignerRFC6979(signer), cnr.Marshal())
func CalculateSignature(dst *neofscrypto.Signature, cnr Container, signer neofscrypto.Signer) error {
return dst.Calculate(signer, cnr.Marshal())
}
// VerifySignature verifies Container signature calculated using CalculateSignature.

View file

@ -16,6 +16,7 @@ import (
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
containertest "github.com/nspcc-dev/neofs-sdk-go/container/test"
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa"
netmaptest "github.com/nspcc-dev/neofs-sdk-go/netmap/test"
subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id"
subnetidtest "github.com/nspcc-dev/neofs-sdk-go/subnet/id/test"
@ -339,7 +340,7 @@ func TestCalculateSignature(t *testing.T) {
var sig neofscrypto.Signature
require.NoError(t, container.CalculateSignature(&sig, val, key.PrivateKey))
require.NoError(t, container.CalculateSignature(&sig, val, neofsecdsa.SignerRFC6979(key.PrivateKey)))
var msg refs.Signature
sig.WriteToV2(&msg)

View file

@ -92,3 +92,38 @@ type PublicKey interface {
// Verify checks signature of the given data. True means correct signature.
Verify(data, signature []byte) bool
}
// StaticSigner emulates real sign and contains already precalculated hash.
// Provides neofscrypto.Signer interface.
type StaticSigner struct {
scheme Scheme
sig []byte
pubKey PublicKey
}
// NewStaticSigner creates new StaticSigner.
func NewStaticSigner(scheme Scheme, sig []byte, pubKey PublicKey) *StaticSigner {
return &StaticSigner{
scheme: scheme,
sig: sig,
pubKey: pubKey,
}
}
// Scheme returns neofscrypto.ECDSA_DETERMINISTIC_SHA256.
// Implements neofscrypto.Signer.
func (s *StaticSigner) Scheme() Scheme {
return s.scheme
}
// Sign returns precalculated hash.
// Implements neofscrypto.Signer.
func (s *StaticSigner) Sign(_ []byte) ([]byte, error) {
return s.sig, nil
}
// Public returns neofscrypto.PublicKey.
// Implements neofscrypto.Signer.
func (s *StaticSigner) Public() PublicKey {
return s.pubKey
}