天天看點

PHP加密算法零:密碼外洩門一:前言二:Md5加密算法(不推薦儲存密碼)三:Sha1加密算法(不推薦儲存密碼)四:Crypt加密算法(推薦儲存密碼)

零:密碼外洩門

2011年12月,CSDN的安全系統遭到黑客攻擊,600萬使用者的登入名、密碼及郵箱遭到洩漏。随後,CSDN"密碼外洩門"持續發酵,天涯、世紀佳緣等網站相繼被曝使用者資料遭洩密。洩密就算了,更讓人無語的是密碼等資訊都是明文存儲,導緻黑客直接拿到了資訊而無需破解,這一系列事件發生後,密文存儲使用者資訊的方式開始流行。

一:前言

這篇部落格會介紹一些經典的加密算法,其中md5、sha1、sha256等加密算法雖然是單向雜湊演算法,是不可逆的,但是由于其太經典了,是以很可能被暴力破解,就是他們會把常見字元進行組合使用這些經典加密算法後存到資料庫中,需要解密時就把需要解密的字元串與資料庫中的進行比對,是以都有被破解的風險,是以這類算法并不适合用在密碼保護場景。

破解網站如下:

PHP加密算法零:密碼外洩門一:前言二:Md5加密算法(不推薦儲存密碼)三:Sha1加密算法(不推薦儲存密碼)四:Crypt加密算法(推薦儲存密碼)
PHP加密算法零:密碼外洩門一:前言二:Md5加密算法(不推薦儲存密碼)三:Sha1加密算法(不推薦儲存密碼)四:Crypt加密算法(推薦儲存密碼)

對于密碼散列安全,php官方是這麼說的:

為什麼需要把應用程式中使用者的密碼進行散列化

當設計一個需要接受使用者密碼的應用時, 對密碼進行散列是最基本的,也是必需的安全考慮。 如果不對密碼進行散列處理,那麼一旦應用的資料庫受到攻擊, 那麼使用者的密碼将被竊取。 同時,竊取者也可以使用使用者賬号和密碼去嘗試其他的應用, 如果使用者沒有為每個應用單獨設定密碼,那麼将面臨風險。

通過對密碼進行散列處理,然後再儲存到資料庫中, 這樣就使得攻擊者無法直接擷取原始密碼, 同時還可以保證你的應用可以對原始密碼進行相同的散列處理, 然後比對散列結果。

需要着重提醒的是,密碼散列隻能保護密碼 不會被從資料庫中直接竊取, 但是無法保證注入到應用中的 惡意代碼攔截到原始密碼。

為何諸如 md5() 和 sha1() 這樣的常見散列函數不适合用在密碼保護場景

MD5,SHA1 以及 SHA256 這樣的雜湊演算法是面向快速、高效 進行散列處理而設計的。随着技術進步和計算機硬體的提升, 破解者可以使用“暴力”方式來尋找散列碼 所對應的原始資料。

因為現代化計算機可以快速的“反轉”上述雜湊演算法的散列值, 是以很多安全專家都強烈建議 不要在密碼散列中使用這些雜湊演算法。

如果不建議使用常用散列函數保護密碼, 那麼我應該如何對密碼進行散列處理

我們可以在進行散列處理的過程中加入的一些資料,用來避免從已計算的散列值表 (被稱作“彩虹表”)中 對比輸出資料進而擷取明文密碼的風險。

簡單而言,“鹽”就是為了提高散列值被破解的難度而加入的少量資料。 現在有很多線上服務都能夠提供計算後的散列值以及其對應的原始輸入的清單, 并且資料量極其龐大。 通過加“鹽”就可以避免直接從清單中查找到對應明文的風險。

如果不提供“鹽”,password_hash() 函數會随機生成“鹽”。 非常簡單,行之有效。

雖然這些算法都有可能被破解,但是這篇部落格還是會介紹幾種推薦儲存的密碼的算法的。

二:Md5加密算法(不推薦儲存密碼)

是單項散列加密算法,不可逆。MD5加密是php最常見的不可逆加密算法。來自 RFC 1321 的解釋 - MD5 封包摘要算法:MD5 封包摘要算法将任意長度的資訊作為輸入值,并将其換算成一個 128 位長度的"指紋資訊"或"封包摘要"值來代表這個輸入值,并以換算後的值作為結果。MD5 算法主要是為數字簽名應用程式而設計的;在這個數字簽名應用程式中,較大的檔案将在加密(這裡的加密過程是通過在一個密碼系統下[如:RSA]的公開密鑰下設定私有密鑰而完成的)之前以一種安全的方式進行壓縮。

文法如下:

參數一的

$str

是原始字元串

參數二的

$raw_output

是可選值,預設為false,如果設定為true,則md5封包摘要将以16位元組長度的原始二進制格式傳回。傳回以32位字元十六進制數字形式傳回散列值。

示例如下:

<?php
$str = "eyes";
echo md5($str);
echo "<br>";
echo md5($str, true);
           
PHP加密算法零:密碼外洩門一:前言二:Md5加密算法(不推薦儲存密碼)三:Sha1加密算法(不推薦儲存密碼)四:Crypt加密算法(推薦儲存密碼)

三:Sha1加密算法(不推薦儲存密碼)

sha1加密算法和MD5加密算法一樣時不可逆的,有兩個參數,一個是要加密的字元串,第二個是bool值,如果指定第二個參數為TRUE,則傳回二進制格式的字元串,如果不指定則預設為FALSE,傳回的是40位的16進制格式的字元串

文法如下:

參數一的

$str

是加密的字元串

參數二的

$raw_output

:如果被設定為TRUE,那麼sha1摘要将以20字元長度的原始格式傳回,否則傳回值是一個40字元長度的十六進制數字

PHP加密算法零:密碼外洩門一:前言二:Md5加密算法(不推薦儲存密碼)三:Sha1加密算法(不推薦儲存密碼)四:Crypt加密算法(推薦儲存密碼)

四:Crypt加密算法(推薦儲存密碼)

crypt()加密算法是一種不可逆的加密算法,他有兩個參數,一個是需要加密的字元串,另外一個是鹽值(或者成為幹擾字元串)。這個函數在不同的作業系統上的表現形式也是不一樣的,會自動檢測。該算法可以在PHP5.3及後續版本使用, 它支援多種雜湊演算法。 針對每種受支援的雜湊演算法,PHP 都提供了對應的原生實作, 是以在使用此函數的時候, 你需要保證所選的雜湊演算法是你的系統所能夠支援的。

如果使用 crypt() 函數來進行密碼驗證, 那麼你需要選擇一種耗時恒定的字元串比較算法來避免時序攻擊。就是說,字元串比較所消耗的時間恒定, 不随輸入資料的多少變化而變化,PHP 中的 ==和=== 操作符 和 strcmp() 函數都不是耗時恒定的字元串比較, 但是 password_verify() 可以幫你完成這項工作。 我們鼓勵你盡可能的使用原生密碼散列API。

文法如下:

傳回一個基于UNIX DES算法或系統上其他可用的替代算法的散列字元串。

參數一的

str

: 需要加密的明文。

參數二的

$salt

:加密時的幹擾串,使編碼更安全,一般是兩個字元

然而,如果沒有salt的話,如果加密時沒有加上這個

$salt

參數,則會随機生成一個幹擾串,且crypt()建立出來的會是弱密碼。 php 5.6及之後的版本會在沒有它的情況下抛出一個 E_NOTICE 級别的錯誤。為了更好的安全性,是以需要確定指定一個足夠強度的鹽值。

<?php
$str = "eyes++";
echo crypt($str);
echo "<br>";
echo crypt($str, "eyes");
           
PHP加密算法零:密碼外洩門一:前言二:Md5加密算法(不推薦儲存密碼)三:Sha1加密算法(不推薦儲存密碼)四:Crypt加密算法(推薦儲存密碼)

圖檔中以$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');
}
           
PHP加密算法零:密碼外洩門一:前言二:Md5加密算法(不推薦儲存密碼)三:Sha1加密算法(不推薦儲存密碼)四:Crypt加密算法(推薦儲存密碼)