零:密碼外泄門
2011年12月,CSDN的安全系統遭到黑客攻擊,600萬用戶的登錄名、密碼及郵箱遭到泄漏,隨后,CSDN"密碼外泄門"持續發酵,天涯、世紀佳緣等網站相繼被曝用戶資料遭泄密,泄密就算了,更讓人無語的是密碼等資訊都是明文存盤,導致黑客直接拿到了資訊而無需破解,這一系列事件發生后,密文存盤用戶資訊的方式開始流行,
一:前言
這篇博客會介紹一些經典的加密演算法,其中md5、sha1、sha256等加密演算法雖然是單向散列演算法,是不可逆的,但是由于其太經典了,因此很可能被暴力破解,就是他們會把常見字符進行組合使用這些經典加密演算法后存到資料庫中,需要解密時就把需要解密的字串與資料庫中的進行比對,因此都有被破解的風險,因此這類演算法并不適合用在密碼保護場景,
破解網站如下:


對于密碼散列安全,php官方是這么說的:
為什么需要把應用程式中用戶的密碼進行散列化
當設計一個需要接受用戶密碼的應用時, 對密碼進行散列是最基本的,也是必需的安全考慮, 如果不對密碼進行散列處理,那么一旦應用的資料庫受到攻擊, 那么用戶的密碼將被竊取, 同時,竊取者也可以使用用戶賬號和密碼去嘗試其他的應用, 如果用戶沒有為每個應用單獨設定密碼,那么將面臨風險,
通過對密碼進行散列處理,然后再保存到資料庫中, 這樣就使得攻擊者無法直接獲取原始密碼, 同時還可以保證你的應用可以對原始密碼進行相同的散列處理, 然后比對散列結果,
需要著重提醒的是,密碼散列只能保護密碼 不會被從資料庫中直接竊取, 但是無法保證注入到應用中的 惡意代碼攔截到原始密碼,
為何諸如 md5() 和 sha1() 這樣的常見散列函式不適合用在密碼保護場景
MD5,SHA1 以及 SHA256 這樣的散列演算法是面向快速、高效 進行散列處理而設計的,隨著技術進步和計算機硬體的提升, 破解者可以使用“暴力”方式來尋找散列碼 所對應的原始資料,
因為現代化計算機可以快速的“反轉”上述散列演算法的散列值, 所以很多安全專家都強烈建議 不要在密碼散列中使用這些散列演算法,
如果不建議使用常用散列函式保護密碼, 那么我應該如何對密碼進行散列處理
我們可以在進行散列處理的程序中加入的一些資料,用來避免從已計算的散列值表 (被稱作“彩虹表”)中 對比輸出資料從而獲取明文密碼的風險,
簡單而言,“鹽”就是為了提高散列值被破解的難度而加入的少量資料, 現在有很多在線服務都能夠提供計算后的散列值以及其對應的原始輸入的清單, 并且資料量極其龐大, 通過加“鹽”就可以避免直接從清單中查找到對應明文的風險,
如果不提供“鹽”,password_hash() 函式會隨機生成“鹽”, 非常簡單,行之有效,
雖然這些演算法都有可能被破解,但是這篇博客還是會介紹幾種推薦保存的密碼的演算法的,
二:Md5加密演算法(不推薦保存密碼)
是單項散列加密演算法,不可逆,MD5加密是php最常見的不可逆加密演算法,來自 RFC 1321 的解釋 - MD5 報文摘要演算法:MD5 報文摘要演算法將任意長度的資訊作為輸入值,并將其換算成一個 128 位長度的"指紋資訊"或"報文摘要"值來代表這個輸入值,并以換算后的值作為結果,MD5 演算法主要是為數字簽名應用程式而設計的;在這個數字簽名應用程式中,較大的檔案將在加密(這里的加密程序是通過在一個密碼系統下[如:RSA]的公開密鑰下設定私有密鑰而完成的)之前以一種安全的方式進行壓縮,
語法如下:
string md5 ( string $str [, bool $raw_output = false ] )
引數一的$str是原始字串
引數二的$raw_output是可選值,默認為false,如果設定為true,則md5報文摘要將以16位元組長度的原始二進制格式回傳,回傳以32位字符十六進制數字形式回傳散列值,
示例如下:
<?php
$str = "eyes";
echo md5($str);
echo "<br>";
echo md5($str, true);

三:Sha1加密演算法(不推薦保存密碼)
sha1加密演算法和MD5加密演算法一樣時不可逆的,有兩個引數,一個是要加密的字串,第二個是bool值,如果指定第二個引數為TRUE,則回傳二進制格式的字串,如果不指定則默認為FALSE,回傳的是40位的16進制格式的字串
語法如下:
string sha1(string $str[, bool $raw_output=false])
引數一的$str是加密的字串
引數二的$raw_output:如果被設定為TRUE,那么sha1摘要將以20字符長度的原始格式回傳,否則回傳值是一個40字符長度的十六進制數字

四:Crypt加密演算法(推薦保存密碼)
crypt()加密演算法是一種不可逆的加密演算法,他有兩個引數,一個是需要加密的字串,另外一個是鹽值(或者成為干擾字串),這個函式在不同的作業系統上的表現形式也是不一樣的,會自動檢測,該演算法可以在PHP5.3及后續版本使用, 它支持多種散列演算法, 針對每種受支持的散列演算法,PHP 都提供了對應的原生實作, 所以在使用此函式的時候, 你需要保證所選的散列演算法是你的系統所能夠支持的,
如果使用 crypt() 函式來進行密碼驗證, 那么你需要選擇一種耗時恒定的字串比較演算法來避免時序攻擊,就是說,字串比較所消耗的時間恒定, 不隨輸入資料的多少變化而變化,PHP 中的 ==和=== 運算子 和 strcmp() 函式都不是耗時恒定的字串比較, 但是 password_verify() 可以幫你完成這項作業, 我們鼓勵你盡可能的使用原生密碼散列API,
語法如下:
string crypt(string $str[, string $salt])
回傳一個基于UNIX DES演算法或系統上其他可用的替代演算法的散列字串,
引數一的str: 需要加密的明文,
引數二的$salt:加密時的干擾串,使編碼更安全,一般是兩個字符
然而,如果沒有salt的話,如果加密時沒有加上這個$salt引數,則會隨機生成一個干擾串,且crypt()創建出來的會是弱密碼, php 5.6及之后的版本會在沒有它的情況下拋出一個 E_NOTICE 級別的錯誤,為了更好的安全性,所以需要確保指定一個足夠強度的鹽值,
<?php
$str = "eyes++";
echo crypt($str);
echo "<br>";
echo crypt($str, "eyes");
圖片中以$1開頭,$結尾,中間不超過12個字符,是MD5的特色,這個在下面會提到,
在 crypt() 函式支持多重散列的系統上,下面的常量根據相應的型別是否可用被設定為 0 或 1:
- CRYPT_STD_DES - 基于標準 DES 演算法的散列使用 “./0-9A-Za-z” 字符中的兩個字符作為鹽值,即如果鹽值超過2個字符,則截取前兩個字符,在鹽值中使用非法的字符將導致 crypt() 失敗,
- CRYPT_EXT_DES - 擴展的基于 DES 演算法的散列,其鹽值為 9 個字符的字串,由 1 個下劃線后面跟著 4 位元組回圈次數和 4 位元組鹽值組成,它們被編碼成可列印字符,每個字符 6 位,有效位最少的優先,0 到 63 被編碼為 “./0-9A-Za-z”,在鹽值中使用非法的字符將導致 crypt() 失敗,
- CRYPT_MD5 - MD5 散列使用一個以 1 1 1 開始的 12 字符的字串鹽值,注意鹽值最多12個字符,超出則截取前8位,
- CRYPT_BLOWFISH - Blowfish 演算法使用如下鹽值:"$2a$",一個兩位 cost 引數,"$" 以及 64 位由 “./0-9A-Za-z” 中的字符組合而成的字串,在鹽值中使用此范圍之外的字符將導致 crypt() 回傳一個空字串,兩位 cost 引數是回圈次數以 2 為底的對數,它的范圍是 04-31,超出這個范圍將導致 crypt() 失敗, PHP 5.3.7 之前只支持 “$2a$” 作為鹽值的前綴,PHP 5.3.7 開始引入了新的前綴來修正一個在Blowfish實作上的安全風險,可以參考? this document來了解關于這個修復的更多資訊,總而言之,開發者如果僅針對 PHP 5.3.7及之后版本進行開發,那應該使用 “$2y$” 而非 “$2a$”
- CRYPT_SHA256 - SHA-256 演算法使用一個以$5$ 開頭的 16 字符字串鹽值進行散列,如果鹽值字串以 “rounds=<N>$” 開頭,N 的數字值將被用來指定散列回圈的執行次數,這點很像 Blowfish 演算法的 cost 引數,默認的回圈次數是 5000,最小是 1000,最大是 999,999,999,超出這個范圍的 N 將會被轉換為最接近的值,
- CRYPT_SHA512 - SHA-512 演算法使用一個以 $6$ 開頭的 16 字符字串鹽值進行散列,如果鹽值字串以 “rounds=<N>$” 開頭,N 的數字值將被用來指定散列回圈的執行次數,這點很像 Blowfish 演算法的 cost 引數,默認的回圈次數是 5000,最小是 1000,最大是 999,999,999,超出這個范圍的 N 將會被轉換為最接近的值,
<?php
$str = "eyes++";
echo crypt($str);
echo "<br>";
echo crypt($str, "eyes");
echo "<hr>";
if (CRYPT_STD_DES) {
echo "標準DES演算法: " . crypt($str, "eyes");
echo "<br>";
echo "標準DES演算法: " . crypt($str, "eyes");
}
echo "<hr>";
if (CRYPT_MD5) {
echo "MD5 散列: " . crypt($str, '$1$abcd$');
echo "<br>";
echo "MD5 散列: " . crypt($str, '$1$abcd$');
}
echo "<hr>";
if (CRYPT_SHA256) {
echo "SHA-256 演算法: " . crypt($str, '$6$1sas515');
echo "<br>";
echo "SHA-256 演算法: " . crypt($str, '$6$1sas515');
}
echo "<hr>";
if (CRYPT_SHA512) {
echo "SHA-512 演算法: " . crypt($str, '$6$1sa151acacsas515');
echo "<br>";
echo "SHA-512 演算法: " . crypt($str, '$6$1sa151acacsas515');
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/301444.html
標籤:其他
