By default, each time a new hash is generated (e.g. wp_hash_password()
) WordPress salts it with random bytes, producing a unique hash for each call. The string returned from wp_hash_password()
consists of four parts concatenated in order - the hashing algorithm ID, the exponent of hash iterations, the randomly generated salt, and finally the salted and hashed password.
For example, given the default hashing configuration, in the string $P$BI17Hnqifi2CHQsPi5z/nVbEInNjl21
:
$P$
is the algorithm identifier
B
indicates the number of hashing iterations
I17Hnqif
is the random salt
i2CHQsPi5z/nVbEInNjl21
is the salted and hashed password
When checking a plaintext password against the hash of a stored user password, instead of simply querying the database for a matching user/password hash, WordPress retrieves the stored hash for the user and passes it into wp_check_password()
alongside the plaintext password. The checking algorithm extracts the salt and iteration count from the stored hash, and uses them to generate a hash of the plaintext password before checking the two against one another.
This mechanism adds a layer of protection against rainbow table attacks as it makes precomputing/using a dictionary of hashes to passwords more expensive - instead of a single hash for a single input, in WordPress' case there are octillions of possible hashes for a single input.
A brief overview of the general technique can be found here. The source of the PasswordHash
class can be scoured for the specifics as they relate to WordPress.
var_dump( wp_check_password( $x, wp_hash_password( $x ) ) );
to see if it isn't alwaystrue
.