Skip to content

Commit 6bfbbee

Browse files
authored
This closes #2328, correct Agile EncryptedPackage 4096-byte chunk boundary handling during decryption (#2329)
- Fix an issue where workbooks protected by ECMA-376 agile encryption with SHA512 hash algorithm failed to open in some cases - Add a test workbook with the SHA512 hash algorithm - Updated unit tests
1 parent 4bebb61 commit 6bfbbee

3 files changed

Lines changed: 19 additions & 7 deletions

File tree

crypt.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,13 @@ func decrypt(key, iv, input []byte) (packageKey []byte, err error) {
510510
// decryptPackage decrypt package by given packageKey and encryption
511511
// info.
512512
func decryptPackage(packageKey, input []byte, encryption Encryption) (outputChunks []byte, err error) {
513-
encryptedKey, offset := encryption.KeyData, packageOffset
513+
encryptedKey := encryption.KeyData
514+
if len(input) < packageOffset {
515+
err = ErrWorkbookFileFormat
516+
return
517+
}
518+
packageSize := binary.LittleEndian.Uint64(input[:packageOffset])
519+
input = input[packageOffset:]
514520
var i, start, end int
515521
var iv, outputChunk []byte
516522
for end < len(input) {
@@ -521,12 +527,7 @@ func decryptPackage(packageKey, input []byte, encryption Encryption) (outputChun
521527
end = len(input)
522528
}
523529
// Grab the next chunk
524-
var inputChunk []byte
525-
if (end + offset) < len(input) {
526-
inputChunk = input[start+offset : end+offset]
527-
} else {
528-
inputChunk = input[start+offset : end]
529-
}
530+
inputChunk := input[start:end]
530531

531532
// Pad the chunk if it is not an integer multiple of the block size
532533
remainder := len(inputChunk) % encryptedKey.BlockSize
@@ -546,6 +547,9 @@ func decryptPackage(packageKey, input []byte, encryption Encryption) (outputChun
546547
outputChunks = append(outputChunks, outputChunk...)
547548
i++
548549
}
550+
if uint64(len(outputChunks)) > packageSize {
551+
outputChunks = outputChunks[:int(packageSize)]
552+
}
549553
return
550554
}
551555

crypt_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ func TestEncrypt(t *testing.T) {
3535
assert.NoError(t, err)
3636
assert.Equal(t, "SECRET", cell)
3737
assert.NoError(t, f.Close())
38+
f, err = OpenFile(filepath.Join("test", "encryptSHA512.xlsx"), Options{Password: "password"})
39+
assert.NoError(t, err)
40+
cell, err = f.GetCellValue("Sheet1", "A1")
41+
assert.NoError(t, err)
42+
assert.Equal(t, "SECRET", cell)
43+
assert.NoError(t, f.Close())
3844
// Test decrypt spreadsheet with unsupported encrypt mechanism
3945
raw, err := os.ReadFile(filepath.Join("test", "encryptAES.xlsx"))
4046
assert.NoError(t, err)
@@ -138,6 +144,8 @@ func TestEncrypt(t *testing.T) {
138144
},
139145
})
140146
assert.Error(t, err)
147+
_, err = decryptPackage(make([]byte, 32), input[:packageOffset-1], Encryption{})
148+
assert.Equal(t, ErrWorkbookFileFormat, err)
141149
// Test put with path that is a prefix of name
142150
compoundFile = &cfb{
143151
paths: []string{"Root Entry/"},

test/encryptSHA512.xlsx

12 KB
Binary file not shown.

0 commit comments

Comments
 (0)