1. Disclaimer
Cryptography is a complex topic, and I am not an expert in this field. Many universities and research institutions have long-term research in this area. In this article, I want to try to show you a way to safely store Web program passwords in a way that is easy to understand.
2. What does "Hash" mean?
"Hash converts a piece of data (small or big data) into a relatively short amount of data, such as a string or an integer. ”
This is done by relying on a one-way hash function. The so-called unidirectional means that it is difficult (or practically impossible) to reverse it back. An example of a common hash function is MD5 (), which is popular in various computer languages and systems.
Copy CodeThe code is as follows:
$data = "Hello World";
$hash = MD5 ($DATA);
Echo $hash; B10a8db164e0754105b7a99be72e3fe5
The result of using MD5 () is always a 32-character string, but it contains only 16 characters, and technically it can be represented by a 128-bit (16-byte) number of integers. You can use MD5 () to handle very long strings and data, but you always get a fixed-length hash value, which may also help you understand why this function is "unidirectional".
3. Use the hash function to store the password
A typical user registration process:
The user fills in the registration form, which contains the password field;
The program stores all user-filled information in the database;
However, the password is encrypted by the hash function before it is stored in the database.
The original password is no longer stored anywhere, or it is discarded.
User logon process:
User input user name and password;
The program encrypts the password by registering the same hash function;
The program from the database to find the user, and read the password after the hash;
The program compares the user name and password, and if so, authorizes the user.
How to choose the appropriate method to encrypt the password, we will discuss this issue later in the article.
4. Problem 1:hash Collision
Hash collision refers to the hash of two different content to get the same hash value. The likelihood of a hash collision depends on the hash algorithm used.
How is it generated?
For example, some old-fashioned programs use CRC32 () to hash passwords, which produce a 32-bit integer as the hash result, which means only 2^32 (that is, 4,294,967,296) of the possible output results.
Let's hash a password:
Copy CodeThe code is as follows:
echo crc32 (' Supersecretpassword ');
outputs:323322056
Now let's assume that a person steals a database and gets a hashed password. He may not be able to restore 323322056 to ' Supersecretpassword ', but he can find another password and can hash out the same value. This only requires a very simple program:
Copy CodeThe code is as follows:
Set_time_limit (0);
$i = 0;
while (true) {
if (CRC32 (Base64_encode ($i)) = = 323322056) {
echo Base64_encode ($i);
Exit
}
$i + +;
}
This program may take some time to run, but in the end it can return a string. We can use this string instead of ' Supersecretpassword ' and use it to successfully log in to the user account using that password.
For example, after running the above program on my computer for a few months, I got a string: ' mtixmjy5mtawng== '. Let's test it out:
Copy CodeThe code is as follows:
echo crc32 (' Supersecretpassword ');
outputs:323322056
echo crc32 (' mtixmjy5mtawng== ');
outputs:323322056
How to solve?
Now a slightly stronger home PC can run the hash function 1 billion times a second, so we need a hash function that can produce a larger range of results. For example, MD5 () is more appropriate, it can produce a 128-bit hash value, that is, there are 340,282,366,920,938,463,463,374,607,431,768,211,456 possible outputs. So it is generally impossible to do so many loops to find a hash collision. However, there are still people who find ways to do this and can look at examples in detail.
SHA1 () is a better alternative because it produces a hash value up to 160 bits.
5. Question 2: Rainbow table
Even if we solve the collision problem, it's not safe enough.
"Rainbow tables are created by calculating the commonly used words and the hash values of their combinations." ”
This table may store millions of or even 1 billion of data. Now the storage is very cheap, so you can build a very large rainbow table.
Now let's assume that a person steals a database and gets millions of hashed passwords. The thief can easily find these hash values in a rainbow table and get the original password in one place. Although not all hash values can be found in the Rainbow table, there are certain to be found.
How to solve?
We can try to add some interference to the password, such as the following example:
Copy CodeThe code is as follows:
$password = "Easypassword";
This is found in a rainbow table
Because the password contains 2 common words
Echo SHA1 ($password); 6c94d3b42518febd4ad747801d50a8972022f956
Use bunch of the random characters, and it can be longer than this
$salt = "f#@v) Hu^%hgfds";
This is not being found in any pre-built rainbow table
Echo SHA1 ($salt. $password); Cd56a16759623378628c0d9336af69b74d9d71a5
All we do here is to append a disturbance string to each password before hashing, as long as the attached string is complex enough, the value after the hash must be found in the pre-built rainbow table. But it's still not safe enough.
6. Question 3: Still a rainbow table
Note that the Rainbow table may start to build up after stealing a string of dry strings. Interference strings can also be stolen with the database, and then they can use this interference string to create a rainbow table from scratch, such as "Easypassword" hash value may exist in the ordinary rainbow table, but in the new rainbow tables, "F#@v" hu^% The hash value of Hgfdseasypassword "will also exist.
How to solve?
We can use a unique interfering string for each user. One available scenario is to use the user's ID in the database:
Copy CodeThe code is as follows:
$hash = SHA1 ($user _id. $password);
The premise of this approach is that the user's ID is a constant value (this is the case for the general application)
We can also randomly generate a unique string of interfering strings for each user, but we also need to store this string:
Copy CodeThe code is as follows:
Generates a character long random string
function Unique_salt () {
Return substr (SHA1 (Mt_rand ()), 0,22);
}
$unique _salt = Unique_salt ();
$hash = SHA1 ($unique _salt. $password);
and save the $unique _salt with the user record
// ...
This approach prevents us from being harmed by the rainbow table, because each password is interfered with using a different string. It is impractical for an attacker to create a rainbow table with the same number of passwords.
7. Problem 4:hash Speed
Most hash algorithms are designed with speed in mind because it is generally used to calculate the hash value of big data or files to verify the correctness and completeness of the data.
How is it generated?
As mentioned, now a powerful PC can operate billions of times a second, it is easy to use brute force to try each password. You might think that a password of more than 8 characters can be avoided by brute force, but let's see if this is true:
If the password can contain lowercase letters, uppercase letters and numbers, then there are 62 (26+26+10) characters Fuche;
A 8-bit password has a possible combination of 62^8, which is slightly larger than 218 trillion.
It takes only 60 hours to calculate the speed at which the hash value is computed 1 billion times a second.
For a 6-bit password, is also a very common password, only 1 minutes to crack. Passwords that require 9 to 10 bits may be more secure, but users may find it cumbersome.
How to solve?
Use a slower hash function.
"Suppose you use an algorithm that can only run 1 million times a second in the same hardware condition instead of a 1 billion-time algorithm, then the attacker may need to take 1000 times times more time to do brute force, and 60 small will become 7 years!" ”
You can implement this method yourself:
Copy CodeThe code is as follows:
function Myhash ($password, $unique _salt) {
$salt = "f#@v) Hu^%hgfds";
$hash = SHA1 ($unique _salt. $password);
Make it take the Times longer
for ($i = 0; $i < $i + +) {
$hash = SHA1 ($hash);
}
return $hash;
}
You can also use an algorithm that supports "cost parameters," such as BLOWFISH. In PHP, you can use the Crypt () function:
Copy CodeThe code is as follows:
function Myhash ($password, $unique _salt) {
The salt for Blowfish should is characters long
Return crypt ($password, ' $2a$10. $unique _salt ');
}
The second parameter of this function contains several values separated by the "$" symbol. The first value is "$2A", indicating that the Blowfish algorithm should be used. The second parameter, "$ $" here is the cost parameter, which is the base of 2 logarithm, indicating the number of times the loop iteration is computed (2^10 = 1024), the value can be from 04 to 31.
As an example:
Copy CodeThe code is as follows:
function Myhash ($password, $unique _salt) {
Return crypt ($password, ' $2a$10. $unique _salt ');
}
function Unique_salt () {
Return substr (SHA1 (Mt_rand ()), 0,22);
}
$password = "Verysecret";
Echo Myhash ($password, Unique_salt ());
Result: $2A$10$DFDA807D832B094184FAEU1ELWHTR2XHTUVS3R9J1NFRGBCUDCCZC
The hash value of the result includes the $2A algorithm, the cost parameter, and a 22-bit interference string that we use. The rest is the calculated hash value, and we'll run a test program:
Copy CodeThe code is as follows:
Assume this is pulled from the database
$hash = ' $2A$10$DFDA807D832B094184FAEU1ELWHTR2XHTUVS3R9J1NFRGBCUDCCZC ';
Assume this was the password the user entered to log back in
$password = "Verysecret";
if (Check_password ($hash, $password)) {
echo "Access granted!";
} else {
echo "Access denied!";
}
function Check_password ($hash, $password) {
First characters include algorithm, cost and salt
Let's call it $full _salt
$full _salt = substr ($hash, 0, 29);
Run the hash function on $password
$new _hash = Crypt ($password, $full _salt);
Returns TRUE or False
return ($hash = = $new _hash);
}
Run it and we'll see "Access granted!"
8. Integrate them
Based on the above discussion, we have written a tool class:
Copy CodeThe code is as follows:
Class Passhash {
Blowfish
private static $algo = ' $2a ';
Cost parameter
private static $cost = ' $ $ ';
Mainly for internal use
public static function Unique_salt () {
Return substr (SHA1 (Mt_rand ()), 0,22);
}
This'll be used to generate a hash
public static function hash ($password) {
Return Crypt ($password,
Self:: $algo.
Self:: $cost.
'$'. Self::unique_salt ());
}
This'll be used to compare a password against a hash
public static function Check_password ($hash, $password) {
$full _salt = substr ($hash, 0, 29);
$new _hash = Crypt ($password, $full _salt);
return ($hash = = $new _hash);
}
}
Here's how to use it when registering:
Copy CodeThe code is as follows:
Include the class
Require ("passhash.php");
Read all form input from $_post
// ...
Do your regular form validation stuff
// ...
Hash the password
$pass _hash = passhash::hash ($_post[' password ');
Store all user info in the DB, excluding $_post[' password ']
Store $pass _hash instead
// ...
Here's how to use it at logon:
Copy CodeThe code is as follows:
Include the class
Require ("passhash.php");
Read all form input from $_post
// ...
Fetch the user record based on $_post[' username ' or similar
// ...
Check the password the user tried to login with
if (Passhash::check_password ($user [' Pass_hash '], $_post[' password ']) {
Grant access
// ...
} else {
Deny Access
// ...
}
9. Whether encryption is available
Not all systems support the Blowfish encryption algorithm, although it is now very common, you can use the following code to check whether your system supports:
Copy CodeThe code is as follows:
if (crypt_blowfish = = 1) {
echo "Yes";
} else {
echo "No";
}
But for php5.3, you don't have to worry about it, because it's built into the implementation of this algorithm.
Conclusion
Passwords that are encrypted in this way are safe enough for most Web applications. But don't forget that you can still allow users to use more secure passwords, such as requiring a minimum number of digits, mixing passwords with letters, numbers, and special characters.
http://www.bkjia.com/PHPjc/322921.html www.bkjia.com true http://www.bkjia.com/PHPjc/322921.html techarticle 1. It is a complex topic to declare cryptography, and I am not an expert in this field. Many universities and research institutions have long-term research in this area. In this article, I want to try to use ...