Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
1 <?php 2 3 namespace PhpOffice\PhpSpreadsheet\Shared; 4 5 use PhpOffice\PhpSpreadsheet\Exception; 6 use PhpOffice\PhpSpreadsheet\Worksheet\Protection; 7 8 class PasswordHasher 9 { 10 /** 11 * Get algorithm name for PHP. 12 */ 13 private static function getAlgorithm(string $algorithmName): string 14 { 15 if (!$algorithmName) { 16 return ''; 17 } 18 19 // Mapping between algorithm name in Excel and algorithm name in PHP 20 $mapping = [ 21 Protection::ALGORITHM_MD2 => 'md2', 22 Protection::ALGORITHM_MD4 => 'md4', 23 Protection::ALGORITHM_MD5 => 'md5', 24 Protection::ALGORITHM_SHA_1 => 'sha1', 25 Protection::ALGORITHM_SHA_256 => 'sha256', 26 Protection::ALGORITHM_SHA_384 => 'sha384', 27 Protection::ALGORITHM_SHA_512 => 'sha512', 28 Protection::ALGORITHM_RIPEMD_128 => 'ripemd128', 29 Protection::ALGORITHM_RIPEMD_160 => 'ripemd160', 30 Protection::ALGORITHM_WHIRLPOOL => 'whirlpool', 31 ]; 32 33 if (array_key_exists($algorithmName, $mapping)) { 34 return $mapping[$algorithmName]; 35 } 36 37 throw new Exception('Unsupported password algorithm: ' . $algorithmName); 38 } 39 40 /** 41 * Create a password hash from a given string. 42 * 43 * This method is based on the algorithm provided by 44 * Daniel Rentz of OpenOffice and the PEAR package 45 * Spreadsheet_Excel_Writer by Xavier Noguer <xnoguer@rezebra.com>. 46 * 47 * @param string $pPassword Password to hash 48 */ 49 private static function defaultHashPassword(string $pPassword): string 50 { 51 $password = 0x0000; 52 $charPos = 1; // char position 53 54 // split the plain text password in its component characters 55 $chars = preg_split('//', $pPassword, -1, PREG_SPLIT_NO_EMPTY); 56 foreach ($chars as $char) { 57 $value = ord($char) << $charPos++; // shifted ASCII value 58 $rotated_bits = $value >> 15; // rotated bits beyond bit 15 59 $value &= 0x7fff; // first 15 bits 60 $password ^= ($value | $rotated_bits); 61 } 62 63 $password ^= strlen($pPassword); 64 $password ^= 0xCE4B; 65 66 return strtoupper(dechex($password)); 67 } 68 69 /** 70 * Create a password hash from a given string by a specific algorithm. 71 * 72 * 2.4.2.4 ISO Write Protection Method 73 * 74 * @see https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-offcrypto/1357ea58-646e-4483-92ef-95d718079d6f 75 * 76 * @param string $password Password to hash 77 * @param string $algorithm Hash algorithm used to compute the password hash value 78 * @param string $salt Pseudorandom string 79 * @param int $spinCount Number of times to iterate on a hash of a password 80 * 81 * @return string Hashed password 82 */ 83 public static function hashPassword(string $password, string $algorithm = '', string $salt = '', int $spinCount = 10000): string 84 { 85 $phpAlgorithm = self::getAlgorithm($algorithm); 86 if (!$phpAlgorithm) { 87 return self::defaultHashPassword($password); 88 } 89 90 $saltValue = base64_decode($salt); 91 $encodedPassword = mb_convert_encoding($password, 'UCS-2LE', 'UTF-8'); 92 93 $hashValue = hash($phpAlgorithm, $saltValue . $encodedPassword, true); 94 for ($i = 0; $i < $spinCount; ++$i) { 95 $hashValue = hash($phpAlgorithm, $hashValue . pack('L', $i), true); 96 } 97 98 return base64_encode($hashValue); 99 } 100 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body