password_get_info
Returns the algorithm, name and options recorded inside a hash created by password_hash.
password_get_info(string $hash): array- Added in PHP 5.5.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$hash | string | A hash created by password_hash(). Any string is accepted; unrecognised input simply reports an unknown algorithm. |
Return value
arrayAn associative array with three keys: algo (the algorithm ID string, or null if the hash is not recognised), algoName (a human-readable name, or "unknown"), and options (the parameters embedded in the hash, such as cost for bcrypt).
Errors
Does not throw for malformed input; an unrecognised hash simply returns algo null and algoName "unknown".
Changelog
- PHP 7.4.0The algo key is now a string ("2y", "argon2id") instead of an int, matching the change to the PASSWORD_* constants. Code comparing it to 1 or 2 broke.
A hash from password_hash is self-describing: the algorithm, its cost parameters and the salt are all packed into the one string you store. password_get_info unpacks the descriptive part of it, without needing the password.
The options key only reports what the hash format actually encodes. For bcrypt that is cost. For Argon2 you get memory_cost, time_cost and threads. The salt is never returned, and neither is anything that would help an attacker.
When to reach for it
Reach for it when you are auditing or migrating a user table: run over stored hashes to find out how many are still bcrypt cost 10, how many are legacy MD5 leftovers from an old system, and how many already use Argon2id. It is also the cheapest way to branch on hash type when your users table holds a mixture of formats from an import.
It is not a validity check. Any string is accepted, so a truncated column, a NULL read as "", or a bare MD5 all return quietly with algoName set to unknown rather than raising an error. Check the algo key yourself if you need to know a hash is usable.
Example
When to use it
- Audit a users table to count how many stored hashes still use an outdated bcrypt cost
- Detect legacy MD5 or SHA-1 hashes imported from an old system so you can upgrade them at next login
- Log which algorithm a failing account's hash uses when debugging a login problem
- Confirm after a deploy that new signups are really being hashed with Argon2id
Frequently asked questions
Does password_get_info tell me if a hash is valid?
No. It never fails and never verifies anything; an empty string or a random value returns algo null with algoName "unknown". Treat a null algo as "not a password_hash hash", and use password_verify to check a password against it.
Why is the algo key a string instead of a number?
As of PHP 7.4 the PASSWORD_* constants and the algo key are strings such as "2y" and "argon2id". Older code comparing algo to the integer 1 silently stopped matching after upgrading.
Can password_get_info recover the salt or the password?
No. It returns only the algorithm ID, its readable name and the cost options. The salt is deliberately excluded and the password is not stored in the hash at all.
More examples
Find hashes that came from a legacy system
Only Ana's row reports "bcrypt"; Bo's MD5 and Cleo's empty column both come back with algo null and are flagged. This is the exact scan you run before a migration, and it shows why a null algo means "not a password_hash hash" rather than "broken".
<?php
$stored = [
'ana' => password_hash('a', PASSWORD_BCRYPT, ['cost' => 4]),
'bo' => md5('b'), // imported from an old app
'cleo' => '', // column was NULL
];
foreach ($stored as $user => $hash) {
$info = password_get_info($hash);
$state = $info['algo'] === null ? 'NEEDS MIGRATION' : $info['algoName'];
echo "$user: $state\n";
}Read the bcrypt cost out of a hash
The cost is visible in the hash prefix ($2y$04$, $2y$06$, $2y$08$) and password_get_info parses it into options['cost'] for you. Reading it this way is how you decide whether a hash predates a cost increase without hardcoding string offsets.
<?php
foreach ([4, 6, 8] as $cost) {
$hash = password_hash('secret', PASSWORD_BCRYPT, ['cost' => $cost]);
$info = password_get_info($hash);
printf("prefix %-8s => cost %d\n", substr($hash, 0, 7), $info['options']['cost']);
}
Discussion