When using PHP's crypt() function for password encryption, many developers will notice a strange phenomenon: sometimes the length of the encryption result is 13 characters, sometimes 20, 34, or even more. This inconsistency in length can easily make people mistakenly think that there is something wrong with the code, or that the password is truncated or encrypted incorrectly. So, what's going on?
PHP's crypt() function is an encapsulated encryption interface, and the underlying layer depends on the encryption algorithm provided by the operating system. The first parameter of this function is the string to be encrypted, and the second parameter is "salt". This salt value not only affects the uniqueness of the encryption result, but also determines which encryption algorithm is used.
echo crypt("mypassword", "salt");
If you don't give salt values or use incorrect format, PHP will automatically fall back to older encryption methods, such as the traditional DES (Data Encryption Standard) algorithm, which will result in very short output, usually only 13 characters.
The crypt() function supports multiple algorithms, and different algorithms are determined by the prefix of the salt value. Here are several common salt value formats and their corresponding encryption algorithms:
algorithm | Salt value format | Result length |
---|---|---|
DES | 2 characters | 13 characters |
MD5 | $1$... | 34 characters |
Blowfish | $2a$... / $2y$... | 60 characters |
SHA-256 | $5$... | 43 characters |
SHA-512 | $6$... | 86 characters |
So if you don't explicitly pass in a prefixed salt value, or pass in a non-formatted salt value, PHP is likely to return to using old DES encryption, which only outputs 13 characters.
For example:
// use SHA-512 encryption
echo crypt("mypassword", '$6$rounds=5000$usesomesillystring$');
// The output is similar to:$6$rounds=5000$usesomesill...(Total length approximately86)
And the following code uses the default DES algorithm:
echo crypt("mypassword", 'sa');
// The output is similar to:sahGDf/YwKdl6(only13Characters)
To avoid this problem, always use salt values with explicit prefixes, preferably the generated random salts, and choose safer algorithms such as Blowfish ( $2y$ ) or SHA-512 ( $6$ ).
You can automatically generate salt values like this:
function generateSalt($algo = 'sha512') {
switch ($algo) {
case 'blowfish':
return '$2y$10$' . substr(str_replace('+', '.', base64_encode(random_bytes(22))), 0, 22);
case 'sha256':
return '$5$' . bin2hex(random_bytes(6));
case 'sha512':
default:
return '$6$' . bin2hex(random_bytes(6));
}
}
$password = 'mypassword';
$salt = generateSalt('sha512');
$hash = crypt($password, $salt);
echo $hash;
<?php
function hashPassword($password) {
$salt = '$2y$10$' . substr(str_replace('+', '.', base64_encode(random_bytes(22))), 0, 22);
return crypt($password, $salt);
}
$plainPassword = '123456';
$hashed = hashPassword($plainPassword);
// Assume saved to the database
file_put_contents('/var/www/m66.net/passwords.txt', $hashed . PHP_EOL);
// Verify password
$inputPassword = '123456';
$isValid = crypt($inputPassword, $hashed) === $hashed;
echo $isValid ? 'Correct password' : 'Error password';
?>
When using the crypt() function, the fundamental reason for the different lengths of the result is that the format of the "salt value" determines the encryption algorithm. To ensure encryption security and consistency:
Always explicitly pass in the correct format salt value ;
Choose modern, secure algorithms such as $2y$ or $6$ ;
Do not rely on default behavior or short salt formats .
After understanding these underlying details, you can avoid hidden security risks in password processing, and make your encryption logic more controllable and reliable.