PHP的OpenSSL加密擴展學習(二):非對稱加密

2021-01-21 硬核項目經理
PHP的OpenSSL加密擴展學習(二):非對稱加密

上篇文章,我們了解了關於對稱和非對稱加密的一些相關的理論知識,也學習了使用 OpenSSL 來進行對稱加密的操作。今天,我們就更進一步,學習 OpenSSL 中的非對稱加密是如何實現的。

生成私鑰

通過之前的學習,我們知道非對稱加密是分別需要一個公鑰和一個私鑰的。我們就先來生成一個私鑰,也就是存放在我們這一端一個密鑰。請記住,在任何時候,私鑰都是不能給別人的哦!

$config = array(
    "private_key_bits" => 4096, // 指定應該使用多少位來生成私鑰
);

$res = openssl_pkey_new($config); // 根據配置信息生成私鑰

openssl_pkey_export($res, $privateKey); // 將一個密鑰的可輸出表示轉換為字符串
var_dump($privateKey); 
// BEGIN PRIVATE KEY
// MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQDFMLW+9t3fNX4C
// YBuV0ILSyPAdSYVXtE4CLv32OvNk9yQZgF2nL/ZuIbBGRcYo2Hf5B31doGrAFDGu
// NoTR+WA7CBjKROFr/+yValsMFIeiKNtttWMkmBciysDJoEoyd6wjDD+kcHQdoJVo
// ……
// END PRIVATE KEY

非常簡單的一個函數 openssl_pkey_new() ,它接收一個參數,這個參數是可配置項並且是可選參數。生成的結果是一個私鑰句柄,不是我們能直接讀取的內容,所以我們再使用 openssl_pkey_export() 來提取可輸出的字符串。

注釋中的內容就是我們生成的私鑰信息了,私鑰信息一般會相對多些,所以省略了後面的內容。

抽取公鑰

接下來就是生成公鑰了,其實,公鑰是從私鑰中抽取出來的。所以我們使用進行加解密的時候,都可以使用私鑰或者公鑰互相操作。

$publicKey = openssl_pkey_get_details($res); // 抽取公鑰信息
var_dump($publicKey);
// array(4) {
//     ["bits"]=>
//     int(4096)
//     ["key"]=>
//     string(800) "BEGIN PUBLIC KEY
//   MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtOIImDdS0W0vAr5Ra1+E
//   hR2AJwQQwxntYKgTku8EmJRBX2vU+x8th8W8SnoGiVM/sOItG0HIe4Egf1UxoZHt
//   gI6r+jpAp7JbTN0sD/VTPDE09F21+hFGjIVBqrkcLPjuEbf7+tjmgAx8cG8WLGId
//   G8Hsub70kRANKJe1bCXIBUggRFk0sQGllxA/hxiG5wANqHTrdpJgJba+ahSi2+4H
//   UWnyCV1O3AaPyz6a12HNUsG4Eio/tWv/hOB9POt6nAqwPHuIbhp56i5bv1ijMJZM
//   jwRen5f/kwdZ01Ig2fi0uBoTR2y/EEaus7xBYpF/gGzZ/uM7cNUXcDyG5YluM/4R
//   MEv4msPMVGB72izItED+C6Cqftxl98iBFRDc+PISFbRSgOU/HsuBhKkM5SYzyi3I
//   Ypaej25++qLPqcA+EDr3JNDhNZ0GOhofCRtPq4dsr7iLLLRnZ0TnhIYe9wAbmO49
//   uthABNBkM54bG+omOfY4Bkn5n39CKpELbhIiXgOd+lA684XUS/2Aw3Dvelc9Gbag
//   oIFvb/wljPYsd0Zmd64CXBpTWbfwXC8K4vCKvFLjytcz2Yp4T6fVjbLT5RA6u8su
//   E0WwE4QTFNKhnM5OvfiMN+NMc3Y/esVfcin3eyvotdz4N6Tt45dkybkf6aQE3Scg
//   E/JBLIEEA+gjGTveY4cNUiECAwEAAQ==
//   END PUBLIC KEY
//   "
//     ["rsa"]=>
// ……

$publicKey = $publicKey['key'];

使用 openssl_pkey_get_details() 抽取出來的內容包含很多內容。不過我們所需要的最主要的內容就是 key 下面的這個公鑰。

大家再回過頭來好好看一下公鑰和私鑰的內容,是不是和我們去申請的 HTTPS 證書中的公私鑰內容長得一樣,而且也和我們自己在系統中使用 openssl 命令行生成的本機的密鑰證書一樣。它們本身就是一樣的東西啦,只是在不同的場景應用的不同而已。HTTPS 證書除了非對稱加密的密鑰之外,還包含有 CA 信息,如果 CA 不通過,瀏覽器也會認為證書是無效的,因此,我們使用自己生成的證書來充當 HTTPS 證書是不可以的。而本身生成的一般會用在 SSH 免密登錄上,或者是 GitHub 的免密代碼倉庫操作上。

加密解密數據

好了,公鑰和私鑰都生成完成了,那麼我們就要進行最重要的加密和解密操作了。

$data = '測試非對稱加密';

// 公鑰加密數據
openssl_public_encrypt($data, $encrypted, $publicKey);
var_dump($encrypted);
// string(512) "��E��2��~��\d����q�O�=(��Y���3L����0�,�J����s�V��V߬G~'�20���@��6�d�����#Z]�.��<Z��8G�����-ʝ�M�0](2��+$�*����\e�7ҕʴ��|SUw�#rFb�8"�s4K�B�Y�'�\S���~!<�"���!U��S(���S ��?e�֜r��/���c��L�YL�'ŖE*S��[�J�"�n��`(ʿoF$�|kC�*j_y�E�D�O����H5���6�t�TY����b5l^)�`�v�>�1��a��r�̹�D��������@�S�>�t|���匓�z~K�,���y��Gܬ��
//                                                              yXZ�L#��c `rj睅,nX���@{7�:�qy�ʲnv�o§�@�@,�n&���I�~ǧ�z6���oe!8,T�����;җ�6�J@A��f����S]��!����2�b��+Oګ��o�<�
//                                                                                                                                                                        ����-�+et��})�KG��$���,�Z|�"

// 私鑰解密數據
openssl_private_decrypt($encrypted, $decrypted, $privateKey);
var_dump($decrypted);
// string(21) "測試非對稱加密"

在這裡,我們使用的就是最標準的公鑰加密,私鑰解密來進行的測試。其實反過來也是可以的,OpenSSL 分別都為我們提供了公鑰的加解密和私鑰的加解密函數。

就像上篇文章的圖示那樣,對方獲得我們的公鑰,然後加密數據傳輸過來,我們通過自己的私鑰解密數據獲得原文。而我方也可以獲得對方的公鑰,並將返回的數據加密後傳輸給對方,然後對方使用自己的私鑰進行解密獲得我們傳遞給它的原文數據。

而 HTTPS 是通過 CA 頒發的證書來獲取公鑰的,瀏覽器通過公鑰加密請求數據傳輸給伺服器,伺服器也是通過相同的原理來向瀏覽器客戶端發送密文數據。因此,在數據傳輸過程中,使用 HTTPS 的傳輸會更加地安全,即使被截獲了,對方也沒有證書提供的密鑰來進行解密。這就是現在所有 App 和 小程序 應用都要求使用 HTTPS 的原因,當然,我們如果做網站開發也最好使用 HTTPS ,就連百度對 HTTPS 的收錄也有相應的調整。

籤名及驗證

接下來我們再接觸一個籤名的概念。當兩端進行通信時,我們怎麼知道當前傳輸過來的數據一定是對端發送過來的的呢,中間有沒有黑客進行了篡改呢?這個就可以通過籤名機制來進行驗證。

// 利用私鑰生成籤名
openssl_sign($data, $signature, $privateKey, OPENSSL_ALGO_SHA256);
var_dump($signature);
// ��<�~�k�٭N����M�тq��;��h�dŬ�Ğ�m�3�nj��/i���U�_�E2z���>B�N�WM!TN�c�F�/��,5�|���%��c~O)"
// ��      >��)y�fn��q��}
//                       �`
//                         �z��{��_D�s`�����|y�,g>R�D��%�
//                                                       �gͯ0�@Λ|��|z}���bZI2,����~Q_���I�LW~���G&���f�|eq�s�D���L���bC'D��~8:�Z����\�9]C�Kd~F96�S� 0��y>�(T��S}��1�謃T
//                                                                                                                                                                    �!��!!�Lj�<�ǺfM�o7�3��������� 8ZR<Vya4����V��Wט����L�QZbv��7?�v`}��?v ǿ�0`�OF��F��@�$b�PBI�o\�v���D���"

// 公鑰驗證籤名
$r = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256);
var_dump($r);
// int(1)

我們通過 openssl_sign() 來生成一個對原始數據的私鑰籤名,然後就可以使用 openssl_verify() 通過公鑰驗證數據籤名是否一致。

在使用的時候,發送方通過自己的私鑰生成籤名,由於籤名內容是亂碼的,我們可以將它 base64_encode() 一下,然後連同加密數據一起傳遞給接收方。然後接收方使用公鑰並根據籤名內容來驗證原文數據是否被篡改過。

// 發送方籤名
$resquestSign = base64_encode($signature);

// 假設通過網絡請求發送了數據
// ……
// 接收到獲得籤名及原始數據
// $signature = $_POST['sign'];
// openssl_private_decrypt($_POST['data'], $data, $privateKey); 

$responseSign = base64_decode($signature);
// 驗證數據有沒有被篡改
$r = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256);
var_dump($r);
// int(1)

// 假設被篡改
$data = '我被修改了';
$r = openssl_verify($data, $signature, $publicKey, OPENSSL_ALGO_SHA256);
var_dump($r);
// int(0)

總結

今天的內容是不是感覺比對稱加密複雜了許多。特別新引入的籤名的這個概念,其實很多證書相關的內容都會和數據籤名有關係。也就是說,看似簡單的一個 HTTPS ,其實瀏覽器和服務端的 openssl 幫我們做了很多事情,遠不止你去 CA 申請一套證書然後在 Nginx 配好那麼簡單。那麼,接下來,我們將要學習的就是生成證書相關的內容了,系好安全帶,車還要繼續飆。

測試代碼:

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%BA%8C%EF%BC%89%EF%BC%9A%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%8A%A0%E5%AF%86.php

參考文檔:

https://www.php.net/manual/zh/function.openssl-pkey-new.php

https://www.php.net/manual/zh/function.openssl-pkey-get-details.php

https://www.php.net/manual/zh/function.openssl-pkey-export.php

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

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

https://www.php.net/manual/zh/function.openssl-sign.php

https://www.php.net/manual/zh/function.openssl-verify.php

相關焦點

  • 常見三種加密:MD5、非對稱加密,對稱加密
    二、對稱加密簡介:對稱加密算法又稱傳統加密算法。加密和解密使用同一個密鑰。加密解密過程:明文->密鑰加密->密文,密文->密鑰解密->明文。三、非對稱加密RSA簡介:1. 對稱加密算法又稱現代加密算法。2. 非對稱加密是計算機通信安全的基石,保證了加密數據不會被破解。3.
  • 聊聊對稱加密、非對稱加密、Hash算法
    非對稱加密什麼是非對稱加密(Asymmetric Key Encryption)?常見的非對稱加密算法:RSA、ECC、Diffie-Hellman、El Gamal、DSA(數字籤名用)常用的非對稱加密:RSA、 ECC優點:安全高(幾乎很難破解)缺點:
  • 對稱加密和非對稱公鑰加密有什麼區別
    Asymmetric cryptography不對稱加密對稱密碼技術對稱密碼技術與凱撒密碼技術相同,用單個密鑰加密和解密數據。 為了更好地理解此過程,將此過程可視化為下圖如果使用對稱加密技術傳輸數據並確保其他人不會截取數據,則必須向接收者共享密鑰。 如果收件人住在附近,可以通過信封或其他線路直接傳遞密鑰,但如果收件人來自其他州或其他國家,該怎麼辦? 在這種情況下,發送密鑰的任務非常困難,因此需要另一種技術「非對稱加密」來克服這個問題。
  • 什麼是非對稱加密?
    豪華陣容的背後只有一個目的,就是使用強大的加密算法來保護個人信息和隱私免受攻擊。而非對稱加密算法也是比特幣存在的重要基石,中本聰在密碼學基礎之上用代碼創造了比特幣,將非對稱加密推向了一個嶄新的高潮。了解非對稱加密之前,我們先要理解什麼是對稱加密?
  • 加密算法科普:des、aes加密、對稱、非對稱加密、Hash算法都是啥
    加密算法導讀加密一般分為對稱加密(Symmetric Key Encryption)和非對稱加密(Asymmetric Key Encryption)常見的對稱加密算法:DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6 和 AES常見的非對稱加密算法:RSA、ECC (行動裝置用)、Diffie-Hellman、El Gamal、
  • 三分鐘了解對稱加密和非對稱加密是如何工作的?
    為了解決這個問題,就有了非對稱加密。非對稱加密( Asymmetric Cryptography )非對稱加密,又稱公鑰加密,它解決了對稱加密的缺陷,使得比特幣更安全。非對稱加密和對稱加密,兩者的主要區別在於:對稱加密使用共享(單一)密鑰加密解密數據,而非對稱加密使用密鑰對解密數據。如下圖所示,兩把鑰匙不同。
  • 現代密碼學核心——非對稱加密
    一路狂奔的密碼學,終於在上個世紀70年代中期迎來了它發展史上最重要的一刻:非對稱加密的出現。所謂非對稱,就是指加密和解密使用不同的密鑰。雖然這個協議實際上提出的是密鑰協商的算法,不支持加密和數字籤名,但由於它開創性地提出了使用不同密鑰的解決思路,人類終於可以實現非對稱加密了。兩位大神也因此貢獻獲得了2015年的圖靈獎。
  • 許多人搞不清的編碼、哈希、對稱加密以及非對稱加密算法的區別
    簡單地說,編碼算法是對二進位數據的一個呈現方式,是為了能讓人類更好識別枯燥的二進位數據,以及讓計算機能理解人類抽象的文字而制定的一套二進位與字符之間的轉換規則。(註:這裡的編碼特指數據編碼,而非圖片、音視頻等編碼算法。
  • 由MDUKEY 加密方式引申開:關於區塊鏈中常見的非對稱加密算法
    作為最優先級的事項,MDUKEY 存儲服務使用代理重加密、多層加密(應用層、網關層、文件系統層)等技術保護用戶隱私數據,並對用戶數據數據進行最小拆分,分布式存儲,減少數據大面積洩露 的風險,同時保證服務的高可用性。   而在數據安全的基礎上,MDUKEY 使用對稱加密與非對稱加密技術結合的加密方式,以及專業的加解密硬體,提高加解密的速率,保證服務的高吞吐量。
  • 非對稱加密的逆應用——數字籤名
    數字籤名實際是非對稱加密算法的另一項主要應用領域,數字籤名本身並沒有引入任何新的技術,但它比加解密應用的更加普遍。加解密解決了信息的保密性問題,因為只有有密鑰的用戶才能解密密文;而數字籤名解決了信息來源真實性的問題,即這個信息是誰發出的,從發出到接收的過程中有沒有被篡改過。
  • 加密類型:5種加密算法以及如何選擇正確的算法
    在本文中,我們將學習對稱和非對稱加密及其用於加密數據的流行加密算法。讓我們對其進行哈希處理。加密類型1:對稱加密顧名思義,對稱加密方法使用單個加密密鑰來加密和解密數據。對這兩個操作使用單個鍵使其成為一個簡單的過程,因此稱為「對稱」。
  • 非對稱加密是什麼?
    區塊鏈主要應用的密碼學算法有兩個部分:一個哈希算法,另一個是非對稱加密。 簡單來說,哈希算法就是一種特殊的函數,不論輸入多長的一串字符,只要通過這個函數都可以得到一個固定長度的輸出值,這就好像身份證號碼一樣,永遠都是十八位而且全國唯一。哈希算法的輸出值就叫做哈希值。
  • 五一科普之:常用加密算法一覽!
    不是嚇唬大家,信息是透明的兄die,不過也要儘量去維護個人的隱私吧,今天學習對稱加密和非對稱加密。大家先讀讀這個字"鑰",是讀"yao",還是讀"yue"。看下圖一 、對稱加密對稱加密,顧名思義,加密方與解密方使用同一鑰匙(密鑰)。
  • 常見加密算法DES、AES和RSA的原理和特點
    本文轉載自【微信公眾號:strongerHuang,ID:strongerHuang】經微信公眾號授權轉載,如需轉載與原文作者聯繫主要總結下常用的對稱性加密算法DES和AES,非對稱性加密算法RSA。2AES加密算法1.AES含義AES,高級加密標準,在密碼學中又稱Rijndael加密法,是美國聯邦政府採用的一種區塊加密標準。這個標準用來替代原先的DES,已經被多方分析且廣為全世界所使用。
  • 色情網站的光棍節「福利」:加密式掛馬玩轉流氓推廣
    .*.96.42/index.php?id=011:主要功能:每次伺服器都會生成一個隨機的validate值放入表單中,這個值每次刷新得到的結果都不一樣,通過這個值作為瀏覽器的會話標記。id=49457這個頁面會根據ID返回Rabbit或者RC4的加密後的Load代碼,頁面載入了額外的兩個js庫文件(encrypt.min.js、tinyjs.min.js),提供相關的對稱和非對稱加密算法。
  • 常見的幾種加密算法比較
    二、數據加密的應用1.媒體加密:DRM2.文件加密:文本加密、pdf、word3.數據加密:ASP.NET(C#)中的數據加密4.硬體加密:加密狗三、加密技術發展趨勢①私用密鑰加密技術與公開密鑰加密技術相結合:鑑於兩種密碼體制加密的特點,在實際應用中可以採用折衷方案
  • DES、RC4、AES等加密算法優勢及應用
    程式設計師捍衛自己珍貴的代碼,全靠花式的加密算法。代碼加密有多重要?程式設計師半年做出的產品,盜版者可能半天就能完全破解。  加密算法的本質,首先是為了對數據進行保密並防止篡改,其次更具有了身份驗證的功能。像是你跟女友約定好的話術,這句話一說出來,她就知道是什麼意思,並且知道說話的人是你,但任何其他人根本不知道你們在說什麼。  根據密鑰類型的不同,加密算法分為對稱和非對稱兩種。
  • 談談區塊鏈的加密技術(公鑰、私鑰)
    2.非對稱加密(Asymmetric cryptography)非對稱加密指為滿足安全性需求和所有權驗證需求而集成到區塊鏈中的加密技術。它和對稱加密的主要區別是:對稱加密使用共享密鑰來解密數據,而非對稱加密使用「密鑰對」來解密數據。密鑰對包含兩部分:一個公鑰,一個私鑰。舉個例子,當你給你媽的銀行卡轉錢時,需要知道她的銀行卡帳號,那麼這個帳號就相當於她的公鑰,是公開可見的。私鑰就相當於是她的密碼,在沒有告訴你密碼的情況下只她自己知道帳戶裡的資金情況。
  • 加密風險:數據安全盲點
    證書、加密密鑰及其用於保護數據的算法已成為越來越多討論的一部分:加密風險或者稱為數據風險。什麼是加密風險?加密風險用於表示通過加密手段數據的保護程度的度量標準。但是,許多企業組織沒有一套有效的工具來衡量其數據受到加密保護的程度。換句話說,當前沒有一種衡量加密風險的適當方法。為了推動數據安全科學的發展,創建一種加密風險的標準,該標準應考慮到所有導致加密數據脆弱性的因素。
  • 用C 語言描述AES256 加密算法
    秘鑰長度決定加密或解密數據所需的處理步驟數。顧名思義,塊密碼算法採用的是數據塊。AES 算法一次處理 16 字節的固定模塊。因此,如果我們密碼內容少於 16 字節,就必須將未使用的字節進行填充。由於 AES 是對稱密碼,信息加密和解密都採用相同的做法和秘鑰。相反,非對稱算法(例如RSA)則使用不同秘鑰進行數據加密和解密。AES 算法中四個階段中每個階段都代表一個狀態。