日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

PHP的OpenSSL加密擴(kuò)展學(xué)習(xí)(一):對(duì)稱加密

 硬核項(xiàng)目經(jīng)理 2021-05-31

PHP的OpenSSL加密擴(kuò)展學(xué)習(xí)(一):對(duì)稱加密

我們已經(jīng)學(xué)過(guò)不少 PHP 中加密擴(kuò)展相關(guān)的內(nèi)容了。而今天開始,我們要學(xué)習(xí)的則是重點(diǎn)中的重點(diǎn),那就是 OpenSSL 加密擴(kuò)展的使用。為什么說(shuō)它是重點(diǎn)中的重點(diǎn)呢?一是 OpenSSL 是目前 PHP 甚至是整個(gè)開發(fā)圈中的數(shù)據(jù)加密事實(shí)標(biāo)準(zhǔn),包括 HTTPS/SSL 在內(nèi)的加密都是它的實(shí)際應(yīng)用,二是 OpenSSL 提供了對(duì)稱和非對(duì)稱加密的形式,也就是我們?nèi)粘V凶钇毡榈膬煞N加密方式,這都是我們需要掌握的內(nèi)容。

那么,它和 Hash 類的加密有什么不同嗎?Hash 類的加密是單向的不可逆轉(zhuǎn)的加密,加密后的內(nèi)容是 16進(jìn)制 的 Hash 串,我們只能通過(guò)彩虹表去反推明文內(nèi)容,所以只要加上鹽值或者多套兩層加密,就非常難逆向破解出來(lái)了。因此,Hash 加密通常會(huì)用于用戶的密碼保存上,即使數(shù)據(jù)庫(kù)泄露了用戶密碼也依然是安全的。而 OpenSSL 這種類型的對(duì)稱/非對(duì)稱加密則是可以通過(guò)某個(gè)關(guān)鍵字或者證書來(lái)進(jìn)行正向加密和逆向解密的,原文都是可以得到的。下面我們就來(lái)具體說(shuō)說(shuō)對(duì)稱和非對(duì)稱加密的問(wèn)題。

什么是對(duì)稱和非對(duì)稱加密

對(duì)稱加密,通常是通過(guò)一個(gè) key(密鑰) 來(lái)對(duì)原文進(jìn)行加密。也就是說(shuō),不管是服務(wù)端還是客戶端或是其它的任何對(duì)端,在兩端通信時(shí),它們傳輸?shù)募用軆?nèi)容都必須要使用相同的 key 來(lái)進(jìn)行加/解密操作。兩端都必須同時(shí)保存這樣一個(gè) key 。估計(jì)大家也想到了,現(xiàn)在不管是 web 開發(fā)還是 app 開發(fā),代碼都是可以反編譯查看到源碼的。如果使用對(duì)稱加密的話,key 是很容易被獲取到的。不過(guò),對(duì)稱加密的好處是速度非???,不消耗資源。

非對(duì)稱加密則是兩端持有不同的 key 。就像我們平常見到的最多的 https 證書,就是分別有 公鑰 和 私鑰 這兩個(gè)概念。一般我們會(huì)使用 公鑰 進(jìn)行加密,然后使用 私鑰 進(jìn)行解密,通常 公鑰 都是公開并發(fā)送給對(duì)方的,而私鑰是保存在自己這里的。也就是說(shuō),對(duì)方向我們發(fā)送數(shù)據(jù)的時(shí)候,使用我們給它的公鑰將數(shù)據(jù)進(jìn)行加密,數(shù)據(jù)在傳輸過(guò)程中就非常安全,因?yàn)橹虚g并沒(méi)有別人有可以解密這段數(shù)據(jù)的私鑰,直到我們接收到數(shù)據(jù)后使用自己的私鑰進(jìn)行解密后就得到了原文數(shù)據(jù)。由于兩邊的密鑰內(nèi)容并不相同,所以相對(duì)于對(duì)稱加密來(lái)說(shuō),非對(duì)稱加密的安全性要高了很多。雖然說(shuō)非對(duì)稱加密的算法和復(fù)雜度都比對(duì)稱加密提升了好幾個(gè)檔次,但相對(duì)于對(duì)稱加密的優(yōu)勢(shì),在非對(duì)稱加密中,速度和性能也就成了它的瓶頸,特別是數(shù)據(jù)量大的情況下。另外,非對(duì)稱加密的數(shù)學(xué)原理是 大數(shù)難分解 問(wèn)題,也就是越大的數(shù)越難進(jìn)行因子分解,如果某個(gè)算法能在短時(shí)間內(nèi)破解這個(gè)問(wèn)題的話,那么恭喜你,現(xiàn)代加密算法的基礎(chǔ)天花板就被你捅破了。

對(duì)稱加密常用的算法有:AES 、DES 、3DES 、 IDEA 、 RC2 、 RC5 等,比較常用的是 AES 和 DES 。

非對(duì)稱加密常用的算法有:RSA 、Elgamal 、ECC 等,RSA 非常常用和普遍,SSL 和一些證書算法都是基于 RSA 。

為了系統(tǒng)安全我們應(yīng)該怎么辦?

那么,我們有沒(méi)有折衷的方式來(lái)使用這兩種加密能力呢?當(dāng)然有了,并且也是非常經(jīng)典的一種技術(shù):數(shù)字信封。

其實(shí)意思非常簡(jiǎn)單,就是利用這兩種加密方式各自的優(yōu)點(diǎn)。非對(duì)稱加密的安全性高,但速度慢,而且數(shù)據(jù)量越大速度越慢,那么我們就用它來(lái)加密對(duì)稱加密的 key ,通常這個(gè) key 不會(huì)很大。然后實(shí)際的數(shù)據(jù)實(shí)體使用這個(gè)對(duì)稱加密的 key 來(lái)進(jìn)行對(duì)稱加密提升速度。這樣,我們發(fā)送給客戶端時(shí),就包括兩個(gè)內(nèi)容,一個(gè)是非對(duì)稱加密進(jìn)行加密的 key ,一個(gè)使用對(duì)稱加密進(jìn)行加密的數(shù)據(jù)內(nèi)容。客戶端拿到信息后,首先使用非對(duì)稱加密的密鑰解碼出對(duì)稱加密的 key ,然后再使用這個(gè) key 來(lái)解密最終的數(shù)據(jù)內(nèi)容。是不是說(shuō)得很暈?我們通過(guò)一張圖來(lái)看看,或許大家就一目了然了。

其中,公鑰和私鑰就不用多解釋了。會(huì)話密鑰就是我們的對(duì)稱加密算法的密鑰 key 。結(jié)合上面對(duì)數(shù)字信封傳輸過(guò)程的解釋,大家應(yīng)該就能看懂了吧。

OpenSSL 擴(kuò)展的對(duì)稱加密

好了,介紹這么多理論知識(shí),接下來(lái)還是回歸正題了,我們?cè)?PHP 中如何實(shí)現(xiàn)對(duì)稱和非對(duì)稱加密呢?非常簡(jiǎn)單,使用 OpenSSL 擴(kuò)展就可以了。這個(gè)擴(kuò)展也是隨 PHP 源碼一起發(fā)布的,編譯安裝的時(shí)候加上 --with-openssl 就可以了。當(dāng)然,它也是需要系統(tǒng)環(huán)境中安裝 OpenSSL 軟件的,在各類操作系統(tǒng)中基本都已經(jīng)直接有了,如果沒(méi)有的話就自己安裝一下即可。最簡(jiǎn)單的,在操作系統(tǒng)命令行看看有沒(méi)有 openssl 命令就可以看出當(dāng)前系統(tǒng)有沒(méi)有安裝 OpenSSL 相關(guān)的軟件。

[root@localhost ~]# openssl version
OpenSSL 1.1.1 FIPS  11 Sep 2018

今天,我們主要學(xué)習(xí)的還是比較簡(jiǎn)單的對(duì)稱加密相關(guān)的函數(shù)。

對(duì)稱加/解密實(shí)現(xiàn)

$data = '測(cè)試對(duì)稱加密';
$key = '加密用的key';
$algorithm =  'DES-EDE-CFB';


$ivlen = openssl_cipher_iv_length($algorithm);
$iv = openssl_random_pseudo_bytes($ivlen);


$password = openssl_encrypt($data, $algorithm, $key, 0, $iv);
echo $password, PHP_EOL;
// 4PvOc75QkIJ184/RULdOTeO8

echo openssl_decrypt($password, $algorithm, $key, 0, $iv), PHP_EOL;
// 測(cè)試對(duì)稱加密

// Warning: openssl_encrypt(): Using an empty Initialization Vector (iv) is potentially insecure and not recommended

openssl_encrypt() 就是加密數(shù)據(jù),它需要原文、算法和密鑰三個(gè)參數(shù),后面的參數(shù)是可選的,但是現(xiàn)在是推薦自己來(lái)定義 iv (向量) 參數(shù),所以如果沒(méi)有 iv 參數(shù)的話,會(huì)報(bào)一個(gè)警告信息。我們使用 openssl_cipher_iv_length() 來(lái)獲取當(dāng)前算法需要的 iv 長(zhǎng)度,然后使用 openssl_random_pseudo_bytes() 函數(shù)來(lái)生成一個(gè)隨機(jī)的符合算法長(zhǎng)度的 iv 內(nèi)容。

中間那個(gè) 0 的參數(shù)是指定標(biāo)記的按位或值,它有兩個(gè)可選常量:OPENSSL_RAW_DATA 和 OPENSSL_ZERO_PADDING ,如果設(shè)置為 OPENSSL_RAW_DATA 加密后的數(shù)據(jù)將按照原樣返回(二進(jìn)制亂碼內(nèi)容),如果設(shè)置為 OPENSSL_ZERO_PADDING ,加密后的數(shù)據(jù)將返回為 base64 之后的內(nèi)容。

openssl_decrypt() 用于對(duì)數(shù)據(jù)進(jìn)行解密,需要的參數(shù)基本和加密函數(shù)一致,只是原文數(shù)據(jù)換成了加密數(shù)據(jù)。

在對(duì)稱加密中,我們還有一種  AEAD 密碼模式(GCM 或 CCM) ,在使用這種模式的算法時(shí),我們需要多一參數(shù)。

$algorithm =  'aes-128-gcm';
$password = openssl_encrypt($data, $algorithm, $key, 0, $iv, $tags);
echo $password, PHP_EOL;
// dPYsR+sdP56rQ99CNxciah+N

echo openssl_decrypt($password, $algorithm, $key, 0, $iv, $tags), PHP_EOL;
// 測(cè)試對(duì)稱加密

這個(gè) $tags 是一個(gè)引用類型的參數(shù),也就是加密后會(huì)賦值到這個(gè)變量中,解密的時(shí)候也需要相同的這個(gè)驗(yàn)證標(biāo)簽。

從加密解密的過(guò)程來(lái)看,如果我們要將這些信息保存在數(shù)據(jù)庫(kù)中,或者進(jìn)行傳輸解密時(shí),我們至少要保存或傳輸這幾個(gè)字段,加密使用的 iv ,加密使用的算法,以及 AEAD 模式的話加密所使用的驗(yàn)證標(biāo)簽,否則數(shù)據(jù)無(wú)法解密。

對(duì)稱加密算法查詢

print_r(openssl_get_cipher_methods());

// Array
// (
//     [0] => AES-128-CBC
//     [1] => AES-128-CBC-HMAC-SHA1
//     [2] => AES-128-CFB
//     [3] => AES-128-CFB1
//     [4] => AES-128-CFB8
//     [5] => AES-128-CTR
//     [6] => AES-128-ECB
//     [7] => AES-128-OFB
//     [8] => AES-128-XTS
//     [9] => AES-192-CBC
//     [10] => AES-192-CFB
//     [11] => AES-192-CFB1
//     [12] => AES-192-CFB8
//     ……
// )

在上面加/解密測(cè)試中所選取的算法就是從這個(gè)函數(shù)中找出來(lái)的,這個(gè)函數(shù)就是顯示當(dāng)前環(huán)境下所有支持的算法列表。

總結(jié)

這篇文章的內(nèi)容有比較多的理論相關(guān)的知識(shí),大家還是要多多地消化。使用 OpenSSL 實(shí)現(xiàn)加/解密的功能其實(shí)還是比較簡(jiǎn)單的,畢竟東西都已經(jīng)幫我們封裝好了,我們只需要按照文檔來(lái)調(diào)用函數(shù)就可以了。學(xué)習(xí),還是要理論結(jié)合實(shí)際,當(dāng)然,更重要的是自己多動(dòng)手!

測(cè)試代碼:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202007/source/PHP%E7%9A%84OpenSSL%E5%8A%A0%E5%AF%86%E6%89%A9%E5%B1%95%E5%AD%A6%E4%B9%A0%EF%BC%88%E4%B8%80%EF%BC%89%EF%BC%9A%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86.php

參考文檔:

https://www./manual/zh/function.openssl-encrypt.php

https://www./manual/zh/function.openssl-decrypt.php

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多