標籤:

PHP的幾種加密演算法

前言

PHP加密方式分為單項散列加密,對稱加密,非對稱加密這幾類。像常用的MD5、hash、crypt、sha1這種就是單項散列加密,單項散列加密是不可逆的。像URL編碼、base64編碼這種就是對稱加密,是可逆的,就是說加密解密都是用的同一秘鑰。除此外就是非對稱加密,加密和解密的秘鑰不是同一個,如果從安全性而言,加密的信息如果還想著再解密回來,非對稱加密無疑是最為安全的方式。

MD5加密

md5加密演算法在PHP中是最常見的加密演算法,這個演算法是不可逆的,通常用於加密用戶的密碼等信息來保證用戶的信息安全。來自 RFC 1321 的解釋 - MD5 報文摘要演算法:MD5 報文摘要演算法將任意長度的信息作為輸入值,並將其換算成一個 128 位長度的"指紋信息"或"報文摘要"值來代表這個輸入值,並以換算後的值作為結果。MD5 演算法主要是為數字簽名應用程序而設計的;在這個數字簽名應用程序中,較大的文件將在加密(這裡的加密過程是通過在一個密碼系統下[如:RSA]的公開密鑰下設置私有密鑰而完成的)之前以一種安全的方式進行壓縮。好,來舉個例子

<?phpn//這裡是一個字元串n$str = "this is zifuchuan";nn//通過MD5加密函數加密n$res = md5($str);nn//在PHP中,MD5()函數還有第二個參數,為bool類型,當為TRUE是返回的加密是16字元原始n//二進位格式字元串,當為FALSE是返回32位的16進位,默認為false,一般都默認nn//返回二進位n$res = md5($str,true);n?>n

Crypt()加密演算法

crypt()加密演算法是一種不可逆的加密演算法,他有兩個參數,一個是需要加密的字元串,另外一個是鹽值(或者成為干擾字元串),如果沒有指定第二個參數那麼將自己隨機生成一個干擾字元串並且是以MD5加密的方式。另外這個函數在不同的操作系統上的表現形式也是不一樣的,會自動檢測。舉個例子。

<?phpn//需要加密的字元串n$str = "this is string";nn//使用crypt加密,不指定鹽值nn$res = crypt($str);nn//指定鹽值,但是鹽值只能寫兩位,如果超過了則只會取前兩位,在某些系統中會直接返回FALSEnn$res = crypt($str,jm);nn?>n

sha1加密演算法

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

<?phpn//需要加密的字元串n$str = "this is string";n//通過sha1進行加密n$res = sha1($str);nn//通過指定第二個參數加密n$res = sha1($str,true);nn?>n

URL編碼加密

對於我們的網站,直接暴露給用戶的就是地址欄的傳參,對於這一部分都是明文的,所以我們可以使用基本的加密演算法來簡單加密一下,注意,此種方式加密是可逆的,也就是說加密後的密文我們可以解密之後看到,所以如果你想實現真正的加密,並不推薦這個加密演算法。

在PHP中對於URL加密解密用到兩個函數urlencode和urldecode.

http://www.guojiadong.com?name=guojiadong&phone=112

我們就可以對這段地址進行加密

<?phpn//需要加密的網址n$str = "http://www.guojiadong.com?name=guojiadong&phone=112";nn//使用urlencode加密n$res = urlencode($str);nn//使用urldecode解密n$result = urldecode($res);nn?>n

既然通過這種方式加密解密並且加密之後也並沒有什麼太大的區別,我們需要他的目的是什麼呢?我們想對於想破解這串加密的字元串可以輕鬆的破解,其實這兩個函數有他特殊的作用,也就是說除了加密的作用,當然了這是題外話,因為本主題主要是加密,但是作為擴展還是要說一下。

<?phpn//在HTML傳參到後台中的時候如果我們想把&作為參數傳到後台,在沒有加密之前,瀏覽器會把他作為n//參數分隔符n//例如:http://guojiadong.com?name=guojiadong&123,我們想把guojiadong&123作為參數傳給n//後台,這個時候直接這樣寫後台得到的數據卻只得到name的值為guojiadong,而123確作為變數n//當然了用一個數字做變數是不合法的,但是瀏覽器確並不這麼智能的區分他n//為了解決這個問題我們就可以對這部分字元編碼n$str = "http://guojiadong.com?name=".urlencode(guojiadong&123);n//這樣我們傳過來的值就變成了name = guojiadong&123nn?>n

Base64編碼加密

大家注意,雖然base64寫到本節加密演算法中,但是他並不是主要用來加密的,而且從大多數的程序來說,幾乎沒有人會用他作為加密手段來加密數據,那麼他的作用主要是用於做什麼呢?這要說的base64加密的機制了。

base64加密本質上說就是把數據轉換為ASCLL碼,比如一個圖片進行base64編碼就會變成一堆以Ascll碼連接的字元串,這會更有利於文件的傳輸,當然base64的作用在與文件的傳輸。例如手機客戶端上傳文件到伺服器,使用base64編碼可以輕鬆實現文件的傳輸。

base64加密函數

base64_encode($data);n

base64解密函數

base64_decode($data);n

hash加密

hash加密也是不可逆的,因為是給定一個不確定的字元串返回特定長度的字元串,這個本質意義上來說實現了單項散列加密。使用方法

hash($ago,$data);n

$ago是可以指定加密使用的哈希演算法,例如:"md5","sha256","haval160,4" 等。

$data是要加密的數據

Password Hashing API 加密

Password Hashing API是PHP 5.5之後才有的新特性,它主要是提供下面幾個函數供我們使用:

password_hash() – 對密碼加密.npassword_verify() – 驗證已經加密的密碼,檢驗其hash字串是否一致.npassword_needs_rehash() – 給密碼重新加密.npassword_get_info() – 返回加密演算法的名稱和一些相關信息.n

雖然說crypt()函數在使用上已足夠,但是password_hash()不僅可以使我們的代碼更加簡短,而且還在安全方面給了我們更好的保障,所以,現在PHP的官方都是推薦這種方式來加密用戶的密碼,很多流行的框架比如Laravel就是用的這種加密方式。

$hash = password_hash($passwod, PASSWORD_DEFAULT);n

對,就是這麼簡單,一行代碼,All done。

PASSWORD_DEFAULT目前使用的就是Bcrypt,所以在上面我會說推薦這個,不過因為Password Hashing API做得更好了,我必須鄭重地想你推薦Password Hashing API。這裡需要注意的是,如果你代碼使用的都是PASSWORD_DEFAULT加密方式,那麼在資料庫的表中,password欄位就得設置超過60個字元長度,你也可以使用PASSWORD_BCRYPT,這個時候,加密後字串總是60個字元長度。

這裡使用password_hash()你完全可以不提供鹽值(salt)和 消耗值 (cost),你可以將後者理解為一種性能的消耗值,cost越大,加密演算法越複雜,消耗的內存也就越大。當然,如果你需要指定對應的鹽值和消耗值,你可以這樣寫:

$options = [

salt => custom_function_for_salt(), //write your own code to generate a suitable salt

cost => 12 // the default cost is 10 ];

$hash = password_hash($password, PASSWORD_DEFAULT, $options);

密碼加密過後,我們需要對密碼進行驗證,以此來判斷用戶輸入的密碼是否正確:

if (password_verify($password, $hash)) {

// Pass }

else {

// Invalid

}

很簡單的吧,直接使用password_verify就可以對我們之前加密過的字元串(存在資料庫中)進行驗證了。

然而,如果有時候我們需要更改我們的加密方式,如某一天我們突然想更換一下鹽值或者提高一下消耗值,我們這時候就要使用到password_needs_rehash()函數了:

if (password_needs_rehash($hash, PASSWORD_DEFAULT, [cost => 12])) {

// cost change to 12 $hash = password_hash($password, PASSWORD_DEFAULT, [cost => 12]);

// dont forget to store the new hash!

}

只有這樣,PHP的Password Hashing API才會知道我們重現更換了加密方式,這樣的主要目的就是為了後面的密碼驗證。

簡單地說一下password_get_info(),這個函數一般可以看到下面三個信息:

algo – 演算法實例

algoName – 演算法名字

options – 加密時候的可選參數

推薦閱讀:

從0開始學PHPExcel(1)之初探
php7為什麼沒有改成強類型語言?
為什麼突然出現大規模黑php風潮?
如何看待 swoole 作者最近修改開源協議?

TAG:PHP |