randomly genereate salt for word password protection
This commit is contained in:
parent
703e34137b
commit
0221414ee0
|
|
@ -45,14 +45,14 @@ class Protection
|
||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $spinCount = 0;
|
private $spinCount = 100000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Algorithm-SID (see to \PhpOffice\PhpWord\Writer\Word2007\Part\Settings::$algorithmMapping)
|
* Algorithm-SID (see to \PhpOffice\PhpWord\Writer\Word2007\Part\Settings::$algorithmMapping)
|
||||||
*
|
*
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
private $algorithmSid = 0;
|
private $mswordAlgorithmSid = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hashed salt
|
* Hashed salt
|
||||||
|
|
@ -145,20 +145,20 @@ class Protection
|
||||||
*
|
*
|
||||||
* @return int
|
* @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)
|
* Set algorithm-sid (see \PhpOffice\PhpWord\Writer\Word2007\Part\Settings::$algorithmMapping)
|
||||||
*
|
*
|
||||||
* @param $algorithmSid
|
* @param $mswordAlgorithmSid
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function setAlgorithmSid($algorithmSid)
|
public function setMswordAlgorithmSid($mswordAlgorithmSid)
|
||||||
{
|
{
|
||||||
$this->algorithmSid = $algorithmSid;
|
$this->mswordAlgorithmSid = $mswordAlgorithmSid;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -213,6 +213,9 @@ class Settings extends AbstractPart
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
if ($protection->getSalt() == null) {
|
||||||
|
$protection->setSalt(openssl_random_pseudo_bytes(16));
|
||||||
|
}
|
||||||
$this->settings['w:documentProtection'] = array(
|
$this->settings['w:documentProtection'] = array(
|
||||||
'@attributes' => array(
|
'@attributes' => array(
|
||||||
'w:enforcement' => 1,
|
'w:enforcement' => 1,
|
||||||
|
|
@ -220,7 +223,7 @@ class Settings extends AbstractPart
|
||||||
'w:cryptProviderType' => 'rsaFull',
|
'w:cryptProviderType' => 'rsaFull',
|
||||||
'w:cryptAlgorithmClass' => 'hash',
|
'w:cryptAlgorithmClass' => 'hash',
|
||||||
'w:cryptAlgorithmType' => 'typeAny',
|
'w:cryptAlgorithmType' => 'typeAny',
|
||||||
'w:cryptAlgorithmSid' => $protection->getAlgorithmSid(),
|
'w:cryptAlgorithmSid' => $protection->getMswordAlgorithmSid(),
|
||||||
'w:cryptSpinCount' => $protection->getSpinCount(),
|
'w:cryptSpinCount' => $protection->getSpinCount(),
|
||||||
'w:hash' => $this->getPasswordHash($protection),
|
'w:hash' => $this->getPasswordHash($protection),
|
||||||
'w:salt' => $this->getSaltHash($protection->getSalt()),
|
'w:salt' => $this->getSaltHash($protection->getSalt()),
|
||||||
|
|
@ -239,11 +242,13 @@ class Settings extends AbstractPart
|
||||||
{
|
{
|
||||||
$compatibility = $this->getParentWriter()->getPhpWord()->getCompatibility();
|
$compatibility = $this->getParentWriter()->getPhpWord()->getCompatibility();
|
||||||
if ($compatibility->getOoxmlVersion() !== null) {
|
if ($compatibility->getOoxmlVersion() !== null) {
|
||||||
$this->settings['w:compat']['w:compatSetting'] = array('@attributes' => array(
|
$this->settings['w:compat']['w:compatSetting'] = array(
|
||||||
'w:name' => 'compatibilityMode',
|
'@attributes' => array(
|
||||||
'w:uri' => 'http://schemas.microsoft.com/office/word',
|
'w:name' => 'compatibilityMode',
|
||||||
'w:val' => $compatibility->getOoxmlVersion(),
|
'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
|
// build low-order word and hig-order word and combine them
|
||||||
$combinedKey = $this->buildCombinedKey($byteChars);
|
$combinedKey = $this->buildCombinedKey($byteChars);
|
||||||
// build reversed hexadecimal string
|
// build reversed hexadecimal string
|
||||||
$hex = strtoupper(dechex($combinedKey & 0xFFFFFFFF));
|
$hex = strtoupper(dechex($combinedKey & 0xFFFFFFFF));
|
||||||
$reversedHex = $hex[6].$hex[7].$hex[4].$hex[5].$hex[2].$hex[3].$hex[0].$hex[1];
|
$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');
|
$generatedKey = mb_convert_encoding($reversedHex, 'UCS-2LE', 'UTF-8');
|
||||||
|
|
||||||
// Implementation Notes List:
|
// Implementation Notes List:
|
||||||
// Word requires that the initial hash of the password with the salt not be considered in the count.
|
// 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.
|
// 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);
|
$generatedKey = hash($algorithm, base64_decode($this->getSaltHash($protection->getSalt())) . $generatedKey, true);
|
||||||
|
|
||||||
$spinCount = (!empty($protection->getSpinCount())) ? $protection->getSpinCount() : 100000;
|
for ($i = 0; $i < $protection->getSpinCount(); $i++) {
|
||||||
|
$generatedKey = hash($algorithm, $generatedKey . pack("CCCC", $i, $i >> 8, $i >> 16, $i >> 24), true);
|
||||||
for ($i = 0; $i < $spinCount; $i++) {
|
|
||||||
$generatedKey = hash($algorithm, $generatedKey . pack("CCCC", $i, $i>>8, $i>>16, $i>>24), true);
|
|
||||||
}
|
}
|
||||||
$generatedKey = base64_encode($generatedKey);
|
$generatedKey = base64_encode($generatedKey);
|
||||||
|
|
||||||
|
|
@ -308,10 +311,6 @@ class Settings extends AbstractPart
|
||||||
*/
|
*/
|
||||||
private function getAlgorithm($sid)
|
private function getAlgorithm($sid)
|
||||||
{
|
{
|
||||||
if (empty($sid)) {
|
|
||||||
$sid = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
$algorithm = self::$algorithmMapping[$sid];
|
$algorithm = self::$algorithmMapping[$sid];
|
||||||
if ($algorithm == '') {
|
if ($algorithm == '') {
|
||||||
$algorithm = 'sha1';
|
$algorithm = 'sha1';
|
||||||
|
|
@ -328,7 +327,7 @@ class Settings extends AbstractPart
|
||||||
*/
|
*/
|
||||||
private function getSaltHash($salt)
|
private function getSaltHash($salt)
|
||||||
{
|
{
|
||||||
return $salt;
|
return base64_encode(str_pad(substr($salt, 0, 16), 16, '1'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue