diff --git a/object/sign.go b/object/sign.go new file mode 100644 index 00000000..1dc5bd0e --- /dev/null +++ b/object/sign.go @@ -0,0 +1,45 @@ +package object + +// SignedData returns marshaled payload of the Put request. +// +// If payload is nil, ErrHeaderNotFound returns. +func (m PutRequest) SignedData() ([]byte, error) { + r := m.GetR() + if r == nil { + return nil, ErrHeaderNotFound + } + + data := make([]byte, r.Size()) + + if _, err := r.MarshalTo(data); err != nil { + return nil, err + } + + return data, nil +} + +// ReadSignedData copies marshaled payload of the Put request to passed buffer. +// +// If payload is nil, ErrHeaderNotFound returns. +func (m PutRequest) ReadSignedData(p []byte) error { + r := m.GetR() + if r == nil { + return ErrHeaderNotFound + } + + _, err := r.MarshalTo(p) + + return err +} + +// SignedDataSize returns the size of payload of the Put request. +// +// If payload is nil, -1 returns. +func (m PutRequest) SignedDataSize() int { + r := m.GetR() + if r == nil { + return -1 + } + + return r.Size() +} diff --git a/object/sign_test.go b/object/sign_test.go new file mode 100644 index 00000000..2574d9cc --- /dev/null +++ b/object/sign_test.go @@ -0,0 +1,79 @@ +package object + +import ( + "testing" + + "github.com/nspcc-dev/neofs-api-go/service" + "github.com/nspcc-dev/neofs-crypto/test" + "github.com/stretchr/testify/require" +) + +func TestSignVerifyRequests(t *testing.T) { + sk := test.DecodeKey(0) + + type sigType interface { + service.SignedDataWithToken + service.SignKeyPairAccumulator + service.SignKeyPairSource + SetToken(*Token) + } + + items := []struct { + constructor func() sigType + bodyCorrupt []func(sigType) + }{ + { // PutRequest.PutHeader + constructor: func() sigType { + return MakePutRequestHeader(new(Object)) + }, + bodyCorrupt: []func(sigType){ + func(s sigType) { + obj := s.(*PutRequest).GetR().(*PutRequest_Header).Header.GetObject() + obj.SystemHeader.PayloadLength++ + }, + }, + }, + { // PutRequest.Chunk + constructor: func() sigType { + return MakePutRequestChunk(make([]byte, 10)) + }, + bodyCorrupt: []func(sigType){ + func(s sigType) { + h := s.(*PutRequest).GetR().(*PutRequest_Chunk) + h.Chunk[0]++ + }, + }, + }, + } + + for _, item := range items { + { // token corruptions + v := item.constructor() + + token := new(Token) + v.SetToken(token) + + require.NoError(t, service.SignDataWithSessionToken(sk, v)) + + require.NoError(t, service.VerifyAccumulatedSignaturesWithToken(v)) + + token.SetSessionKey(append(token.GetSessionKey(), 1)) + + require.Error(t, service.VerifyAccumulatedSignaturesWithToken(v)) + } + + { // body corruptions + for _, corruption := range item.bodyCorrupt { + v := item.constructor() + + require.NoError(t, service.SignDataWithSessionToken(sk, v)) + + require.NoError(t, service.VerifyAccumulatedSignaturesWithToken(v)) + + corruption(v) + + require.Error(t, service.VerifyAccumulatedSignaturesWithToken(v)) + } + } + } +}