詳解 RSA 非對稱加密

前言

隨着互聯網越來越滲透入我們生活的方方面面,各種私密信息在網絡中傳播,爲了保證信息的真實可靠,在我們對其安全性的要求也越來越高,對此,加密是一個永遠不過時的話題。非對稱加密,全站 HTTPS 等,深入瞭解,總會遇到 RSA 加密算法。在一些特殊行業,如博主工作的互聯網金融,RSA 加密算法的重要性更是非同一般。

可能由於密碼學的枯燥,還有加密各種標準的混雜,加密與解密難以測試與驗證,再加上大公司有大牛寫框架,小公司多用 demo,網上有關加密的知識不是很多,一開始嘗試瞭解比較困難,所以我總結一下最近學習的一些知識,希望能幫到需要的人。

由於 RSA 算法原理牽涉到的都是些數學知識,作爲一個數學渣,不拿出來誤導別人了。有感興趣的,可以看一下阮一峯大神的博客:RSA 算法原理

www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html

以前寫過一篇 PHP 使用 openssl 擴展的博客:PHP 的 openssl 加密擴展使用小結

zhenbianshu.github.io/2016/07/php_openssl.html

講了一些加密基礎和 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 證書有以下特點:

der 格式

der 格式是 pem 格式證書的二進制格式,證書和私鑰都可以以 der 格式存儲。 其特點爲:

PKCS#7 格式

它是一種 PKCS#7 格式以-----BEGIN PKCS-----開頭,以-----END PKCS7-----結尾,它只能保存證書或證書鏈,不能保存私鑰。 其特點爲:

PKCS#12(pfx)格式

它能把服務器證書(包括公鑰),中間證書和私鑰存儲在一起。特點爲:

密鑰的保存

對於密鑰(單指公私鑰)的保存,並不需要特殊的格式,直接將 base64 編碼後的密鑰作爲字符串存入文檔即可。

RSA 加密操作

密鑰生成和使用

#生產一個1024位的私鑰, 保存在 rsa_private_key.pem 文件裏
openssl genrsa -out rsa_private_key.pem 1024
#通過私鑰生產公鑰
openssl rsa -in rsa_private_key.pem -pubout -out pub.pem

此外,介紹一下 openssl 提供的一個測試加密速度的小工具,可以查看一定時間內某算法計算的次數,讓我們對各種加密算法的速度有一個大概的認識。

openssl speed algciper
eg: openssl speed rsa1024
    openssl speed des-ede3

格式轉換

從 pfx 文件中提取公私鑰

#從pfx文件中獲取到密匙對文件,有時會需要密碼
openssl pkcs12 -in source.pfx -nocerts -nodes -out key.key 
#從密匙對文件中獲取到私匙。
opensll rsa -in key.key -out pri.key 
#從密匙對文件中獲取到公匙;
opensll rsa -in key.key -pubout -out pub.key 
#java語言用
openssl pkcs8 -in pri.key -out repri.key -outform der -nocrypt -topk8

各種證書之間的互相轉換

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 行業來說,加解密特別是非對稱加密也一定會越來越重要,有備無患嘛。

source: //zhenbianshu.github.io/2017/01/understand_and_use_rsa.html
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/PC3Yngf3U-bSUhbDpdcVJw