PHP中雜湊密碼的安全性分析

2022-09-26 05:00:12 字數 3433 閱讀 5605

php的基本雜湊函式已經不再安全?

php手冊中有專門的乙個部分來介紹這個問題

很多應用,都是將使用者的密碼都是直接通過md5加密直接儲存到資料庫中的,包括我最近在用的開源專案zabbix的web管理介面。

$password = "1234";

$hash = md5($password);

echo $res;

php常用的雜湊函式有md5和sha1,這種雜湊之後,一般是不可逆的,但是可以重現,也就gudeqvpqry是說同樣的明文,雜湊之後的結果是一樣的,對於一些簡單的明文,是可以通過遍歷,然後對照加密之後的密文得到明文的。

網上有流傳的「彩虹表」,就是遍歷的到的乙個非常大的資料庫,儲存了明文和密文的對照關係,通過查詢就能得到密文對應的明文。

這個**就提供這種伺服器,也就說如果黑客「脫褲」成功,拿到使用者密碼的密文之後,還是有很大的可能性解密得到明文了。

將明文「1234」,通過md5加密之後,在上面的**是很容易解密出來的。

通過「加鹽」,增加破解難度

「加鹽」的意思是給明文加上一些資料,然後再進行加密。這樣的話,就算明文(使用者的密碼)比較簡單,加鹽之後就變得更加複雜一些,然後再加密,這就增加了黑客去解密明文的難度。

$password = "1234";

$salt = "s@jn#.sk_jf3;gg*&";

$hash = md5($password.$salt);

echo $res;

同樣的明文「1234」,加了乙個比較複雜的「鹽」之後,再進行加密,解密的難度就增加了不少,在上面的解密**是就不能被解密出來了(最起碼不付錢是解密不出來的,哈哈哈)。

上面我們對所有的密碼都使用的同樣的鹽,這中方式是不大安全的。比如,張三和李四的密碼是一樣的,則儲存在資料庫中的密文也是一樣的,這無疑讓黑客更容易破解了。

更常使用的方式,是對於不同的使用者使用不同的鹽進行加密,在使用者的註冊過程中,生成使用者對應的鹽,然後進行儲存;在使用者登入時,取出鹽用於加密操作,鹽和使用者id一一對應。

可以使用php自帶的random_bytes生成一定長度的鹽

$password = "1234";

$salt = bin2hex(random_bytes(32));

$hash = md5($password.$salt);

echo $res;

關於鹽的儲存

可以將鹽和密文一起存在資料庫的使用者資訊表中,優點是資料庫查詢取出密碼的同時也可以取出鹽,進行加密比對程式設計客棧操作,一次資料查詢就可以搞定,缺點是安全性差,如果黑客「脫褲」成功,則獲取密文的同時也獲取了對應的鹽。

更好的方案是將鹽和密文分開儲存,比如密文儲存在mysql資料庫中,鹽儲存在redis伺服器中,這樣即使黑客「脫褲」拿到了資料庫中的密文,也需要再進一步拿到對應的鹽才能進一步破解,安全性更好,不過這樣需要進行二次查詢,即每次登陸都需要從redis中取出對應的鹽,犧牲了一定的效能,提高了安全性。

php5.5中更加安全的解決方案

說php是專為為web設計的語言一點也沒錯,應該是php開發者也注意到了這個密碼儲存的問題。

於是php5.5開始,就設計了password_hashing模組,用於密碼的雜湊和驗證。

使用password_hash進行雜湊,使用的演算法、cost 和鹽值作為雜湊的一部分返回,所以不用單獨儲存salt的值,因為它每次都會自己生成salt,所以優點就是「每次加密的結果都不一樣」,但是可以放心,加密結果包含了salt資訊,password_verify可以正確解析。

$password = "1234";

$hash = password_hash($password,password_default);

雜湊之後的結果,只能使用password_verify進行驗證,因此驗證密碼的功能只能由php語言來實現。

$password = "1234";

$hash = password_hash($password,password_default);

$res = password_verify($password,$hash); //驗證結果為true

優缺點分析

優點是安全性很高,即使被脫褲,也很難將密文解密,因為同乙個密文,每次加密的結果都不一樣,所以沒法撞庫!

password_hash實際上是對crypt和salt的封裝,crypt加密比普通的md5和sha1更加複雜,所以耗時也更加多一些,這可以算是乙個缺點,對於使用者量很大,經常需要進行登入操作的站點,可能會有效能上的影響。還有一點是通用性不強,因為這種方式只適用於php語言,其他語言是沒有辦法對密文進行操作的。

剛才測試了一下password_hash的效能,嚇的半死。。

md5.php

<?php $stime = microtime(true);

$password = "root123@";

$salt = "83979fklsdfgklu9023*&*(&()#&*(y*(@&*<:l:%:::>>?11!!^%^$%$%^<>yuiyuihjkdshfjkh#j#hjk#hkl;dskfs";

for($i=0;$i<100;$i++)

$etime = microtime(true);

echo "stime:$stime

";echo "etime:$etime

";echo "cost:".($etime-$stime);

執行結果:

stime:1478265603.1118

etime:1478265603.1229

cost:0.011116981506348

password_hash.php

<?php $stime = microtime(true);

$password = "root123@";

for($i=0;$i<100;$i++)

$etime = microtime(true);

echo 程式設計客棧"stime:$stime

";echo "etime:$etime

";echo "cost:".($etime-$stime);

執行結果:

stime:1478265640.382

etime:1478265646.6675

cost:6.2854981422424

如果是安全性要求特別高的情況下,可以使用password_hash的方式,這種情況下一般可以通過其他方式提高伺服器效能。

不過,大多是情況下,將salt儲存在redis,md5之後的密文儲存在mysql的方式已經非常安全了,微笑 :)

ps:關於加密解密感興趣的朋友還可以參考本站**工具:

文字**加密解密工具(包含aes、des、rc4等):

md5**加密工具:

**雜湊/雜湊演算法加密工具:

**md5/hash/sha-1/sha-2/sha-256/sha-512/sha-3/ripemd-160加密工具:

**sha1/sha224/sha256/sha384/sha512加密工具:

PHP安全性漫談之PHP安全性設定

伺服器並不能阻止所有的安全問題,例如程式漏洞問題 使用者輸入表單問題 php檔案許可權問題等。也可以通過一些手段來迷惑黑客或者別有用心者。1 程式 漏洞問題 很多 php 程式所存在的重大弱點並不是 php 語言本身的問題,而是程式設計者的安全意識不高而導致的。因此,必須時時注意每一段 可能存在的問...

密碼安全性檢查

要求 安全級別低 密碼由單純數字或字母組成 密碼長度小於等於8位 安全級別中 密碼由數字,字母,特殊字元任意兩種組合,密碼長度不低於8位 安全級別高 密碼由數字,字母及特殊字元三種組合,開頭只能為字母。密碼長度不低於16位 str.isdigit 當字串只包含數字返回true str.isalpha...

密碼系統的安全性

1 無條件安全性 這種評價方法考慮的是假定攻擊者擁有無限的計算資源,但仍然無法破譯該密碼系統。2 計算安全性 這種方法是指使用目前最好的方法攻破它所需要的計算遠遠超出攻擊者的計算資源水平,則可以定義這個密碼體制是安全的。3 可證明安全性 這種方法是將密碼系統的安全性歸結為某個經過深入研究的數學難題 ...