In modern web application development, securely storing user passwords is crucial. PHP's built-in crypt() function supports multiple encryption algorithms, including the Blowfish encryption algorithm. Blowfish is widely used for password hashing due to its high strength and customizable work factor (cost). This article will provide a detailed guide on how to use PHP's crypt() function to securely encrypt passwords using the Blowfish algorithm (identifier $2y$).
Blowfish is a symmetric key encryption algorithm designed to replace older encryption algorithms. For password hashing, Blowfish provides excellent resistance against brute-force attacks with its adjustable "work factor." The higher the work factor, the longer it takes to compute the encryption, thus enhancing password security.
PHP's crypt() function uses the $2y$ identifier to represent the Blowfish hash format, which is recommended for PHP 5.3.7 and later versions, ensuring security improvements over earlier versions.
Blowfish's salt is a 22-character string containing a-z, A-Z, 0-9, ., /, totaling 64 characters. The crypt() function requires the salt format 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, representing 2^12 hash computations, approximately 4096 times, providing good security without being too slow.
$password = 'your_password_here';
$hash = crypt($password, $salt);
The resulting $hash is a complete Blowfish hash string, which can be stored directly in the database.
To verify the password, simply use the original hash as the salt in the crypt() function and compare the result:
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/zh/function.crypt.php