前言
隨着互聯網越來越滲透入我們生活的方方面面,各種私密信息在網絡中傳播,為了保證信息的真實可靠,在我們對其安全性的要求也越來越高,對此,加密是一個永遠不過時的話題。非對稱加密,全站HTTPS等,深入了解,總會遇到RSA加密算法。在一些特殊行業,如博主工作的互聯網金融,RSA加密算法的重要性更是非同一般。
可能由於密碼學的枯燥,還有加密各種標准的混雜,加密與解密難以測試與驗證,再加上大公司有大牛寫框架,小公司多用demo,網上有關加密的知識不是很多,一開始嘗試了解比較困難,所以我總結一下最近學習的一些知識,希望能幫到需要的人。
由於RSA算法原理牽涉到的都是些數學知識,作為一個數學渣,不拿出來誤導別人了。有感興趣的,可以看一下阮一峰大神的博客:RSA算法原理
以前寫過一篇PHP使用openssl擴展的博客:PHP的openssl加密擴展使用小結,講了一些加密基礎和PHP中如何進行加密。本文主要聊一聊非對稱加密的相關知識、RSA加密算法的數字證書操作,也會附帶一些其他相關知識和使用心得。如文章有錯漏之處,煩請指出,謝謝。
數字證書
公鑰傳輸問題
在密文傳輸過程中,客戶端(Client C)向服務器(Server S)發送數據,C使用S的公鑰加密,這樣只有S使用自己的私鑰解密才能拿到信息,其他人即使得到了數據,沒有S的私鑰也沒用。
但是如果有一個黑客H告訴C自己是S,並將自己的假公鑰發送給C,那么C用假公鑰加密數據並將數據發送給了H,那么H就順利得到了信息,無法起到數據加密的作用。
這就需要一個中間人來頒發一個身份證明來證明S是真的S。
數字證書認證中心
這個中間人就是數字證書認證機構。
數字證書認證中心(Certificate Authority)(也被稱為證書認證機構或CA)是指頒發證書、廢除證書、更新證書、驗證證書、管理密鑰的機構。它能在認證某組織或個人后分發證書的機構,它驗證的信息包括已簽約的證書,當然它也負責吊銷有危害的證書。
數字證書
中間人頒發的身份證明就是數字證書。
數字證書是一個包含 證書擁有者公鑰、證書擁有者信息、證書認證中心數字簽名的文件。 拿到數字證書后,我們解析證書的證書認證機構數字簽名確保證書是真的,且沒有被篡改過后,取得其中的公鑰,然后就可以使用此公鑰與瀏覽器進行交互了。
根證書
CA 這么重要,可是怎么能證明 CA 是真的呢?這個不用擔心,許多 CA 都有嵌入在瀏覽器中的根證書,所以瀏覽器能自動識別它們。在一些API交互中,如請求支付寶的接口時,我們已經在本地存儲了支付寶的證書了。
不用擔心本地的根證書安全問題,如果本地存儲的根證書都被修改了,那么加解密也就沒有什么意義了。
證書鏈
由於世界上需要證書的組織眾多,任何一家 CA 也不能處理全部的認證請求。於是大大小小的 CA 出現了,可是每個客戶端不可能把他們的證書作為根證書全存儲起來。
於是CA建立自上而下的信任鏈,下級 CA 信任上級 CA,下級 CA 由上級 CA 頒發證書並認證。因為下級 CA 的證書是用上級 CA 的密鑰加密的,而上級 CA 的密鑰只有自己知道,因此別人無法冒充上級 CA 給別人發證書。
在進行證書認證時,服務器會發給客戶端一個包含着“證書機構證書”的證書,會層層鏈接到最上層的 CA,我們本地擁有最上級的 CA 的證書,如果能證明此 CA 的真實性,那么也便能證明服務器證書的可靠。
證書標准
X.509是目前最能用的證書標准, 證書由用戶公共密鑰和用戶標識符組成。此外還包括版本號、證書序列號、CA標識符、簽名算法標識、簽發者名稱、證書有效期等信息。這一標准的最新版本是X.509 v3,它定義了包含擴展信息的數字證書。該版數字證書提供了一個擴展信息字段,用來提供更多的靈活性及特殊應用環境下所需的信息傳送。
RSA加密標准
公鑰加密標准
公鑰加密標准(Public Key Cryptography Standards, PKCS),此系列標准的設計與發布皆由RSA信息安全公司所制定。包括證書申請、證書更新、證書作廢表發布、擴展證書內容以及數字簽名、數字信封的格式等方面的一系列相關協議。
目前在使用的最高版本為 PKCS#12,這版本也是我工作中使用最多的版本,此外我還接觸過 PKCS#7 版本,java多用 PKCS#8 版本,下面分別說一下。
PKCS#7:
定義一種通用的消息語法,包括數字簽名和加密等用於增強的加密機制,PKCS#7與PEM兼容,所以不需其他密碼操作,就可以將加密的消息轉換成PEM消息。規范了以公開密鑰基礎設施(PKI)所產生之簽名/密文之格式。其拓展數字證書在 S/MIME與CMS 的應用,PKCS#7一般主要用來做數字信封。
PKCS#8
描述私有密鑰信息格式,該信息包括公開密鑰算法的私有密鑰以及可選的屬性集等,Apache讀取證書私鑰的標准,在JAVA平台中使用。(接入一些支付公司中經常會提供此格式的密鑰,有些印象)
PKCS#12:
描述個人信息交換語法標准。描述了將用戶公鑰、私鑰、證書和其他相關信息打包的語法。 含有私鑰,同時可以有公鑰,有口令保護 格式一般為 .pfx
。 由於它可以加密碼保護,打開時需要一串特殊密碼,所以相對安全些。
證書和密鑰文件格式
需要注意:證書文件格式與加密標准並沒有嚴格的對應關系,證書文件格式是存儲證書的方式不同,可能存儲的內容也略有不同。而加密標准是使用證書文件進行加解密的方式不同。
pem格式
最普通的證書格式,以-----BEGIN CERTIFICATE-----
開頭,以-----END CERTIFICATE-----
結尾;有些pem證書把私鑰也放在了一個文件中,但是很多平台還是需求證書和私鑰分開放在不同的文件中。 pem證書有以下特點:
- base64編碼;
- 有.pem, .crt, .cer, .key文件后綴;
- Apache等類似服務器使用pem格式證書;
der格式
der格式是pem格式證書的二進制格式,證書和私鑰都可以以der格式存儲。 其特點為:
- 二進制格式;
- 以.cer或.der格式為后綴;
- 常被用於java平台;
PKCS#7格式
它是一種PKCS#7格式以-----BEGIN PKCS-----
開頭,以-----END PKCS7-----
結尾,它只能保存證書或證書鏈,不能保存私鑰。 其特點為:
- base64編碼;
- 文件后綴為 .p7p, .p7c;
- window或java tomcat等平台支持此類型;
PKCS#12(pfx)格式
它能把服務器證書(包括公鑰),中間證書和私鑰存儲在一起。特點為:
- 二進制文檔;
- 以 .pfx 或.p12為后綴;
- 經常在windows系統內被用於導入導出證書和私鑰;
- 打開可能需要額外密碼;
密鑰的保存
對於密鑰(單指公私鑰)的保存,並不需要特殊的格式,直接將base64編碼后的密鑰作為字符串存入文檔即可。
RSA加密操作
密鑰生成和使用
openssl genrsa -out rsa_private_key.pem 1024 // 生產一個1024位的私鑰, 保存在 rsa_private_key.pem 文件里
openssl rsa -in rsa_private_key.pem -pubout -out pub.pem // 通過私鑰生產公鑰
此外,介紹一下openssl提供的一個測試加密速度的小工具,可以查看一定時間內某算法計算的次數,讓我們對各種加密算法的速度有一個大概的認識。
openssl speed algciper
eg: openssl speed rsa1024
openssl speed des-ede3
格式轉換
從pfx文件中提取公私鑰
openssl pkcs12 -in source.pfx -nocerts -nodes -out key.key // 從pfx文件中獲取到密匙對文件,有時會需要密碼
opensll rsa -in key.key -out pri.key // 從密匙對文件中獲取到私匙。
opensll rsa -in key.key -pubout -out pub.key // 從密匙對文件中獲取到公匙;
openssl pkcs8 -in pri.key -out repri.key -outform der -nocrypt -topk8 //java語言用
各種證書之間的互相轉換
PEM to DER
openssl x509 -outform der -in certificate.pem -out certificate.der
—————————————————————————————————–
PEM to P7B
openssl crl2pkcs7 -nocrl -certfile certificate.cer -out certificate.p7b -certfile CAcert.cer
———————————————————————————————————————————-
PEM to PFX
openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CAcert.crt
——————————————————————————————————————————————————
DER to PEM
openssl x509 -inform der -in certificate.cer -out certificate.pem
————————————————————————————————
P7B to PEM
openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
————————————————————————————————-
P7B to PFX
openssl pkcs7 -print_certs -in certificate.p7b -out certificate.cer
openssl pkcs12 -export -in certificate.cer -inkey privateKey.key -out certificate.pfx -certfile CAcert.cer
——————————————————————————————————————————————————-
PFX to PEM
openssl pkcs12 -in certificate.pfx -out certificate.cer -nodes
PHP中使用RSA
作為一個PHPer,當然還要提一下在 PHP 中如何使用 RSA 加密,所用工具依然是強大的openssl擴展:
# 從pfx文件中提取私鑰和證書(需要傳入密碼 $password):
openssl_pkcs12_read($file_content, $key, $password);
$key['pkey'] => 私鑰
$key['cert'] => 證書
# 解析x.509證書
openssl_x509_read($cert);
# 以pkcs7加密標准加解密/簽名驗簽數據:需要注意pkcs7操作都需要使用一個臨時文件,多進程時要考慮一下文件沖突問題,還有別忘了最后釋放臨時文件。
openssl_pkcs7_encrypt()/openssl_pkcs7_decrypt()
openssl_pkcs7_sign()/openssl_pkcs7_verify()
# 從字符串中獲取公私鑰:
openssl_pkey_get_private()/openssl_pkey_get_public()
# RSA以pkcs#12標准加解密/簽名驗簽數據:
openssl_private(public)_encrypt()/openssl_private(public)_decrypt()
小結
最后不得不吐槽一下各種不統一標准的支付公司,可能由於系統老,有各種各樣的奇葩的加解密要求。。。 不像支付寶和微信這種大平台,純純的 RSA 操作,使用起來非常方便。希望跟我以前一樣飽受加解密折磨,最后還一頭霧水的看官能通過此文有所收獲。
隨着硬件的快速發展,加解密帶來的資源消耗已經越來越微不足道了,我相信不僅是金融等行業,對其他IT行業來說,加解密特別是非對稱加密也一定會越來越重要,有備無患嘛。
最后,如果您覺得此文對您稍有幫助,可以點擊下方推薦。持續更新,歡迎關注。
參考: