PHP的Mcrypt加密擴展知識瞭解

今天咱們來學習的是 PHP 中的一個過期的擴展 Mcrypt 。在 PHP7 以前,這個擴展是隨 PHP 安裝包一塊兒內置發佈的,可是如今新版本的 PHP 中已經沒有了,須要使用這個擴展的話咱們須要單獨安裝,而且在使用的時候也是會報出過期的警告的。因此,咱們學習使用這些函數的時候,就須要使用 @ 來抑制錯誤信息。固然,之因此會對這套擴展發出過期警告,是由於 PHP 更加推薦使用 OpenSSL 來處理相似的加密能力。php

模塊和算法

Mcrypt 主要是使用的 Mcrypt 工具來進行加密操做的,因此在 CentOS 或者其它操做系統中,咱們須要安裝 libmcrypt-devel 來使用這個擴展。若是 yum 中沒法安裝的話,直接更新 yum 源便可。git

Mcrypt 包含不少的模塊和算法。算法就不用多解釋了,就是用來對數據進行加密的方式。而模塊,包括 CBC, OFB,CFB 和 ECB 這幾種,是一系列的分組、流式加密的模式,有推薦的模塊,也有安全的模塊,具體的區分你們能夠自行查閱相關的資料,這裏咱們先看一下咱們的環境中所支持的模塊和算法。github

$algorithms = @mcrypt_list_algorithms();
print_r($algorithms);
// Array
// (
//     [0] => cast-128
//     [1] => gost
//     [2] => rijndael-128
//     [3] => twofish
//     [4] => arcfour
//     [5] => cast-256
//     [6] => loki97
//     [7] => rijndael-192
//     [8] => saferplus
//     [9] => wake
//     [10] => blowfish-compat
//     [11] => des
//     [12] => rijndael-256
//     [13] => serpent
//     [14] => xtea
//     [15] => blowfish
//     [16] => enigma
//     [17] => rc2
//     [18] => tripledes
// )

$modes = @mcrypt_list_modes();
print_r($modes);
// Array
// (
//     [0] => cbc
//     [1] => cfb
//     [2] => ctr
//     [3] => ecb
//     [4] => ncfb
//     [5] => nofb
//     [6] => ofb
//     [7] => stream
// )

mcrypt_list_algorithms() 函數能夠得到當前環境下全部支持的 Mcrypt 算法。而 mcrypt_list_modes() 則打印出了當前環境下全部可支持的模塊。注意在某些版本的 PHP 或者某些系統中,這些內容會有所不一樣,在使用 Mcrypt 相關的加密能力的時候,這兩項都是相互配合使用的。所以,咱們有必要在須要運行 Mcrypt 的環境中預先肯定好當前環境下所支持的模塊和算法。算法

加密解密數據

$key = hash('sha256', 'secret key', true);
$input = json_encode(['id'=>1, 'data'=>'Test mcrypt!']);

$td = @mcrypt_module_open('rijndael-128', '', 'cbc', '');
$iv = @mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_URANDOM);
@mcrypt_generic_init($td, $key, $iv);
$encrypted_data = @mcrypt_generic($td, $input);
@mcrypt_generic_deinit($td);
@mcrypt_module_close($td);

echo $encrypted_data, PHP_EOL;
// ��I      $�3���gE�ǣu(�9n�����
//                            p�>P

$td = @mcrypt_module_open('rijndael-128', '', 'cbc', '');

@mcrypt_generic_init($td, $key, $iv);
$data = @mdecrypt_generic($td, $encrypted_data);
echo $data, PHP_EOL;
// {"id":1,"data":"Test mcrypt!"}

@mcrypt_generic_deinit($td);
@mcrypt_module_close($td);

代碼比較多也較亂,咱們一塊一塊來看。json

首先是咱們肯定一個加密的 key ,而後 input 就是咱們要加密的數據。好比咱們要加密一個 json 數據。這個 key 其實用字符串就能夠,但咱們這裏也對 key 進行了一次 hash 處理,這個 hash 相關的內容在上一篇文章咱們已經詳細的講解過了。安全

接下來就是使用 mcrypt_module_open() 打開一個加密模塊句柄,這裏咱們使用 rijndael-128 算法和 cbc 模塊。而後使用 mcrypt_create_iv() 建立一個 iv ,這個 iv 就是一個初始化向量。初始化向量的值依密碼算法而不一樣。最基本的要求是「惟一性」,也就是說同一把密鑰不重複使用同一個初始化向量。這個特性不管在分組加密或流加密中都很是重要。相信你們要是作過微信或支付寶相關的接口通訊,在解密驗證數據的時候必定會見過這個 iv 屬性。微信

使用 mcrypt_generic() 生成加密結果,使用 mcrypt_generic_deinit() 結束生成初始化,最後經過 mcrypt_module_close() 關閉加密模塊句柄。這樣,一套 Mcrypt 加密流程就完成了。函數

一樣的,解密流程和加密流程也是相似的,只是咱們使用 mdecrypt_generic() 這個函數來進行解密就能夠了。工具

另外一種加密解密數據方式

上面的加密流程很是麻煩並且複雜,其實在 Mcrypt 中還提供了一種更簡單的加密函數。學習

$string = 'Test MCrypt2';
$algorithm = 'rijndael-128';
$key = md5( "mypassword", true);
$iv_length = @mcrypt_get_iv_size( $algorithm, MCRYPT_MODE_CBC );
$iv = @mcrypt_create_iv( $iv_length, MCRYPT_RAND );

$encrypted = @mcrypt_encrypt( $algorithm, $key, $string, MCRYPT_MODE_CBC, $iv );
$result = @mcrypt_decrypt( $algorithm, $key, $encrypted, MCRYPT_MODE_CBC, $iv );

echo $encrypted, PHP_EOL; // \<�`�U��Uf)�Y
echo $result, PHP_EOL; // Test MCrypt2

咱們依然要準備好要加密的數據,算法,key ,以及 iv 向量。而後直接使用 mcrypt_encrypt() 和 mcrypt_decrypt() 來進行加/解密就能夠了,是否是方便不少。

總結

相對於 Hash 來講,Mcrypt 是可解密的對稱加密形式。關於什麼是對稱和非對稱加密,咱們將在 OpenSSL 擴展的學習中詳細地講解,而 Hash 加密則是單向的加密形式,是沒法經過加密後的數據反向計算得到原始數據的。它們都有不一樣的應用場景,不過就像 PHP 提示的那樣,Mcrypt 已是不推薦使用的擴展了,因此咱們在這裏只是簡單的進行了加/解密的測試而已,若是有用到的小夥伴,能夠根據手冊進行更深刻地學習。

測試代碼:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202007/source/PHP%E7%9A%84Mcrypt%E5%8A%A0%E5%AF%86%E6%89%A9%E5%B1%95%E7%9F%A5%E8%AF%86%E4%BA%86%E8%A7%A3.php

參考文檔:

https://www.php.net/manual/zh/book.mcrypt.php

https://ask.csdn.net/questions/700696

各自媒體平臺都可搜索【硬核項目經理】

相關文章
相關標籤/搜索