diff --git a/cmd/encryption-v1.go b/cmd/encryption-v1.go index ab3422244..fe51341d5 100644 --- a/cmd/encryption-v1.go +++ b/cmd/encryption-v1.go @@ -786,11 +786,23 @@ func (o *ObjectInfo) DecryptedSize() (int64, error) { if !o.IsEncrypted() { return 0, errors.New("Cannot compute decrypted size of an unencrypted object") } - size, err := sio.DecryptedSize(uint64(o.Size)) - if err != nil { - err = errObjectTampered // assign correct error type + if len(o.Parts) == 0 { + size, err := sio.DecryptedSize(uint64(o.Size)) + if err != nil { + err = errObjectTampered // assign correct error type + } + return int64(size), err } - return int64(size), err + + var size int64 + for _, part := range o.Parts { + partSize, err := sio.DecryptedSize(uint64(part.Size)) + if err != nil { + return 0, errObjectTampered + } + size += int64(partSize) + } + return size, nil } // EncryptedSize returns the size of the object after encryption. diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index c8aff2351..464e5863a 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -1077,7 +1077,6 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt return } - // Calculating object encryption key var objectEncryptionKey []byte objectEncryptionKey, err = decryptObjectInfo(key, dstBucket, dstObject, li.UserDefined) if err != nil { @@ -1086,7 +1085,13 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt return } - reader, err = sio.EncryptReader(reader, sio.Config{Key: objectEncryptionKey}) + var partIDbin [4]byte + binary.LittleEndian.PutUint32(partIDbin[:], uint32(partID)) // marshal part ID + + mac := hmac.New(sha256.New, objectEncryptionKey) // derive part encryption key from part ID and object key + mac.Write(partIDbin[:]) + partEncryptionKey := mac.Sum(nil) + reader, err = sio.EncryptReader(reader, sio.Config{Key: partEncryptionKey}) if err != nil { pipeWriter.CloseWithError(err) writeErrorResponse(w, toAPIErrorCode(err), r.URL)