In modern web application development, securely storing user passwords is critical. PHP's built-in crypt() function supports various encryption algorithms, including Blowfish. The Blowfish algorithm is widely used for password hashing due to its high strength and customizable work factor (cost). This article will provide a detailed explanation of how to use PHP's crypt() function with the Blowfish algorithm (denoted as $2y$) to securely encrypt passwords.
Blowfish is a symmetric key encryption algorithm designed to replace older encryption algorithms. For password hashing, Blowfish offers good resistance against brute-force attacks with its adjustable "work factor." The higher the work factor, the longer the time required to compute the encryption, thus enhancing password security.
PHP's crypt() function uses the $2y$ identifier to represent the Blowfish hash format. This is the recommended format for PHP 5.3.7 and above, which helps avoid security issues present in earlier versions.
The salt for Blowfish encryption is a 22-character string containing a-z, A-Z, 0-9, ., and / characters, totaling 64 possible characters. PHP's crypt() function requires the salt to be formatted as follows:
$2y$ + two-digit work factor (cost) + $ + 22-character salt
For example:
$salt = '$2y$12$' . substr(strtr(base64_encode(random_bytes(16)), '+', '.'), 0, 22);
Here, 12 is the work factor, indicating 2^12 iterations of hashing, which is roughly 4096 iterations—both secure and efficient.
$password = 'your_password_here';
$hash = crypt($password, $salt);
The returned $hash is a complete Blowfish hash string that can be directly stored in the database.
To verify the password, simply call crypt() with the original hash as the salt and compare the results:
function verify_password($password, $hash) {
return crypt($password, $hash) === $hash;
}
<?php
<p>// Generate a secure salt<br>
function generate_blowfish_salt($cost = 12) {<br>
if ($cost < 4 || $cost > 31) {<br>
throw new InvalidArgumentException("Work factor must be between 4 and 31");<br>
}<br>
$randomBytes = random_bytes(16);<br>
$base64Salt = substr(strtr(base64_encode($randomBytes), '+', '.'), 0, 22);<br>
return sprintf('$2y$%02d$%s', $cost, $base64Salt);<br>
}</p>
<p>// Encrypt password<br>
function encrypt_password($password, $cost = 12) {<br>
$salt = generate_blowfish_salt($cost);<br>
return crypt($password, $salt);<br>
}</p>
<p>// Verify password<br>
function verify_password($password, $hash) {<br>
return crypt($password, $hash) === $hash;<br>
}</p>
<p>// Test<br>
$password = 'mypassword123';<br>
$hash = encrypt_password($password);</p>
<p>echo "Password Hash: $hash\n";</p>
<p>if (verify_password('mypassword123', $hash)) {<br>
echo "Password verification successful!\n";<br>
} else {<br>
echo "Password verification failed!\n";<br>
}<br>
?><br>
PHP Official Documentation: https://www.m66.net/manual/en/function.crypt.php