diff --git a/crypt/cipher.go b/crypt/cipher.go index 58a81c71a..85ee101f1 100644 --- a/crypt/cipher.go +++ b/crypt/cipher.go @@ -579,6 +579,11 @@ func (fh *decrypter) fillBuffer() (err error) { block := fh.buf _, ok := secretbox.Open(block[:0], readBuf[:n], fh.nonce.pointer(), &fh.c.dataKey) if !ok { + // if block wouldn't decode and got unexpected EOF + // then return that as it is probably a better error + if err != nil { + return err + } return ErrorEncryptedBadBlock } fh.bufIndex = 0 diff --git a/crypt/cipher_test.go b/crypt/cipher_test.go index 5bacdcdcd..0d4414bdd 100644 --- a/crypt/cipher_test.go +++ b/crypt/cipher_test.go @@ -917,14 +917,36 @@ func TestDecrypterRead(t *testing.T) { c, err := newCipher(NameEncryptionStandard, "", "") assert.NoError(t, err) - // Test truncating the header - for i := 1; i < blockHeaderSize; i++ { - cd := newCloseDetector(bytes.NewBuffer(file1[:len(file1)-i])) + // Test truncating the file at each possible point + for i := 0; i < len(file16)-1; i++ { + what := fmt.Sprintf("truncating to %d/%d", i, len(file16)) + cd := newCloseDetector(bytes.NewBuffer(file16[:i])) fh, err := c.newDecrypter(cd) - assert.NoError(t, err) + if i < fileHeaderSize { + assert.EqualError(t, err, ErrorEncryptedFileTooShort.Error(), what) + continue + } + if err != nil { + assert.NoError(t, err, what) + continue + } _, err = ioutil.ReadAll(fh) - assert.Error(t, err, ErrorEncryptedFileBadHeader.Error()) - assert.Equal(t, 0, cd.closed) + var expectedErr error + switch { + case i == fileHeaderSize: + // This would normally produce an error *except* on the first block + expectedErr = nil + case i <= fileHeaderSize+blockHeaderSize: + expectedErr = ErrorEncryptedFileBadHeader + default: + expectedErr = io.ErrUnexpectedEOF + } + if expectedErr != nil { + assert.EqualError(t, err, expectedErr.Error(), what) + } else { + assert.NoError(t, err, what) + } + assert.Equal(t, 0, cd.closed, what) } // Test producing an error on the file on Read the underlying file