From 0221414ee0855612b6a5f09412790fb2bf2dfd1e Mon Sep 17 00:00:00 2001 From: Maria Haubner Date: Fri, 10 Mar 2017 16:57:42 +0100 Subject: [PATCH] randomly genereate salt for word password protection --- src/PhpWord/Metadata/Protection.php | 14 ++++---- src/PhpWord/Writer/Word2007/Part/Settings.php | 35 +++++++++---------- 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/PhpWord/Metadata/Protection.php b/src/PhpWord/Metadata/Protection.php index 511503e4..a25a8f31 100644 --- a/src/PhpWord/Metadata/Protection.php +++ b/src/PhpWord/Metadata/Protection.php @@ -45,14 +45,14 @@ class Protection * * @var int */ - private $spinCount = 0; + private $spinCount = 100000; /** * Algorithm-SID (see to \PhpOffice\PhpWord\Writer\Word2007\Part\Settings::$algorithmMapping) * * @var int */ - private $algorithmSid = 0; + private $mswordAlgorithmSid = 4; /** * Hashed salt @@ -145,20 +145,20 @@ class Protection * * @return int */ - public function getAlgorithmSid() + public function getMswordAlgorithmSid() { - return $this->algorithmSid; + return $this->mswordAlgorithmSid; } /** * Set algorithm-sid (see \PhpOffice\PhpWord\Writer\Word2007\Part\Settings::$algorithmMapping) * - * @param $algorithmSid + * @param $mswordAlgorithmSid * @return self */ - public function setAlgorithmSid($algorithmSid) + public function setMswordAlgorithmSid($mswordAlgorithmSid) { - $this->algorithmSid = $algorithmSid; + $this->mswordAlgorithmSid = $mswordAlgorithmSid; return $this; } diff --git a/src/PhpWord/Writer/Word2007/Part/Settings.php b/src/PhpWord/Writer/Word2007/Part/Settings.php index ed9c07d3..c709ee62 100644 --- a/src/PhpWord/Writer/Word2007/Part/Settings.php +++ b/src/PhpWord/Writer/Word2007/Part/Settings.php @@ -213,6 +213,9 @@ class Settings extends AbstractPart ) ); } else { + if ($protection->getSalt() == null) { + $protection->setSalt(openssl_random_pseudo_bytes(16)); + } $this->settings['w:documentProtection'] = array( '@attributes' => array( 'w:enforcement' => 1, @@ -220,7 +223,7 @@ class Settings extends AbstractPart 'w:cryptProviderType' => 'rsaFull', 'w:cryptAlgorithmClass' => 'hash', 'w:cryptAlgorithmType' => 'typeAny', - 'w:cryptAlgorithmSid' => $protection->getAlgorithmSid(), + 'w:cryptAlgorithmSid' => $protection->getMswordAlgorithmSid(), 'w:cryptSpinCount' => $protection->getSpinCount(), 'w:hash' => $this->getPasswordHash($protection), 'w:salt' => $this->getSaltHash($protection->getSalt()), @@ -239,11 +242,13 @@ class Settings extends AbstractPart { $compatibility = $this->getParentWriter()->getPhpWord()->getCompatibility(); if ($compatibility->getOoxmlVersion() !== null) { - $this->settings['w:compat']['w:compatSetting'] = array('@attributes' => array( - 'w:name' => 'compatibilityMode', - 'w:uri' => 'http://schemas.microsoft.com/office/word', - 'w:val' => $compatibility->getOoxmlVersion(), - )); + $this->settings['w:compat']['w:compatSetting'] = array( + '@attributes' => array( + 'w:name' => 'compatibilityMode', + 'w:uri' => 'http://schemas.microsoft.com/office/word', + 'w:val' => $compatibility->getOoxmlVersion(), + ) + ); } } @@ -277,21 +282,19 @@ class Settings extends AbstractPart // build low-order word and hig-order word and combine them $combinedKey = $this->buildCombinedKey($byteChars); // build reversed hexadecimal string - $hex = strtoupper(dechex($combinedKey & 0xFFFFFFFF)); - $reversedHex = $hex[6].$hex[7].$hex[4].$hex[5].$hex[2].$hex[3].$hex[0].$hex[1]; + $hex = strtoupper(dechex($combinedKey & 0xFFFFFFFF)); + $reversedHex = $hex[6] . $hex[7] . $hex[4] . $hex[5] . $hex[2] . $hex[3] . $hex[0] . $hex[1]; $generatedKey = mb_convert_encoding($reversedHex, 'UCS-2LE', 'UTF-8'); // Implementation Notes List: // Word requires that the initial hash of the password with the salt not be considered in the count. // The initial hash of salt + key is not included in the iteration count. - $algorithm = $this->getAlgorithm($protection->getAlgorithmSid()); + $algorithm = $this->getAlgorithm($protection->getMswordAlgorithmSid()); $generatedKey = hash($algorithm, base64_decode($this->getSaltHash($protection->getSalt())) . $generatedKey, true); - $spinCount = (!empty($protection->getSpinCount())) ? $protection->getSpinCount() : 100000; - - for ($i = 0; $i < $spinCount; $i++) { - $generatedKey = hash($algorithm, $generatedKey . pack("CCCC", $i, $i>>8, $i>>16, $i>>24), true); + for ($i = 0; $i < $protection->getSpinCount(); $i++) { + $generatedKey = hash($algorithm, $generatedKey . pack("CCCC", $i, $i >> 8, $i >> 16, $i >> 24), true); } $generatedKey = base64_encode($generatedKey); @@ -308,10 +311,6 @@ class Settings extends AbstractPart */ private function getAlgorithm($sid) { - if (empty($sid)) { - $sid = 4; - } - $algorithm = self::$algorithmMapping[$sid]; if ($algorithm == '') { $algorithm = 'sha1'; @@ -328,7 +327,7 @@ class Settings extends AbstractPart */ private function getSaltHash($salt) { - return $salt; + return base64_encode(str_pad(substr($salt, 0, 16), 16, '1')); } /**