PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

Unsupported password algorithm: $algorithmName

Error message

Unsupported password algorithm: $algorithmName

What it means

Thrown by PasswordHasher::getAlgorithm() when the algorithm name passed to hashPassword() is non-empty but not one of the ten exact Excel algorithm identifiers (MD2, MD4, MD5, SHA-1, SHA-256, SHA-384, SHA-512, RIPEMD-128, RIPEMD-160, WHIRLPOOL — the Protection::ALGORITHM_* values). The lookup is an exact, case-sensitive array-key match, so near-misses are rejected.

Source

Thrown at src/PhpSpreadsheet/Shared/PasswordHasher.php:39

        // Mapping between algorithm name in Excel and algorithm name in PHP
        $mapping = [
            Protection::ALGORITHM_MD2 => 'md2',
            Protection::ALGORITHM_MD4 => 'md4',
            Protection::ALGORITHM_MD5 => 'md5',
            Protection::ALGORITHM_SHA_1 => 'sha1',
            Protection::ALGORITHM_SHA_256 => 'sha256',
            Protection::ALGORITHM_SHA_384 => 'sha384',
            Protection::ALGORITHM_SHA_512 => 'sha512',
            Protection::ALGORITHM_RIPEMD_128 => 'ripemd128',
            Protection::ALGORITHM_RIPEMD_160 => 'ripemd160',
            Protection::ALGORITHM_WHIRLPOOL => 'whirlpool',
        ];

        if (array_key_exists($algorithmName, $mapping)) {
            return $mapping[$algorithmName];
        }

        throw new SpException('Unsupported password algorithm: ' . $algorithmName);
    }

    /**
     * Create a password hash from a given string.
     *
     * This method is based on the spec at:
     * https://interoperability.blob.core.windows.net/files/MS-OFFCRYPTO/[MS-OFFCRYPTO].pdf
     * 2.3.7.1 Binary Document Password Verifier Derivation Method 1
     *
     * It replaces a method based on the algorithm provided by
     * Daniel Rentz of OpenOffice and the PEAR package
     * Spreadsheet_Excel_Writer by Xavier Noguer <xnoguer@rezebra.com>.
     *
     * @param string $password Password to hash
     */
    private static function defaultHashPassword(string $password): string
    {
        $verifier = 0;

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Use the constants, never literals: pass Protection::ALGORITHM_SHA_512 etc. from PhpOffice\PhpSpreadsheet\Worksheet\Protection.
  2. Normalize before calling: validate input against the ten known values (case-sensitive) and reject early with a clear message.
  3. If you only need Excel's legacy 16-bit hash, pass '' (the default) so getAlgorithm short-circuits to the default path.
  4. When the name comes from a file you parse, map it through a whitelist table keyed by the exact spec strings before invoking hashPassword().

Example fix

// before
$hash = \PhpOffice\PhpSpreadsheet\Shared\PasswordHasher::hashPassword($pw, 'sha512');
// Unsupported password algorithm: sha512

// after
use PhpOffice\PhpSpreadsheet\Worksheet\Protection;
$hash = \PhpOffice\PhpSpreadsheet\Shared\PasswordHasher::hashPassword(
    $pw,
    Protection::ALGORITHM_SHA_512, // exact 'SHA-512'
    $salt,
    $spinCount
);
Defensive patterns

Strategy: validation

Validate before calling

use PhpOffice\PhpSpreadsheet\Worksheet\Protection;
const SHEET_ALGOS = [
    Protection::ALGORITHM_MD2, Protection::ALGORITHM_MD4, Protection::ALGORITHM_MD5,
    Protection::ALGORITHM_SHA_1, Protection::ALGORITHM_SHA_256, Protection::ALGORITHM_SHA_384,
    Protection::ALGORITHM_SHA_512, Protection::ALGORITHM_RIPEMD_128,
    Protection::ALGORITHM_RIPEMD_160, Protection::ALGORITHM_WHIRLPOOL,
];
if ($algo !== '' && !in_array($algo, SHEET_ALGOS, true)) {
    throw new InvalidArgumentException("Unsupported sheet-protection algorithm: $algo");
}
$hash = PasswordHasher::hashPassword($pw, $algo, $salt, $spin);

Type guard

function validSheetAlgorithm(string $algo): ?string
{
    return in_array($algo, SHEET_ALGOS, true) ? $algo : null; // exact spec spelling or null
}

Try / catch

try { $hash = PasswordHasher::hashPassword($pw, $algo); }
catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
    if (str_contains($e->getMessage(), 'Unsupported password algorithm')) {
        $hash = PasswordHasher::hashPassword($pw); // fall back to legacy default hash
    } else { throw $e; }
}

Prevention

When it happens

Trigger: Calling PasswordHasher::hashPassword($pw, $algorithm) with e.g. 'sha512' (lowercase), 'SHA512' (missing hyphen), 'bcrypt', or a raw string from a spreadsheet's own XML where you expected the library's constant spelling; an empty string is special-cased to the legacy default hash, so only non-empty unknown names throw.

Common situations: Copying algorithm names from sheetProtection XML attributes with altered casing; passing PHP hash() names ('ripemd160' works by luck, 'sha-512' doesn't); reading algorithm names from user/DB input; version drift where older code stored different spellings.

Related errors


AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17). Data as JSON: /api/errors/a1ac733c485105c6. Report an issue: GitHub.