mirror of
https://github.com/minio/minio.git
synced 2025-04-10 14:37:53 -04:00
[refactor] simplify en/decrypted size computation (#5658)
This commit replaces the en/decrypted size computation with functions from the `sio` package. Fixes #5657
This commit is contained in:
parent
2938e332ba
commit
a4d2e2b428
@ -623,9 +623,9 @@ func DecryptBlocksRequest(client io.Writer, r *http.Request, startOffset, length
|
|||||||
var partStartOffset = startOffset
|
var partStartOffset = startOffset
|
||||||
// Skip parts until final offset maps to a particular part offset.
|
// Skip parts until final offset maps to a particular part offset.
|
||||||
for i, part := range objInfo.Parts {
|
for i, part := range objInfo.Parts {
|
||||||
decryptedSize, err := decryptedSize(part.Size)
|
decryptedSize, err := sio.DecryptedSize(uint64(part.Size))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, -1, -1, err
|
return nil, -1, -1, errObjectTampered
|
||||||
}
|
}
|
||||||
|
|
||||||
partStartIndex = i
|
partStartIndex = i
|
||||||
@ -633,12 +633,12 @@ func DecryptBlocksRequest(client io.Writer, r *http.Request, startOffset, length
|
|||||||
// Offset is smaller than size we have reached the
|
// Offset is smaller than size we have reached the
|
||||||
// proper part offset, break out we start from
|
// proper part offset, break out we start from
|
||||||
// this part index.
|
// this part index.
|
||||||
if partStartOffset < decryptedSize {
|
if partStartOffset < int64(decryptedSize) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue to look for next part.
|
// Continue to look for next part.
|
||||||
partStartOffset -= decryptedSize
|
partStartOffset -= int64(decryptedSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
startSeqNum := partStartOffset / sseDAREPackageBlockSize
|
startSeqNum := partStartOffset / sseDAREPackageBlockSize
|
||||||
@ -734,20 +734,6 @@ func (li *ListPartsInfo) IsEncrypted() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func decryptedSize(encryptedSize int64) (int64, error) {
|
|
||||||
if encryptedSize == 0 {
|
|
||||||
return encryptedSize, nil
|
|
||||||
}
|
|
||||||
size := (encryptedSize / (sseDAREPackageBlockSize + sseDAREPackageMetaSize)) * sseDAREPackageBlockSize
|
|
||||||
if mod := encryptedSize % (sseDAREPackageBlockSize + sseDAREPackageMetaSize); mod > 0 {
|
|
||||||
if mod < sseDAREPackageMetaSize+1 {
|
|
||||||
return -1, errObjectTampered // object is not 0 size but smaller than the smallest valid encrypted object
|
|
||||||
}
|
|
||||||
size += mod - sseDAREPackageMetaSize
|
|
||||||
}
|
|
||||||
return size, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DecryptedSize returns the size of the object after decryption in bytes.
|
// DecryptedSize returns the size of the object after decryption in bytes.
|
||||||
// It returns an error if the object is not encrypted or marked as encrypted
|
// It returns an error if the object is not encrypted or marked as encrypted
|
||||||
// but has an invalid size.
|
// but has an invalid size.
|
||||||
@ -756,19 +742,22 @@ func (o *ObjectInfo) DecryptedSize() (int64, error) {
|
|||||||
if !o.IsEncrypted() {
|
if !o.IsEncrypted() {
|
||||||
panic("cannot compute decrypted size of an object which is not encrypted")
|
panic("cannot compute decrypted size of an object which is not encrypted")
|
||||||
}
|
}
|
||||||
|
size, err := sio.DecryptedSize(uint64(o.Size))
|
||||||
return decryptedSize(o.Size)
|
if err != nil {
|
||||||
|
err = errObjectTampered // assign correct error type
|
||||||
|
}
|
||||||
|
return int64(size), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncryptedSize returns the size of the object after encryption.
|
// EncryptedSize returns the size of the object after encryption.
|
||||||
// An encrypted object is always larger than a plain object
|
// An encrypted object is always larger than a plain object
|
||||||
// except for zero size objects.
|
// except for zero size objects.
|
||||||
func (o *ObjectInfo) EncryptedSize() int64 {
|
func (o *ObjectInfo) EncryptedSize() int64 {
|
||||||
size := (o.Size / sseDAREPackageBlockSize) * (sseDAREPackageBlockSize + sseDAREPackageMetaSize)
|
size, err := sio.EncryptedSize(uint64(o.Size))
|
||||||
if mod := o.Size % (sseDAREPackageBlockSize); mod > 0 {
|
if err != nil {
|
||||||
size += mod + sseDAREPackageMetaSize
|
panic(err) // Since AWS S3 allows parts to be 5GB at most this cannot happen - sio max. size is 256 TB
|
||||||
}
|
}
|
||||||
return size
|
return int64(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecryptCopyObjectInfo tries to decrypt the provided object if it is encrypted.
|
// DecryptCopyObjectInfo tries to decrypt the provided object if it is encrypted.
|
||||||
|
@ -275,59 +275,6 @@ func TestParseSSECopyCustomerRequest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var encryptedSizeTests = []struct {
|
|
||||||
size, encsize int64
|
|
||||||
}{
|
|
||||||
{size: 0, encsize: 0}, // 0
|
|
||||||
{size: 1, encsize: 33}, // 1
|
|
||||||
{size: 1024, encsize: 1024 + 32}, // 2
|
|
||||||
{size: 2 * sseDAREPackageBlockSize, encsize: 2 * (sseDAREPackageBlockSize + 32)}, // 3
|
|
||||||
{size: 100*sseDAREPackageBlockSize + 1, encsize: 100*(sseDAREPackageBlockSize+32) + 33}, // 4
|
|
||||||
{size: sseDAREPackageBlockSize + 1, encsize: (sseDAREPackageBlockSize + 32) + 33}, // 5
|
|
||||||
{size: 5 * 1024 * 1024 * 1024, encsize: 81920 * (sseDAREPackageBlockSize + 32)}, // 6
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEncryptedSize(t *testing.T) {
|
|
||||||
for i, test := range encryptedSizeTests {
|
|
||||||
objInfo := ObjectInfo{Size: test.size}
|
|
||||||
if size := objInfo.EncryptedSize(); test.encsize != size {
|
|
||||||
t.Errorf("Test %d: got encrypted size: #%d want: #%d", i, size, test.encsize)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var decryptSSECustomerObjectInfoTests = []struct {
|
|
||||||
encsize, size int64
|
|
||||||
err error
|
|
||||||
}{
|
|
||||||
{encsize: 0, size: 0, err: nil}, // 0
|
|
||||||
{encsize: 33, size: 1, err: nil}, // 1
|
|
||||||
{encsize: 1024 + 32, size: 1024, err: nil}, // 2
|
|
||||||
{encsize: 2 * (sseDAREPackageBlockSize + 32), size: 2 * sseDAREPackageBlockSize, err: nil}, // 3
|
|
||||||
{encsize: 100*(sseDAREPackageBlockSize+32) + 33, size: 100*sseDAREPackageBlockSize + 1, err: nil}, // 4
|
|
||||||
{encsize: (sseDAREPackageBlockSize + 32) + 33, size: sseDAREPackageBlockSize + 1, err: nil}, // 5
|
|
||||||
{encsize: 81920 * (sseDAREPackageBlockSize + 32), size: 5 * 1024 * 1024 * 1024, err: nil}, // 6
|
|
||||||
{encsize: 0, size: 0, err: nil}, // 7
|
|
||||||
{encsize: sseDAREPackageBlockSize + 32 + 31, size: 0, err: errObjectTampered}, // 8
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDecryptedSize(t *testing.T) {
|
|
||||||
for i, test := range decryptSSECustomerObjectInfoTests {
|
|
||||||
objInfo := ObjectInfo{Size: test.encsize}
|
|
||||||
objInfo.UserDefined = map[string]string{
|
|
||||||
ServerSideEncryptionSealAlgorithm: SSESealAlgorithmDareSha256,
|
|
||||||
}
|
|
||||||
|
|
||||||
size, err := objInfo.DecryptedSize()
|
|
||||||
if err != test.err || (size != test.size && err == nil) {
|
|
||||||
t.Errorf("Test %d: decryption returned: %v want: %v", i, err, test.err)
|
|
||||||
}
|
|
||||||
if err == nil && size != test.size {
|
|
||||||
t.Errorf("Test %d: got decrypted size: #%d want: #%d", i, size, test.size)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var encryptRequestTests = []struct {
|
var encryptRequestTests = []struct {
|
||||||
header map[string]string
|
header map[string]string
|
||||||
metadata map[string]string
|
metadata map[string]string
|
||||||
|
39
vendor/github.com/minio/sio/sio.go
generated
vendored
39
vendor/github.com/minio/sio/sio.go
generated
vendored
@ -48,6 +48,9 @@ const (
|
|||||||
maxPayloadSize = 1 << 16
|
maxPayloadSize = 1 << 16
|
||||||
tagSize = 16
|
tagSize = 16
|
||||||
maxPackageSize = headerSize + maxPayloadSize + tagSize
|
maxPackageSize = headerSize + maxPayloadSize + tagSize
|
||||||
|
|
||||||
|
maxDecryptedSize = 1 << 48
|
||||||
|
maxEncryptedSize = maxDecryptedSize + ((headerSize + tagSize) * 1 << 32)
|
||||||
)
|
)
|
||||||
|
|
||||||
var newAesGcm = func(key []byte) (cipher.AEAD, error) {
|
var newAesGcm = func(key []byte) (cipher.AEAD, error) {
|
||||||
@ -68,6 +71,7 @@ var (
|
|||||||
errUnsupportedCipher = errors.New("sio: unsupported cipher suite")
|
errUnsupportedCipher = errors.New("sio: unsupported cipher suite")
|
||||||
errInvalidPayloadSize = errors.New("sio: invalid payload size")
|
errInvalidPayloadSize = errors.New("sio: invalid payload size")
|
||||||
errTagMismatch = errors.New("sio: authentication failed")
|
errTagMismatch = errors.New("sio: authentication failed")
|
||||||
|
errUnexpectedSize = errors.New("sio: size is too large for DARE")
|
||||||
|
|
||||||
// Version 1.0 specific
|
// Version 1.0 specific
|
||||||
errPackageOutOfOrder = errors.New("sio: sequence number mismatch")
|
errPackageOutOfOrder = errors.New("sio: sequence number mismatch")
|
||||||
@ -115,6 +119,41 @@ type Config struct {
|
|||||||
PayloadSize int
|
PayloadSize int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EncryptedSize computes the size of an encrypted data stream
|
||||||
|
// from the plaintext size. It is the inverse of DecryptedSize().
|
||||||
|
//
|
||||||
|
// EncryptedSize returns an error if the provided size is to large.
|
||||||
|
func EncryptedSize(size uint64) (uint64, error) {
|
||||||
|
if size > maxDecryptedSize {
|
||||||
|
return 0, errUnexpectedSize
|
||||||
|
}
|
||||||
|
|
||||||
|
encSize := (size / maxPayloadSize) * maxPackageSize
|
||||||
|
if mod := size % maxPayloadSize; mod > 0 {
|
||||||
|
encSize += mod + (headerSize + tagSize)
|
||||||
|
}
|
||||||
|
return encSize, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecryptedSize computes the size of a decrypted data stream
|
||||||
|
// from the encrypted stream size. It is the inverse of EncryptedSize().
|
||||||
|
//
|
||||||
|
// DecryptedSize returns an error if the provided size is to large
|
||||||
|
// or if the provided size is an invalid encrypted stream size.
|
||||||
|
func DecryptedSize(size uint64) (uint64, error) {
|
||||||
|
if size > maxEncryptedSize {
|
||||||
|
return 0, errUnexpectedSize
|
||||||
|
}
|
||||||
|
decSize := (size / maxPackageSize) * maxPayloadSize
|
||||||
|
if mod := size % maxPackageSize; mod > 0 {
|
||||||
|
if mod <= headerSize+tagSize {
|
||||||
|
return 0, errors.New("sio: size is not valid") // last package is not valid
|
||||||
|
}
|
||||||
|
decSize += mod - (headerSize + tagSize)
|
||||||
|
}
|
||||||
|
return decSize, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Encrypt reads from src until it encounters an io.EOF and encrypts all received
|
// Encrypt reads from src until it encounters an io.EOF and encrypts all received
|
||||||
// data. The encrypted data is written to dst. It returns the number of bytes
|
// data. The encrypted data is written to dst. It returns the number of bytes
|
||||||
// encrypted and the first error encountered while encrypting, if any.
|
// encrypted and the first error encountered while encrypting, if any.
|
||||||
|
2
vendor/github.com/minio/sio/writer-v1.go
generated
vendored
2
vendor/github.com/minio/sio/writer-v1.go
generated
vendored
@ -192,7 +192,7 @@ func flush(w io.Writer, p []byte) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if n != len(p) { // not neccasary if the w follows the io.Writer doc *precisly*
|
if n != len(p) { // not neccasary if the w follows the io.Writer doc *precisely*
|
||||||
return io.ErrShortWrite
|
return io.ErrShortWrite
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
2
vendor/github.com/minio/sio/writer-v2.go
generated
vendored
2
vendor/github.com/minio/sio/writer-v2.go
generated
vendored
@ -80,7 +80,7 @@ func (w *encWriterV20) Write(p []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *encWriterV20) Close() error {
|
func (w *encWriterV20) Close() error {
|
||||||
if w.offset > 0 { // true if at least one Write call happend
|
if w.offset > 0 { // true if at least one Write call happened
|
||||||
w.SealFinal(w.buffer, w.buffer[headerSize:headerSize+w.offset])
|
w.SealFinal(w.buffer, w.buffer[headerSize:headerSize+w.offset])
|
||||||
if err := flush(w.dst, w.buffer[:headerSize+w.offset+tagSize]); err != nil { // write to underlying io.Writer
|
if err := flush(w.dst, w.buffer[:headerSize+w.offset+tagSize]); err != nil { // write to underlying io.Writer
|
||||||
return err
|
return err
|
||||||
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
@ -446,10 +446,10 @@
|
|||||||
"revisionTime": "2017-08-28T17:39:33Z"
|
"revisionTime": "2017-08-28T17:39:33Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "pvBHvHfubwxgvXNz35PDMbBWY9s=",
|
"checksumSHA1": "LLNO4saSnirHPhxJQ6nk2E0VMKs=",
|
||||||
"path": "github.com/minio/sio",
|
"path": "github.com/minio/sio",
|
||||||
"revision": "83dd737d26dbcf4847f48ecec77c2c13f739eb25",
|
"revision": "b421622190be1ffb4569c7303ed1b7bef201a7c3",
|
||||||
"revisionTime": "2018-03-01T21:58:29Z"
|
"revisionTime": "2018-03-15T10:40:56Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "V/quM7+em2ByJbWBLOsEwnY3j/Q=",
|
"checksumSHA1": "V/quM7+em2ByJbWBLOsEwnY3j/Q=",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user