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 sessionSet bool
session session.Container session session.Container
signer neofscrypto.Signer
} }
// SetContainer sets structured information about new NeoFS container. // SetContainer sets structured information about new NeoFS container.
@ -37,6 +39,13 @@ func (x *PrmContainerPut) SetContainer(cnr container.Container) {
x.cnrSet = true 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. // WithinSession specifies session within which container should be saved.
// //
// Creator of the session acquires the authorship of the request. This affects // 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 return x.id
} }
func (c *Client) defaultSigner() neofscrypto.Signer {
return neofsecdsa.SignerRFC6979(c.prm.key)
}
// ContainerPut sends request to save container in NeoFS. // ContainerPut sends request to save container in NeoFS.
// //
// Exactly one return value is non-nil. By default, server status is returned in res structure. // 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) prm.cnr.WriteToV2(&cnr)
var sig neofscrypto.Signature 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 { if err != nil {
return nil, fmt.Errorf("calculate container signature: %w", err) return nil, fmt.Errorf("calculate container signature: %w", err)
} }
@ -375,6 +392,8 @@ type PrmContainerDelete struct {
tokSet bool tokSet bool
tok session.Container tok session.Container
signer neofscrypto.Signer
} }
// SetContainer sets identifier of the NeoFS container to be removed. // SetContainer sets identifier of the NeoFS container to be removed.
@ -384,6 +403,13 @@ func (x *PrmContainerDelete) SetContainer(id cid.ID) {
x.idSet = true 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. // WithinSession specifies session within which container should be removed.
// //
// Creator of the session acquires the authorship of the request. // 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() data := cidV2.GetValue()
var sig neofscrypto.Signature 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 { if err != nil {
return nil, fmt.Errorf("calculate signature: %w", err) return nil, fmt.Errorf("calculate signature: %w", err)
} }
@ -599,6 +629,8 @@ type PrmContainerSetEACL struct {
sessionSet bool sessionSet bool
session session.Container session session.Container
signer neofscrypto.Signer
} }
// SetTable sets eACL table structure to be set for the container. // 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 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 // WithinSession specifies session within which extended ACL of the container
// should be saved. // should be saved.
// //
@ -665,8 +704,12 @@ func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL)
eaclV2 := prm.table.ToV2() eaclV2 := prm.table.ToV2()
var sig neofscrypto.Signature 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 { if err != nil {
return nil, fmt.Errorf("calculate signature: %w", err) return nil, fmt.Errorf("calculate signature: %w", err)
} }

View file

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

View file

@ -92,3 +92,38 @@ type PublicKey interface {
// Verify checks signature of the given data. True means correct signature. // Verify checks signature of the given data. True means correct signature.
Verify(data, signature []byte) bool 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
}