How to encrypt hash password in PHP?

In this tutorial we will show you the solution of how to encrypt and decrypt password in PHP, encryption is nothing but achieving the encryption code with the help of some algorithms which are sometimes called hashing algorithms and they usually work with by taking a string then it will creating a unique format string.

The conversion of encrypted data into its original form is called Decryption.

For encrypt a password string we used hash algorithm method available in php.

Step By Step Guide On How To Encrypt And Decrypt Password In PHP :-

Here we takes password string in a variable then using password_hash() method for our password string change into encrypted type of string.

Password_hash() creates a new password hash using a strong one-way hashing algorithm with constant PASSWORD_DEFAULT it supports algorithm.

Method of password_verify() can verify that given hash matches the given password.

By this method we verified our password with hash type string and it returns Boolean value if its true our password correct otherwise it is not valid password.

<?php
$pwsd = "prawin@123";
$hash = password_hash($pwsd,PASSWORD_DEFAULT);
$res=password_verify($pwsd,$hash);
if($res){
    echo 'original password: '.$pwsd.'<br>';
    echo 'encrypt password: '.$hash.'<br>';
    echo 'Password Verified Successfully';
}
else{
    echo 'Incorrect Password';
}
?>
  1. A php script can be placed anywhere in the document. A php script starts with <?php and end with ?>.
  2. The default file extension for php files is “.php” and php statements end with ‘;’ semicolon.
  3. When declaring a variable in php we must use ‘$’ symbol before the variable name. Here we stored our password to variable ‘$pwsd’ and the password is ‘prawin@123’.
  4. Then using password_hash() method we transformed our password to hash type and the result string stored to variable ‘$hash’. Then don’t forget to add constant parameter of ‘PASSWORD_DEFAULT’ otherwise it throws error.
  5. Now we have to pass parameter of our original password and hashing password to the password_verify() method and it checks two variable values are same string then it returns Booleans value. The result of Boolean value stored to variable ‘$res’.
  6. If() condition checks whether Boolean value returned true or not. If result true means changed hash password and original form of password are same. If its false it throws message of ‘incorrect password’ to the webpage.
  7. If our passwords are same then we prints original password, encrypted password and result string message of ‘Password verified successfully’ will display on browser webpage.
  8. In php for display any string or value on webpage we need to use ‘echo’ or ‘print’. Here we used echo for print results on browser.

Conclusion :-

In conclusion we are able to know how to encrypt and decrypt password using php.

When work with php we need to create and process php files at server location and then we need to start the server before execute the program.

When we executing this program on browser it checks our user defined password and hash type converted passwords are same then result will display on webpage browser.

I hope this tutorial on how to encrypt and decrypt password in PHP helps you and the steps and method mentioned above are easy to follow and implement.

A few years ago I attended Laracon EU where Marcus Bointon gave a great talk on Crypto in PHP 7.2. I left the talk having a much greater appreciation for how vastly complicated cryptography is, but also for how PHP is making encryption more accessible thanks to the introduction of Sodium. Data encryption in PHP has been vital to my work on SpinupWP, a cloud-based server control panel with root access to thousands of servers and sites, and I thought it would be useful to share what I’ve learned since then. Buckle up, because this could be a bumpy ride!

Types of Encryption

There are a range of different encryption methods in use today, the most common being hashing, secret key encryption, and envelope encryption. In addition, each encryption method has multiple algorithms or ciphers to choose from (each with its own strengths and weaknesses). In this article, we’re going to look at implementing all three encryption methods.

Hashing

A hashing algorithm takes an input value and transforms it to a fixed-length output known as a “message digest”, “hash value” or simply a “hash”. Hashing is one way only, which means that the only way to validate a hashed output is to pass the original value to the hashing algorithm and compare the results. This makes hashing perfect for storing user passwords.

It’s worth noting that hashing isn’t a bulletproof solution and not all hashing algorithms are equal. Consider MD5 and SHA1 which are fast and efficient, making them ideal for checksumming and file verification. However, their speed makes them unsuitable for hashing a user’s password.

With today’s computational power of modern CPUs/GPUs and cloud computing, a hashed password can be cracked by brute force in a matter of minutes. It’s fairly trivial to quickly generate billions of MD5 hashes from random words until a match is found, thereby revealing the original plaintext password. Instead, intentionally slower hashing algorithms such as bcrypt or Argon2 should be used.

While a hashed password generated by any algorithm will certainly obscure the original data and slow down any would-be attacker, we as developers should strive to use the strongest algorithm available. Luckily, PHP makes this easy thanks to

[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
4.

$hash = password_hash($password, PASSWORD_DEFAULT);

The

[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
4 function not only uses a secure one-way hashing algorithm, but it automatically handles and prevents time based side-channel attacks. The function accepts a
[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
6 to be encrypted, and a
[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
7 hashing algorithm. As of PHP 5.5, bcrypt (
[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
8), which is based on the Blowfish cipher, will be used as the default hashing algorithm. Later versions of PHP introduced the Argon2 (PHP 7.2) and Argon2id (PHP 7.3) algorithms, but bcrypt is still the default. In fact, besides improvements to the
[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
4 function, the available options are considered so secure that no new algorithms have been introduced to the language for either PHP 8.0 or PHP 8.1.

It is possible to use Argon2 or Argon2id, if your version of PHP has been compiled with Argon2 support, by passing either the

if (password_verify($password, $hash)) {
    echo "Let me in, I'm genuine!";
}
0 or
if (password_verify($password, $hash)) {
    echo "Let me in, I'm genuine!";
}
1 constant as the
[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
7 argument of the
[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
4 function. To check which algorithms are supported on your web host, you can launch the PHP interactive mode from the server command line, and run the
if (password_verify($password, $hash)) {
    echo "Let me in, I'm genuine!";
}
4 function. Below is an example of the output of that command on a standard SpinupWP server, where all three options are available.

[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >

Verifying a user’s password is also a trivial process thanks to the

if (password_verify($password, $hash)) {
    echo "Let me in, I'm genuine!";
}
5 function. Simply pass the plaintext password supplied by the user and compare it to the stored hash, like so:

if (password_verify($password, $hash)) {
    echo "Let me in, I'm genuine!";
}

Notice how the password verification is performed in PHP. If you’re storing a user’s credentials in a database you may be inclined to hash the password entered at login and then perform a database SQL query, like so:

SELECT * FROM users
WHERE username = 'Ashley'
AND password = 'password_hash'
LIMIT 1;

This approach is susceptible to side-channel attacks and should be avoided. Instead, return the user and then check the password hash in PHP.

SELECT username, password FROM users
WHERE username = 'Ashley'
LIMIT 1;
if (password_verify($user->password, $hash)) {
    echo "Let me in, I'm genuine!";
}

While hashing is great to encrypt passwords, it doesn’t work for arbitrary data that our application needs to access without user intervention. Let’s consider a billing application, which encrypts a user’s credit card information, typically saved from an HTML form. (Given the related legal and PCI compliance requirements, we don’t recommend building your own billing application, rather use something like Stripe. We’re just using this as an example). Each month our application needs to bill the user for their previous month’s usage. Hashing the credit card data wouldn’t work because it requires that our application be able to decrypt the hashed data which, as we pointed out earlier, is not possible with hashing.

Secret key encryption to the rescue!

Secret Key Encryption

Secret key encryption (or symmetric encryption as it’s also known) uses a single key to both encrypt and decrypt data. In the past PHP relied on mcrypt and openssl for secret key encryption. PHP 7.2 introduced Sodium, which is more modern and widely considered more secure. If you’re running an older version of PHP you can install Sodium via The PHP Extension Community Library aka PECL.

In order to encrypt a value, first you’ll need an encryption key, which can be generated using the

if (password_verify($password, $hash)) {
    echo "Let me in, I'm genuine!";
}
6 function.

$key = sodium_crypto_secretbox_keygen();

You can also use the

if (password_verify($password, $hash)) {
    echo "Let me in, I'm genuine!";
}
7 function with the
if (password_verify($password, $hash)) {
    echo "Let me in, I'm genuine!";
}
8 integer constant for the key length, but using
if (password_verify($password, $hash)) {
    echo "Let me in, I'm genuine!";
}
6 ensures that the key length is always correct (i.e. not too short), and it’s easier.

$key = random_bytes( SODIUM_CRYPTO_SECRETBOX_KEYBYTES );

Either way, you’ll usually only do this once and store the result as an environment variable. Remember that this key must be kept secret at all costs. If the key is ever compromised, so is any data encrypted by using it.

To encrypt the original value, pass it to the

SELECT * FROM users
WHERE username = 'Ashley'
AND password = 'password_hash'
LIMIT 1;
0 function with the
SELECT * FROM users
WHERE username = 'Ashley'
AND password = 'password_hash'
LIMIT 1;
1 and a generated
SELECT * FROM users
WHERE username = 'Ashley'
AND password = 'password_hash'
LIMIT 1;
2. To create the nonce use the
if (password_verify($password, $hash)) {
    echo "Let me in, I'm genuine!";
}
7 function, with the
SELECT * FROM users
WHERE username = 'Ashley'
AND password = 'password_hash'
LIMIT 1;
4 integer constant for the nonce length, because the same nonce should never be reused.

$nonce = random_bytes( SODIUM_CRYPTO_SECRETBOX_NONCEBYTES );
$encrypted_result = sodium_crypto_secretbox( 'This is a secret!', $nonce, $key );

This presents a problem because we need the nonce to decrypt the value later. Luckily, nonces don’t have to be kept secret so we can prepend it to our

SELECT * FROM users
WHERE username = 'Ashley'
AND password = 'password_hash'
LIMIT 1;
5 then
SELECT * FROM users
WHERE username = 'Ashley'
AND password = 'password_hash'
LIMIT 1;
6 the value before saving it to the database.

$encoded = base64_encode( $nonce . $encrypted_result );

This will create a base64 encoded string of 76 characters in length.

When it comes to decrypting the value, do the opposite, starting with decoding the base64 encoded string.

[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
0

Because we know the length of the nonce (

SELECT * FROM users
WHERE username = 'Ashley'
AND password = 'password_hash'
LIMIT 1;
4) we can extract it using
SELECT * FROM users
WHERE username = 'Ashley'
AND password = 'password_hash'
LIMIT 1;
8 before decrypting the value.

[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
1

That’s all there is to secret key encryption in PHP, thanks to Sodium!

Envelope Encryption

While the approach outlined above is certainly a step in the right direction, it still leaves our data vulnerable if the secret key is compromised. Let’s consider a malicious user that gains access to the server that hosts our application. They won’t hang around on the server to decrypt any sensitive data. Rather, they’ll make a copy of the data and all the relevant files onto their own infrastructure and work to discover our secret key which we used to encrypt the data. This leaves our data completely exposed.

The simple solution is to not store our secret key in the same location as the encrypted data, but this presents a problem. How do we encrypt and decrypt on demand? Enter Key Management Services (KMS) which allow you to securely host keys on their platform. Companies that offer cloud infrastructure like AWS and Google each have their own offerings. As a quick tutorial, we’ll be focusing on Google’s Cloud KMS.

Google Cloud KMS

Cloud KMS is a service provided by Google for securely hosting cryptographic keys. It provides a variety of useful features around key storage, including automatic key rotation and delayed key destruction. However, we’re primarily concerned with storing our secret key separately from our application.

To make things more secure we’re going to use a technique known as envelope encryption. Essentially, envelope encryption involves encrypting keys with another key. We do this for two reasons:

  1. Cloud KMS has a size limit of 64 KiB on the data that can be encrypted and decrypted. Therefore, it may not be possible to send all of the data in one fell swoop.
  2. More importantly we don’t want to send our sensitive plaintext data to a third party, regardless of how trustworthy they may seem.

Instead of sending our plaintext data to Cloud KMS, we’re going to generate a unique encryption key every time we write sensitive data to the database. This key is known as a data encryption key (DEK), which will be used to encrypt our data. The DEK is then sent to Cloud KMS to be encrypted, which returns a key-encryption key (known as a KEK). Finally, the KEK is stored side-by-side in the database next to the encrypted data and the DEK is destroyed. The process looks like so:

  1. Generate a data encryption key (DEK)
  2. Encrypt the data using secret key encryption
  3. Send the unique encryption key (DEK) to Cloud KMS for encryption, which returns the KEK
  4. Store the encrypted data and encrypted key (KEK) side-by-side
  5. Destroy the generated key (DEK)

When decrypting data the process is reversed:

  1. Retrieve the encrypted data and encrypted key (KEK) from the database
  2. Send the KEK to Cloud KMS for decryption, which returns the DEK
  3. Use the DEK to decrypt our encrypted data
  4. Destroy the DEK

Cloud KMS and PHP

Like most Google Cloud services, there is a which we can use in our PHP applications The Cloud KMS documentation is quite extensive, but I recommend starting with the Quickstart guide and the Authentication guide, which takes you through all the requirements.

Cloud KMS Requirements

First, you need to create a Google Cloud account and create a new Google Cloud project. Then you enable the Cloud KMS API and install and initialize the Cloud SDK. This step allows to you run the

SELECT * FROM users
WHERE username = 'Ashley'
AND password = 'password_hash'
LIMIT 1;
9 command-line tool, which you use to create your Cloud KMS key which is part of a Cloud KMS keyring, and exists in a Cloud KMS location . Finally, you need to create a , grant permissions to the service account based on the project and then store the service account credentials in a local credentials file.

While this all seems like a lot of work to set up, the Google Cloud docs are really helpful in guiding you through the steps.

Cloud KMS PHP Implementation

With this in mind, I’ve created a very simple helper class for performing envelope encryption, which uses the Google Cloud KMS SDK. I wouldn’t consider this production-ready code, as it could use some better error handling, but it gives you a place to start. This helper class makes use of the most recent version of the Google Cloud KMS SDK, which is currently at version 1.12.

[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
2

You’ll notice that the actual encryption and decryption methods are almost identical to the secret key implementation introduced above. The difference however is that we’re now using multiple encryption keys. Let’s see the helper class in action.

KeyManager Usage

To make use of this helper class, you’ll need to start a new project with Composer support, install the

SELECT username, password FROM users
WHERE username = 'Ashley'
LIMIT 1;
0 package, and make sure to require the Composer autoloader. You will then need to set up the
SELECT username, password FROM users
WHERE username = 'Ashley'
LIMIT 1;
1 constant, using the credentials file you .

Finally, you need to set up the

SELECT username, password FROM users
WHERE username = 'Ashley'
LIMIT 1;
2,
SELECT username, password FROM users
WHERE username = 'Ashley'
LIMIT 1;
3,
SELECT username, password FROM users
WHERE username = 'Ashley'
LIMIT 1;
4 and
SELECT username, password FROM users
WHERE username = 'Ashley'
LIMIT 1;
5 variables, which you match the values when you . You can then create a new instance of the KeyManager class, and use it for encryption and decryption.

[email protected]:~$ php -a
Interactive mode enabled

php > print_r(password_algos());
Array
(
    [0] => 2y
    [1] => argon2i
    [2] => argon2id
)
php >
3

If you’d like to see this code in action, I’ve created a GitHub repository which sets everything up for this simple implementation.

If an attacker compromised our system, they would still be able to gain access to our Cloud KMS API implementation, and use that to decrypt any encrypted data they may have copied. If that’s the case, you may be wondering how envelope encryption is any more secure than regular secret key encryption?

The key difference (pun intended) is that the KMS API access can be revoked, thus preventing an attacker from decrypting any data they’ve made off with. With regular secret key encryption where a single local key is compromised, you don’t have that luxury. The attacker has all the time in the world to decrypt your sensitive data, using the local key. Envelope encryption isn’t a flawless solution, but it certainly lowers your risk of a data breach.

WordPress and Sensitive Data

A common question I see in WordPress developer circles is; “How should I encrypt sensitive data like API keys in my plugin or custom theme?”. Usually, these are plugins or themes that need to be able to access some third-party API (eg MailChimp or AWS services), that authenticates using an API access key and sometimes an access key secret. One such example is our own WP Offload Media, which needs access credentials to your offsite storage provider.

Generally, there are two main options available for implementing these access details.

  1. Store them as plain text with an identifier (usually as a PHP constant) in a credentials file that is not publicly accessible, and require that file from the wp-config.php file.
  2. Encrypt them, store them in the database, and then decrypt them when you need to make an API call, using one of the encryption methods we’ve discussed above.

The reality is that, whatever you do, if your code can read the secret, so can any motivated attacker. As we’ve discussed, even envelope encryption is not completely secure, and as a plugin developer, you have less control over the encryption methods available to site owners.

In my opinion, it’s better to educate your users on security. Make sure you have documentation in place that they can use to disable third-party API access at the source if a breach ever happens. Make sure that your documentation covers aspects like how to limit read or write capabilities to third-party services. For example, we recently updated our SpinupWP backup storage provider documentation with details on how to .

If you work with site owners, teach them to keep WordPress core, plugins, and themes up to date, as well as their PHP version, to prevent vulnerabilities; and to use secure passwords, password managers, and two-factor authentication where possible. If they need to access servers, ensure they are using SSH key authentication and SFTP to manage files.

It’s all well and good changing the locks to your house after someone steals your keys, but it’s better to never have your keys stolen in the first place.

Wrapping Up

Data security and encryption are vast subjects and I’ve covered only a handful of ways to protect sensitive data using PHP. Ultimately though, whatever encryption you implement is still vulnerable to attack, the levels of risk just vary. Knowing the different types does mean you can choose to implement them at different levels of your application code, depending on the sensitivity of your data.

What precautions do you take? Are you using hashing, secret key encryption, or envelope encryption? Let us know in the comments below.

This entry was posted in WP Migrate DB Pro, Plugin Development and tagged Development, Security, PHP, Encryption, Hashing, Password.

About the Author

Ashley Rich

Ashley is a Laravel and Vue.js developer with a keen interest in tooling for WordPress hosting, server performance, and security. Before joining Delicious Brains, Ashley served in the Royal Air Force as an ICT Technician.

@A5hleyRich ashleyrich.com

  • Nick says:

    I am working on a side project right now and this is what I had planned to research this coming weekend. You just saved me a lot of work, so thanks a bunch for sharing!

  • Jeff Cleverley says:

    Great article, much appreciated.

  • Lakshmeepathi says:

    Fantastic – I love finding articles that go to the depth required and something that tells my brain ‘it’s possible using these methods, and here you can dig deeper if required in the future’. Thanks!

  • luroch says:

    This is really helpful!

  • Syed Umair Ali says:

    I just go through the article I found it very useful. You can find some related content below that will also be helpful for all. I just go through the article I found it very useful. https://fullstackuser.com/qs/29555/is-comparing-strings-in-mysql-vulnerable-to-timing-attacks

  • Tomas Davis says:

    You need to know more about the field of cryptocurrencies. In any case, the investment depends only on you, and remember that the profitability of trading largely depends on the broker you choose. Therefore, it will be useful if you read the article from this site https://tabtrader.com/academy/articles/what-is-dao where you can also read some reviews about a bitcoin trader and understand that this is a real way to make money. Perhaps you should check out this service in action.

    Can you encrypt a hashed password?

    One of several peppering strategies is to hash the passwords as usual (using a password hashing algorithm) and then HMAC or encrypt the hashes with a symmetrical encryption key before storing the password hash in the database, with the key acting as the pepper.

    How to apply password hashing in PHP?

    Let's say we have the following input: $password = $_POST['password']; You first hash the password by doing this: $hashed_password = password_hash($password, PASSWORD_DEFAULT);

    How to show encrypted password in PHP?

    Decryption of the password: To decrypt a password hash and retrieve the original string, we use the password_verify() function.

    Is password_hash PHP secure?

    The result hash from password_hash() is secure because: It uses a strong hashing algorithm. It adds a random salt to prevent rainbow tables and dictionary attacks.