Updated PHP: Password Security in modern PHP

Source: Internet
Author: User
Tags anthony ferrara md5 hash rehash

Updated PHP: Password Security in modern PHP

From the very beginning, PHP was a programming language born to build websites. This idea is rooted in the depth of PHP's core than any other programming language, which may be one reason why PHP has become so popular in the Web application building field. However, when PHP was first designed in the 1990s S, the term Web application did not even exist. Therefore, password protection is not one of the functions that PHP creators need to design resources. After all, you don't have to worry about the password when you just use PHP to implant a Website access counter or modify a date stamp on the webpage.

But 20 years later, people can hardly imagine creating a Web application that does not involve password-protected user accounts. The most important task for PHP programmers is to use the latest and safest method to protect the account password. To this end, PHP 5.5 adds a new password hash library created by Anthony Ferrara (@ ircmaxell. This library provides some functions that you can use to process one-way password encryption using the best practices currently. Other features are designed to meet future security requirements, so that you can always take the lead when your computer and attackers are getting better. This article will introduce the functions of the library and how to use them most effectively.

About this series

As an active open-source project, PHP is constantly improving and currently supports many Web sites. PHP was a template language in the early days, and PHP has undergone significant changes since then. If you have not used or evaluated PHP Technology for many years, you may not recognize some of the current PHP projects. This series of articles will show you the latest PHP features and how to use today's PHP to build a modern and secure website.

Importance of secure hashing

"Treat your password like a toothbrush. Do not allow anyone else to use it and change a new password every six months. "

Clifford Stoll

The following suggestions may be self-explanatory (at least I hope): Do not store users' passwords as plain text. Always use Hash Algorithms and other one-way encryption algorithms to store the encrypted version of the password, so that no one who can access your account database can find your user password. This warning is not only applicable to protecting users from harming your website by obtaining database access. You also need to defend against malicious attempts in your organization.

What is hash?

The hash algorithm obtains a string of any length and creates a hash value in the same way: a fixed-length string representation. Each time you input the same original string, you will receive the same hash value. This is a one-way process from which you cannot obtain the original string.

This demand becomes increasingly urgent, because unfortunately many users use the same password for multiple websites. If someone can access the email address and original password of a user, he may be able to access the account of the user on another website.

Cracking speed

All hash values are not created in the same way. Then you can use various algorithms to create hash values. Two algorithms used in the past are MD5 and SHA-1. Today, powerful computers can easily crack these two algorithms. For example, existing software can crack the MD5 hash value at a rate of 3.65 billion computations per second on a single GPU and crack the hash value of SHA-1 at a rate of 1.36 billion computations per second. Based on the password complexity and length, a hash value can be cracked in less than half an hour.

Therefore, it is important to use a more complex hash algorithm in computing. Not only do you want a longer hash value (this will reduce the chance of hash collision, that is, reduce the chance of two phrases generating the same hash value ), you also want to take as long as possible to generate the hash value. Why? For your own Web application, you only need to wait once to generate a password hash value each time you log on. If the waiting time lasts for 1 second (or even two seconds), the user will not care about it or even notice it. However, by slowing down the number of attempts to crack from 3.6 billion per second to 1 per second, the difficulty of any attempt will increase exponentially.

Rainbow table

You also need to defend against rainbow tables. Rainbow tables (for example, MD5 that you can access on md5cracker.org) are reverse lookup tables with hash values. The creator of the table computes all common words, phrases, modified words in advance, and even the MD5 Hash Value of random strings. A person who can access a hash value can enter it in the search table and find the password used to generate it, thus effectively reversing this one-way process. The relatively low processing cost of cracking the MD5 hash value makes it possible to create a rainbow table.

It takes a long time to generate a rainbow table for a complex computing algorithm. But it is still possible, and the Creator only needs to make one-time effort. An appropriate solution is to add a SALT to your hash value. In this context, SALT refers to any phrase that is first added to your password before creating a hash value. By using SALT, you will eventually (in reality) defeat the rainbow table. Others need to generate a rainbow table specific to your application, and then crack multiple passwords to find out what SALT is-this is a complicated and costly scenario.

Improve past PHP password practices

Now let's take a look at listing 1, which is an example of a valid Password practice in PHP a few years ago.

Listing 1. Password security practices that are generally considered valid in PHP
 

<?php// Create a password class to handle management of this:class Password {const SALT = 'MyVoiceIsMyPassport';public static function hash($password) {return hash('sha512', self::SALT . $password);}public static function verify($password, $hash) {return ($hash == self::hash($password));}}// Hash the password:$hash = Password::hash('correct horse battery staple');// Check against an entered password (This example will fail to verify)if (Password::verify('Tr0ub4dor&3', $hash)) {echo 'Correct Password!n';} else {echo "Incorrect login attempt!n";}

Examples such as listing 1 are considered best practices on the Web. For a long time, this method was the best practice-obviously better than using MD5, and much better than storing passwords as plain text. Listing 1 uses a much more complex SHA-512 algorithm, and it forces all passwords to be added to SALT to defeat the predefined rainbow table. However, this method still has some problems.

Use random SALT

Listing 1 uses a SALT, but each password uses the same SALT. Therefore, once a password is cracked (or worse, SALT is discovered by accessing the code library ), then, you can add the SALT to each table entry to create a custom rainbow table. The solution to win the rainbow table is to use a random SALT for each password when creating the password, and store the SALT and password together to get the password.

Further increase costs

Listing 1 also uses a SHA-512 (a much more complex algorithm with PHP) without MD5 or SHA-1. However, even the SHA-512 hash value can also calculate 46 million rate cracking per second. Although it is slower than the MD5 or SHA1 cracking rate, this rate is still insufficient for sufficient security. The solution to this problem is to use more complex computing algorithms and use these algorithms multiple times. For example, running a SHA-512 100 times consecutively for each password can significantly slow down any attack attempt.

The good news is that you do not need to use your own code to implement this solution. The new password hash computing library in PHP 5.5 solves this problem.

Introduction to password_hash ()

This password hash extension allows you to create complex and secure password hash values for computing, including generating and processing random salts behind the scenes. In the simplest use case of calling password_hash () for the password you want to calculate the hash value, this extension will handle everything for you. You also need to provide the second parameter: the hash algorithm you want to extend. You have two options, but currently, specifying the PASSWORD_DEFAULT constant is the best option (I will explain the reason later ):

<?php$hash = password_hash('correct horse battery staple', PASSWORD_DEFAULT);
 
Specify cost parameters

You can also provide the third parameter, which is an array of options for changing the hash value generation method. You can specify SALT here, but it is best not to specify SALT and allow random SALT generation for you. More importantly, you can specify a cost value in this array. This value (the default value is 10) determines how complex the algorithm should be and how long it will take to generate a hash value. (This value is considered to be the number of times the algorithm itself is re-run to reduce computation .) If you want a safer password and your computer can handle it, you can call it like this:

<?php$hash = password_hash('correct horse battery staple', PASSWORD_DEFAULT, ['cost' => 14]);

Using my own MacBook Pro as a test environment, it takes about 0.085 seconds to generate a password_hash with a cost of 10 (default. Increase the cost to 14 and change the time To 1.394 seconds for each calculation.

Verify the generated Password

Because the passwords in the previous two examples are generated using a random SALT process, I cannot directly know the related SALT. Therefore, if I try to run password_hash () again and compare the string to verify the password, the result will not match. Each time you call this function, a new SALT is generated and the returned hash value is different. Therefore, this extension provides the second function password_verify (), which handles the verification process for you. You call password_verify () to pass in the password provided by the user and the stored hash value. If the password is correct, this function returns a Boolean value TRUE; otherwise, FALSE:
 

<?phpif (password_verify($password, $hash)) {    // Correct Password}
 

Now I can refactor the class in Listing 1 and use the built-in password hash extension, as shown in Listing 2.

Listing 2. refactoring the Password class in Listing 1

<?phpclass Password {    public static function hash($password) {        return password_hash($password, PASSWORD_DEFAULT, ['cost' => 14]);    }    public static function verify($password, $hash) {        return password_verify($password, $hash);    }}
Handling ever-changing security needs

With the new password hash extension, you can upgrade your code library to today's security standard level. But just a few years ago, experts once said that SHA-1 is a best practice solution. So, if it is not the best practice, what will happen when the password encryption needs to be stronger? Fortunately, the new extension has a built-in function that considers this possibility.

You can use the password_needs_rehash () function (behind the scenes) to check whether the Stored Password Matches Your specified security requirements. If they do not match, it may be because you have added the cost parameter or a new PHP version is changed to a different hash algorithm behind the scenes. Because of this, PASSWORD_DEFAULT should be your preferred algorithm; this option will always make your software use the current best practice version.

The use of this function is more complex, but not too complex. When checking a user's password (for example, when a user attempts to log on), you need to execute an additional task: Call password_needs_rehash (), which accepts parameters similar to password_hash. The password_needs_rehash () function checks the provided password hash value based on the security settings of the new request. If the password hash value does not match these settings, this function will report this fact to you.

Some programmers are hard to understand here, because the password_needs_rehash () function does everything to let you know whether the password needs to be re-computed. Whether to generate a new hash value for the password and save it depends on you, because the password extension does not know how to store the password.

In listing 3, I provide a complete simulated User class. In this class, by using the tool I discussed, you can safely process the User password, it also supports changing security requirements in the future.

Listing 3. The simulated User class shows the full use of password Extension

<?phpclass User {// Store password options so that rehash & hash can share them:const HASH = PASSWORD_DEFAULT;const COST = 14;// Internal data storage about the user:public $data;// Mock constructor:public function __construct() {// Read data from the database, storing it into $data such as://  $data->passwordHash  and  $data->username$this->data = new stdClass();$this->data->passwordHash = 'dbd014125a4bad51db85f27279f1040a';}// Mock save functionalitypublic function save() {// Store the data from $data back into the database}// Allow for changing a new password:public function setPassword($password) {$this->data->passwordHash = password_hash($password, self::HASH, ['cost' => self::COST]);}// Logic for logging a user in:public function login($password) {// First see if they gave the right password:echo "Login: ", $this->data->passwordHash, "\n";if (password_verify($password, $this->data->passwordHash)) {// Success - Now see if their password needs rehashedif (password_needs_rehash($this->data->passwordHash, self::HASH, ['cost' => self::COST])) {// We need to rehash the password, and save it.  Just call setPassword$this->setPassword($password);$this->save();}return true; // Or do what you need to mark the user as logged in.}return false;}}
Conclusion

Now you know how the new password hash library is used by PHP and how it continues to help your users defend against security breaches. In the next PHP revival, I will turn to the evolution of the PHP language itself to the ecosystem and tools that have begun to evolve around it: first, Composer, A popular PHP dependency manager for the entire community.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.