mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-14 20:16:34 +00:00
Preserve XLSX output before authentication
This commit is contained in:
@@ -230,12 +230,6 @@ final class AgileEncryption
|
||||
if ($input === false) {
|
||||
throw new Exception('Could not open XLSX package for decryption.');
|
||||
}
|
||||
$output = @fopen($outputFilename, 'wb');
|
||||
if ($output === false) {
|
||||
fclose($input);
|
||||
|
||||
throw new Exception('Could not open XLSX package for decryption.');
|
||||
}
|
||||
|
||||
try {
|
||||
$hash = self::passwordHash($password, $info['passwordSalt'], $info['spinCount'], $info['hashAlgorithm']);
|
||||
@@ -249,21 +243,29 @@ final class AgileEncryption
|
||||
throw new Exception('Malformed XLSX encryption information.');
|
||||
}
|
||||
self::verifyIntegrityFile($info, $secretKey, $input);
|
||||
rewind($input);
|
||||
$size = self::unpackSize(self::read($input, 8));
|
||||
for ($block = 0; $size > 0; ++$block) {
|
||||
$length = min(self::SEGMENT_SIZE, $size);
|
||||
$cipher = self::read($input, self::paddedLength($length));
|
||||
$iv = self::iv($info['keyDataSalt'], pack('V', $block), $info['hashAlgorithm']);
|
||||
self::write($output, substr(self::aesDecrypt($cipher, $secretKey, $iv, $info['keyBits']), 0, $length));
|
||||
$size -= $length;
|
||||
$output = @fopen($outputFilename, 'wb');
|
||||
if ($output === false) {
|
||||
throw new Exception('Could not open XLSX package for decryption.');
|
||||
}
|
||||
if (fread($input, 1) !== '') {
|
||||
throw new Exception('Malformed encrypted XLSX package.');
|
||||
rewind($input);
|
||||
|
||||
try {
|
||||
$size = self::unpackSize(self::read($input, 8));
|
||||
for ($block = 0; $size > 0; ++$block) {
|
||||
$length = min(self::SEGMENT_SIZE, $size);
|
||||
$cipher = self::read($input, self::paddedLength($length));
|
||||
$iv = self::iv($info['keyDataSalt'], pack('V', $block), $info['hashAlgorithm']);
|
||||
self::write($output, substr(self::aesDecrypt($cipher, $secretKey, $iv, $info['keyBits']), 0, $length));
|
||||
$size -= $length;
|
||||
}
|
||||
if (fread($input, 1) !== '') {
|
||||
throw new Exception('Malformed encrypted XLSX package.');
|
||||
}
|
||||
} finally {
|
||||
fclose($output);
|
||||
}
|
||||
} finally {
|
||||
fclose($input);
|
||||
fclose($output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -298,6 +298,27 @@ class AgileEncryptionTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testDecryptFileDoesNotTruncateOutputWhenPasswordIsIncorrect(): void
|
||||
{
|
||||
$package = AgileEncryption::encrypt('package', 'password', 128, 'SHA1', 10);
|
||||
$inputFilename = tempnam(sys_get_temp_dir(), 'phpspreadsheet-input-');
|
||||
$outputFilename = tempnam(sys_get_temp_dir(), 'phpspreadsheet-output-');
|
||||
self::assertNotFalse($inputFilename);
|
||||
self::assertNotFalse($outputFilename);
|
||||
file_put_contents($inputFilename, $package['encryptedPackage']);
|
||||
file_put_contents($outputFilename, 'preserve this content');
|
||||
|
||||
try {
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage('XLSX encryption password is incorrect');
|
||||
AgileEncryption::decryptFile(AgileEncryption::parse($package['encryptionInfo']), $inputFilename, $outputFilename, 'wrong');
|
||||
} finally {
|
||||
self::assertSame('preserve this content', file_get_contents($outputFilename));
|
||||
unlink($inputFilename);
|
||||
unlink($outputFilename);
|
||||
}
|
||||
}
|
||||
|
||||
public function testDecryptFileClosesInputWhenOutputCannotBeOpened(): void
|
||||
{
|
||||
$package = AgileEncryption::encrypt('package', 'password', 128, 'SHA1', 10);
|
||||
@@ -327,12 +348,14 @@ class AgileEncryptionTest extends TestCase
|
||||
self::assertNotFalse($inputFilename);
|
||||
self::assertNotFalse($outputFilename);
|
||||
file_put_contents($inputFilename, $package['encryptedPackage']);
|
||||
file_put_contents($outputFilename, 'preserve this content');
|
||||
|
||||
try {
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage('integrity check failed');
|
||||
AgileEncryption::decryptFile(AgileEncryption::parse($package['encryptionInfo']), $inputFilename, $outputFilename, 'password');
|
||||
} finally {
|
||||
self::assertSame('preserve this content', file_get_contents($outputFilename));
|
||||
unlink($inputFilename);
|
||||
unlink($outputFilename);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user