PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

Password exceeds 255 characters

Error message

Password exceeds 255 characters

What it means

Thrown by PasswordHasher::hashPassword() when the password exceeds MAX_PASSWORD_LENGTH (255 characters). The MS-OFFCRYPTO password-verifier derivation the class implements is only defined for strings up to 255 characters, so longer input is rejected outright rather than hashed.

Source

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

    /**
     * Create a password hash from a given string by a specific algorithm.
     *
     * 2.4.2.4 ISO Write Protection Method
     *
     * @see https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-offcrypto/1357ea58-646e-4483-92ef-95d718079d6f
     *
     * @param string $password Password to hash
     * @param string $algorithm Hash algorithm used to compute the password hash value
     * @param string $salt Pseudorandom base64-encoded string
     * @param int $spinCount Number of times to iterate on a hash of a password
     *
     * @return string Hashed password
     */
    public static function hashPassword(string $password, string $algorithm = '', string $salt = '', int $spinCount = 10000): string
    {
        if (strlen($password) > self::MAX_PASSWORD_LENGTH) {
            throw new SpException('Password exceeds ' . self::MAX_PASSWORD_LENGTH . ' characters');
        }
        $phpAlgorithm = self::getAlgorithm($algorithm);
        if (!$phpAlgorithm) {
            return self::defaultHashPassword($password);
        }

        $saltValue = base64_decode($salt);
        $encodedPassword = mb_convert_encoding($password, 'UCS-2LE', 'UTF-8');

        $hashValue = hash($phpAlgorithm, $saltValue . $encodedPassword, true);
        for ($i = 0; $i < $spinCount; ++$i) {
            $hashValue = hash($phpAlgorithm, $hashValue . pack('L', $i), true);
        }

        return base64_encode($hashValue);
    }
}

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Enforce a <= 255 cap in the UI/API that collects the protection password and explain the limit.
  2. If a longer secret is mandatory, hash/derive a <=255-byte value first (e.g. substr(sha1($secret), 0, 40)) and use that as the workbook password, documenting that the sheet password is now derived.
  3. Trim accidental whitespace/newlines from pasted input before the length check.
  4. Catch the exception and return a validation error rather than letting it bubble into a 500.

Example fix

// before
$hash = PasswordHasher::hashPassword($request->input('password'));
// Password exceeds 255 characters

// after
$password = trim((string) $request->input('password'));
if (strlen($password) > 255) {
    throw new \InvalidArgumentException('Sheet protection password must be at most 255 characters.');
}
$hash = PasswordHasher::hashPassword($password);
Defensive patterns

Strategy: validation

Validate before calling

define('SHEET_PASSWORD_MAX', 255);
$password = trim($password);
if (strlen($password) > SHEET_PASSWORD_MAX) {
    throw new InvalidArgumentException(
        sprintf('Sheet password too long: %d chars (max %d).', strlen($password), SHEET_PASSWORD_MAX)
    );
}

Type guard

function sheetPasswordCandidate(mixed $pw): ?string
{
    return (is_string($pw) && strlen(trim($pw)) > 0 && strlen($pw) <= 255) ? $pw : null;
}

Try / catch

try { $hash = PasswordHasher::hashPassword($password); }
catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
    if (str_contains($e->getMessage(), 'exceeds')) {
        // decide policy: reject, or derive a shorter password from the secret
        throw new DomainException('Password must be at most 255 characters.', 0, $e);
    }
    throw $e;
}

Prevention

When it happens

Trigger: Calling hashPassword($password) with strlen($password) > 255 — e.g. hashing a passphrase, a generated token, or accidental input like pasted multi-line text or a whole array-as-string; also when reading user-supplied passwords for sheet protection without an upstream length cap.

Common situations: Applications that reuse login passphrases (arbitrary length) as sheet-protection passwords; unit tests using long random strings; user paste errors; feeding base64 blobs where a password belonged.

Related errors


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