Skip to content

Commit

Permalink
neofs: Sign multipart objects in the gate
Browse files Browse the repository at this point in the history
Closes #975.

Signed-off-by: Evgenii Baidakov <[email protected]>
  • Loading branch information
smallhive committed Sep 11, 2024
1 parent 63fc2aa commit e59d186
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 6 deletions.
12 changes: 8 additions & 4 deletions api/layer/multipart_upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,8 +340,10 @@ func (n *layer) uploadPart(ctx context.Context, multipartInfo *data.MultipartInf
if nBts > 0 {
prm.Payload = bytes.NewReader((*chunk)[:nBts])
prm.PayloadSize = uint64(nBts)
prm.Multipart.PayloadHash = sha256.New()
prm.Multipart.PayloadHash.Write((*chunk)[:nBts])

id, _, err = n.objectPutAndHash(ctx, prm, bktInfo)
id, err = n.multipartObjectPut(ctx, prm, bktInfo)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -496,11 +498,12 @@ func (n *layer) uploadZeroPart(ctx context.Context, multipartInfo *data.Multipar
Multipart: &Multipart{
MultipartHashes: objHashes,
HeaderObject: &hashlessHeaderObject,
PayloadHash: sha256.New(),
},
Payload: bytes.NewBuffer(nil),
}

id, _, err := n.objectPutAndHash(ctx, prm, bktInfo)
id, err := n.multipartObjectPut(ctx, prm, bktInfo)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -822,11 +825,12 @@ func (n *layer) CompleteMultipartUpload(ctx context.Context, p *CompleteMultipar
SplitFirstID: &splitFirstID,
SplitPreviousID: &splitPreviousID,
HeaderObject: header,
PayloadHash: sha256.New(),
},
Payload: bytes.NewBuffer(nil),
}

lastPartObjID, _, err := n.objectPutAndHash(ctx, prm, p.Info.Bkt)
lastPartObjID, err := n.multipartObjectPut(ctx, prm, p.Info.Bkt)
if err != nil {
return nil, nil, err
}
Expand All @@ -852,7 +856,7 @@ func (n *layer) CompleteMultipartUpload(ctx context.Context, p *CompleteMultipar
},
}

_, _, err = n.objectPutAndHash(ctx, prm, p.Info.Bkt)
_, err = n.multipartObjectPut(ctx, prm, p.Info.Bkt)
if err != nil {
return nil, nil, err
}
Expand Down
2 changes: 2 additions & 0 deletions api/layer/neofs.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ type Multipart struct {
HeaderObject *object.Object
// Link contains info for linking object.
Link *object.Link
// PayloadHash contains precalculated hash for object.
PayloadHash hash.Hash
}

// PrmObjectDelete groups parameters of NeoFS.DeleteObject operation.
Expand Down
18 changes: 16 additions & 2 deletions api/layer/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,20 @@ func (n *layer) objectPutAndHash(ctx context.Context, prm PrmObjectCreate, bktIn
hash := sha256.New()
prm.Payload = wrapReader(prm.Payload, 64*1024, func(buf []byte) {
hash.Write(buf)
})
id, err := n.neoFS.CreateObject(ctx, prm)
if err != nil {
return oid.ID{}, nil, err
}
return id, hash.Sum(nil), nil
}

// multipartObjectPut writes only Multipart hash collection.
// It doesn't calculate hash from payload, it already calculated in prm.Multipart.PayloadHash, if required.
func (n *layer) multipartObjectPut(ctx context.Context, prm PrmObjectCreate, bktInfo *data.BucketInfo) (oid.ID, error) {
n.prepareAuthParameters(ctx, &prm.PrmAuth, bktInfo.Owner)

prm.Payload = wrapReader(prm.Payload, 64*1024, func(buf []byte) {
if prm.Multipart != nil {
for _, h := range prm.Multipart.MultipartHashes {
h.Write(buf)
Expand All @@ -496,9 +510,9 @@ func (n *layer) objectPutAndHash(ctx context.Context, prm PrmObjectCreate, bktIn
})
id, err := n.neoFS.CreateObject(ctx, prm)
if err != nil {
return oid.ID{}, nil, err
return oid.ID{}, err
}
return id, hash.Sum(nil), nil
return id, nil
}

// ListObjectsV1 returns objects in a bucket for requests of Version 1.
Expand Down
35 changes: 35 additions & 0 deletions internal/neofs/neofs.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,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"
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
"github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
Expand Down Expand Up @@ -246,6 +247,33 @@ func (x *NeoFS) DeleteContainer(ctx context.Context, id cid.ID, token *session.C
return nil
}

func (x *NeoFS) signMultipartObject(obj *object.Object, signer neofscrypto.Signer, payloadHash hash.Hash) error {
var (
sig neofscrypto.Signature
)

obj.SetPayloadChecksum(checksum.NewFromHash(checksum.SHA256, payloadHash))

if x.IsHomomorphicHashingEnabled() {
var homoChecksum = tz.New()

homoChecksum.Write(obj.Payload())
obj.SetPayloadHomomorphicHash(checksum.NewFromHash(checksum.TillichZemor, homoChecksum))
}

if err := obj.CalculateAndSetID(); err != nil {
return fmt.Errorf("calculate ID: %w", err)
}

if err := sig.Calculate(signer, obj.GetID().Marshal()); err != nil {
return fmt.Errorf("sign object ID: %w", err)
}

obj.SetSignature(&sig)

return nil
}

// CreateObject implements neofs.NeoFS interface method.
func (x *NeoFS) CreateObject(ctx context.Context, prm layer.PrmObjectCreate) (oid.ID, error) {
attrNum := len(prm.Attributes) + 1 // + creation time
Expand Down Expand Up @@ -310,9 +338,16 @@ func (x *NeoFS) CreateObject(ctx context.Context, prm layer.PrmObjectCreate) (oi
prm.Payload = bytes.NewReader(obj.Payload())
obj.SetPayloadSize(uint64(len(obj.Payload())))

prm.Multipart.PayloadHash = sha256.New()
prm.Multipart.PayloadHash.Write(obj.Payload())

// Link object should never have a previous one.
obj.ResetPreviousID()
}

if err := x.signMultipartObject(&obj, x.signer(ctx), prm.Multipart.PayloadHash); err != nil {
return oid.ID{}, errors.New("failed to sign object")
}
}

if len(prm.Locks) > 0 {
Expand Down

0 comments on commit e59d186

Please sign in to comment.