Security Analysis of Hash Cryptography in PHP

  • 2021-12-13 16:25:34
  • OfStack

This paper illustrates the security of hash cipher in PHP. Share it for your reference, as follows:

php's basic hash function is no longer safe?

There is a special section in the php manual to introduce this problem
http://php.net/manual/zh/faq.passwords.php

In many applications, the user's password is directly stored in the database through md5 encryption, including the web management interface of the open source project zabbix that I recently used.


$password = "1234";
$hash = md5($password);
echo $res;

php commonly used hash functions are md5 and sha1. After this hash, 1 is irreversible, but it can be reproduced, that is to say, the same plaintext, the result after hash is 1. For 1 simple plaintext, it can be traversed and then compared with encrypted ciphertext to get plaintext.

There is a circulating "Rainbow Table" on the Internet, which is a very large database traversed, which stores the contrast relationship between plaintext and ciphertext, and can get the plaintext corresponding to ciphertext through query.

http://www.cmd5.com/

This website provides this kind of server, which means that if hackers "take off their pants" successfully, they will still have a great possibility to decrypt and get plaintext after getting the ciphertext of the user's password.

Will plaintext "1234", through md5 after encryption, in the above site is very easy to decrypt out.

Increase the difficulty of cracking by "adding salt"

"Salt" means to add some data to the plaintext, and then encrypt it. In this way, even if the plaintext (the user's password) is relatively simple, it becomes more complicated after adding salt, and then encrypting it, which increases the difficulty for hackers to decrypt the plaintext.


$password = "1234";
$salt = "s@jn#.sK_jF3;gg*&";
$hash = md5($password.$salt);
echo $res;

The same plaintext "1234", after adding a complicated "salt", is encrypted again, and the difficulty of decryption increases a lot. The decryption website above cannot be decrypted (at least it can't be decrypted without paying, hahaha).

We use the same salt for all passwords above, which is not very safe. For example, if the passwords of Zhang 3 and Li 4 are the same, the ciphertext stored in the database is also the same, which undoubtedly makes it easier for hackers to crack.

The more commonly used way is to encrypt different users with different salts. In the process of user registration, the salt corresponding to users is generated and then stored; When the user logs in, salt is taken out for encryption operation, and the salt corresponds to the user id11.

You can use the php random_bytes To produce a salt of a fixed length


$password = "1234";
$salt = bin2hex(random_bytes(32));
$hash = md5($password.$salt);
echo $res;

About the storage of salt

Salt and ciphertext can be stored in the user information table of the database. The advantage is that the password can be taken out while the database queries, and the encryption comparison operation can be carried out, which can be done after one data query. The disadvantage is poor security. If the hacker "takes off his pants" successfully, the corresponding salt can be obtained while the ciphertext is obtained.

A better solution is to store salt and ciphertext separately. For example, ciphertext is stored in mysql database, Salt is stored in redis server, so even if hackers "take off their pants" and get the ciphertext in the database, they need to take another step to get the corresponding salt before they can crack it, which is better in security. However, it needs to be queried twice, that is, the corresponding salt needs to be taken out from redis every time they log in, which sacrifices the performance of one order and improves security.

More secure solutions in php 5.5

It is true to say that php is a language specially designed for web. It should be that php developers have also noticed the problem of password preservation.

Since php5.5, password_hashing module has been designed for hashing and verifying passwords.

http://php.net/manual/zh/book.password.php

Using password_hash for hashing, the algorithm used, cost and salt value are returned as a part of hashing, so there is no need to save the value of salt separately, because it will generate salt by itself every time, so the advantage is that "the result of encryption is not 1", but you can rest assured that the encryption result contains salt information, and password_verify can be correctly analyzed.


$password = "1234";
$hash = password_hash($password,PASSWORD_DEFAULT);

The result after hash, you can only use the password_verify Therefore, the function of verifying password can only be realized by php language.


$password = "1234";
$hash = password_hash($password,PASSWORD_DEFAULT);
$res = password_verify($password,$hash);  // The verification result is true

Advantage and disadvantage analysis

The advantage is that the security is very high, even if the pants are taken off, it is difficult to decrypt the ciphertext, because the same ciphertext, the encryption result is not 1, so it is impossible to hit the library!

password_hash is actually the encapsulation of crypt and salt. crypt encryption is more complex than ordinary md5 and sha1, so it takes more time. This can be regarded as a disadvantage, which may have a performance impact on sites with a large number of users and frequent login operations. Another point is that the versatility is not strong, because this way is only applicable to php language, and other languages have no way to operate ciphertext.

Just now, I tested the performance of password_hash, and I was scared to death. .

md5.php


<?php
$stime = microtime(true);
$password = "root123@";
$salt = "83979fklsdfgklu9023*&*(&()#&*(Y*(@&*<:L:%:::>><??11!!^%^$%$%^<>YUIYUIhjkdshfJKH#J#HJK#HKl;dskfs";
for($i=0;$i<100;$i++){
  $res = md5($password);
}
$etime = microtime(true);
echo "stime:$stime<br/>";
echo "etime:$etime<br/>";
echo "cost:".($etime-$stime);

Run results:

stime:1478265603.1118
etime:1478265603.1229
cost:0.011116981506348

password_hash.php


<?php
$stime = microtime(true);
$password = "root123@";
for($i=0;$i<100;$i++){
  $res = password_hash($password,PASSWORD_DEFAULT);
}
$etime = microtime(true);
echo "stime:$stime<br/>";
echo "etime:$etime<br/>";
echo "cost:".($etime-$stime);

Run results:

stime:1478265640.382
etime:1478265646.6675
cost:6.2854981422424

If the security requirements are particularly high, you can use password_hash In this case, 1 can improve server performance in other ways.

However, in most cases, it is very safe to store salt in redis and the ciphertext after md5 in mysql. Smile:)

PS: Friends who are interested in encryption and decryption can also refer to the online tools of this site:

Text online encryption and decryption tools (including AES, DES, RC4, etc.):
http://tools.ofstack.com/password/txt_encode

MD5 Online Encryption Tool:
http://tools.ofstack.com/password/CreateMD5Password

Online hash/hash algorithm encryption tool:
http://tools.ofstack.com/password/hash_encrypt

Online MD5/hash/SHA-1/SHA-2/SHA-256/SHA-512/SHA-3/RIPEMD-160 Encryption Tool:
http://tools.ofstack.com/password/hash_md5_sha

Online sha1/sha224/sha256/sha384/sha512 Encryption Tool:
http://tools.ofstack.com/password/sha_encode

For more readers interested in PHP related contents, please check the special topics of this site: "Summary of php Encryption Methods", "Summary of PHP Encoding and Transcoding Operation Skills", "Summary of PHP Mathematical Operation Skills", "Encyclopedia of PHP Array (Array) Operation Skills", "Summary of php String (string) Usage", "Tutorial on PHP Data Structure and Algorithm", "Summary of php Programming Algorithm" and "Summary of php Regular Expression Usage"

I hope this article is helpful to everyone's PHP programming.


Related articles: