想要入門(mén)密碼學(xué)的基礎(chǔ)知識(shí),尤其是有關(guān) OpenSSL 的入門(mén)知識(shí)嗎?
本文是使用 OpenSSL 的密碼學(xué)基礎(chǔ)知識(shí)的兩篇文章中的第一篇,OpenSSL 是在 Linux 和其他系統(tǒng)上流行的生產(chǎn)級(jí)庫(kù)和工具包。(要安裝 OpenSSL 的最新版本,請(qǐng)參閱 這里 。)OpenSSL 實(shí)用程序可在命令行使用,程序也可以調(diào)用 OpenSSL 庫(kù)中的函數(shù)。本文的示例程序使用的是 C語(yǔ)言,即 OpenSSL 庫(kù)的源語(yǔ)言。
本系列的兩篇文章涵蓋了加密哈希、數(shù)字簽名、加密和解密以及數(shù)字證書(shū)。你可以從 我的網(wǎng)站 的 ZIP 文件中找到這些代碼和命令行示例。
讓我們首先回顧一下 OpenSSL 名稱中的 SSL。
OpenSSL 簡(jiǎn)史
安全套接字層 (Secure Socket Layer)(SSL)是 Netscape 在 1995 年發(fā)布的一種加密協(xié)議。該協(xié)議層可以位于 HTTP 之上,從而為 HTTPS 提供了 S: 安全(secure)。SSL 協(xié)議提供了各種安全服務(wù),其中包括兩項(xiàng)在 HTTPS 中至關(guān)重要的服務(wù):
對(duì)等身份驗(yàn)證(Peer authentication)(也稱為相互質(zhì)詢):連接的每一邊都對(duì)另一邊的身份進(jìn)行身份驗(yàn)證。如果 Alice 和 Bob 要通過(guò) SSL 交換消息,則每個(gè)人首先驗(yàn)證彼此的身份。
機(jī)密性(Confidentiality):發(fā)送者在通過(guò)通道發(fā)送消息之前先對(duì)其進(jìn)行加密。然后,接收者解密每個(gè)接收到的消息。此過(guò)程可保護(hù)網(wǎng)絡(luò)對(duì)話。即使竊聽(tīng)者 Eve 截獲了從 Alice 到 Bob 的加密消息(即中間人攻擊),Eve 會(huì)發(fā)現(xiàn)他無(wú)法在計(jì)算上解密此消息。
反過(guò)來(lái),這兩個(gè)關(guān)鍵 SSL 服務(wù)與其他不太受關(guān)注的服務(wù)相關(guān)聯(lián)。例如,SSL 支持消息完整性,從而確保接收到的消息與發(fā)送的消息相同。此功能是通過(guò)哈希函數(shù)實(shí)現(xiàn)的,哈希函數(shù)也隨 OpenSSL 工具箱一起提供。
SSL 有多個(gè)版本(例如 SSLv2 和 SSLv3),并且在 1999 年出現(xiàn)了一個(gè)基于 SSLv3 的類似協(xié)議 傳輸層安全性(Transport Layer Security)(TLS)。TLSv1 和 SSLv3 相似,但不足以相互配合工作。不過(guò),通常將 SSL/TLS 稱為同一協(xié)議。例如,即使正在使用的是 TLS(而非 SSL),OpenSSL 函數(shù)也經(jīng)常在名稱中包含 SSL。此外,調(diào)用 OpenSSL 命令行實(shí)用程序以 openssl 開(kāi)始。
除了 man 頁(yè)面之外,OpenSSL 的文檔是零零散散的,鑒于 OpenSSL 工具包很大,這些頁(yè)面很難以查找使用。命令行和代碼示例可以將主要主題集中起來(lái)。讓我們從一個(gè)熟悉的示例開(kāi)始(使用 HTTPS 訪問(wèn)網(wǎng)站),然后使用該示例來(lái)選出我們感興趣的加密部分進(jìn)行講述。
一個(gè) HTTPS 客戶端
此處顯示的 client 程序通過(guò) HTTPS 連接到 Google:
/* compilation: gcc -o client client.c -lssl -lcrypto */#include
可以從命令行編譯和執(zhí)行該程序(請(qǐng)注意 -lssl 和 -lcrypto 中的小寫(xiě)字母 L):
gcc -o client client.c -lssl -lcrypto
該程序嘗試打開(kāi)與網(wǎng)站 www.google.com 的安全連接。在與 Google Web 服務(wù)器的 TLS 握手過(guò)程中,client 程序會(huì)收到一個(gè)或多個(gè)數(shù)字證書(shū),該程序會(huì)嘗試對(duì)其進(jìn)行驗(yàn)證(但在我的系統(tǒng)上失敗了)。盡管如此,client 程序仍繼續(xù)通過(guò)安全通道獲取 Google 主頁(yè)。該程序取決于前面提到的安全工件,盡管在上述代碼中只著重突出了數(shù)字證書(shū)。但其它工件仍在幕后發(fā)揮作用,稍后將對(duì)它們進(jìn)行詳細(xì)說(shuō)明。
通常,打開(kāi) HTTP(非安全)通道的 C 或 C++ 的客戶端程序?qū)⑹褂弥T如文件描述符或網(wǎng)絡(luò)套接字之類的結(jié)構(gòu),它們是兩個(gè)進(jìn)程(例如,這個(gè) client 程序和 Google Web 服務(wù)器)之間連接的端點(diǎn)。另一方面,文件描述符是一個(gè)非負(fù)整數(shù)值,用于在程序中標(biāo)識(shí)該程序打開(kāi)的任何文件類的結(jié)構(gòu)。這樣的程序還將使用一種結(jié)構(gòu)來(lái)指定有關(guān) Web 服務(wù)器地址的詳細(xì)信息。
這些相對(duì)較低級(jí)別的結(jié)構(gòu)不會(huì)出現(xiàn)在客戶端程序中,因?yàn)?OpenSSL 庫(kù)會(huì)將套接字基礎(chǔ)設(shè)施和地址規(guī)范等封裝在更高層面的安全結(jié)構(gòu)中。其結(jié)果是一個(gè)簡(jiǎn)單的 API。下面首先看一下 client 程序示例中的安全性詳細(xì)信息。
該程序首先加載相關(guān)的 OpenSSL 庫(kù),我的函數(shù) init_ssl 中對(duì) OpenSSL 進(jìn)行了兩次調(diào)用:SSL_load_error_strings();
SSL_library_init();
下一個(gè)初始化步驟嘗試獲取安全上下文,這是建立和維護(hù)通往 Web 服務(wù)器的安全通道所需的信息框架。如對(duì) OpenSSL 庫(kù)函數(shù)的調(diào)用所示,在示例中使用了 TLS 1.2:const SSL_METHOD* method = TLSv1_2_client_method(); /* TLS 1.2 */
如果調(diào)用成功,則將 method 指針被傳遞給庫(kù)函數(shù),該函數(shù)創(chuàng)建類型為 SSL_CTX 的上下文:SSL_CTX* ctx = SSL_CTX_new(method);
client 程序會(huì)檢查每個(gè)關(guān)鍵的庫(kù)調(diào)用的錯(cuò)誤,如果其中一個(gè)調(diào)用失敗,則程序終止。
現(xiàn)在還有另外兩個(gè) OpenSSL 工件也在發(fā)揮作用:SSL 類型的安全會(huì)話,從頭到尾管理安全連接;以及類型為 BIO( 基本輸入/輸出(Basic Input/Output))的安全流,用于與 Web 服務(wù)器進(jìn)行通信。BIO 流是通過(guò)以下調(diào)用生成的:
BIO* bio = BIO_new_ssl_connect(ctx);
請(qǐng)注意,這個(gè)最重要的上下文是其參數(shù)。BIO 類型是 C 語(yǔ)言中 FILE 類型的 OpenSSL 封裝器。此封裝器可保護(hù) client 程序與 Google 的網(wǎng)絡(luò)服務(wù)器之間的輸入和輸出流的安全。
有了 SSL_CTX 和 BIO,然后程序在 SSL 會(huì)話中將它們組合在一起。三個(gè)庫(kù)調(diào)用可以完成工作:
BIO_get_ssl(bio, &ssl); /* 會(huì)話 */
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* 魯棒性 */
BIO_set_conn_hostname(bio, name); /* 準(zhǔn)備連接 */
安全連接本身是通過(guò)以下調(diào)用建立的:
BIO_do_connect(bio);
如果最后一個(gè)調(diào)用不成功,則 client 程序終止;否則,該連接已準(zhǔn)備就緒,可以支持 client 程序與 Google Web 服務(wù)器之間的機(jī)密對(duì)話。
在與 Web 服務(wù)器握手期間,client 程序會(huì)接收一個(gè)或多個(gè)數(shù)字證書(shū),以認(rèn)證服務(wù)器的身份。但是,client 程序不會(huì)發(fā)送自己的證書(shū),這意味著這個(gè)身份驗(yàn)證是單向的。(Web 服務(wù)器通常配置為不需要客戶端證書(shū))盡管對(duì) Web 服務(wù)器證書(shū)的驗(yàn)證失敗,但 client 程序仍通過(guò)了連接到 Web 服務(wù)器的安全通道繼續(xù)獲取 Google 主頁(yè)。
為什么驗(yàn)證 Google 證書(shū)的嘗試會(huì)失?。康湫偷?OpenSSL 安裝目錄為 /etc/ssl/certs,其中包含 ca-certificates.crt 文件。該目錄和文件包含著 OpenSSL 自帶的數(shù)字證書(shū),以此構(gòu)成 信任庫(kù)(truststore)??梢愿鶕?jù)需要更新信任庫(kù),尤其是可以包括新信任的證書(shū),并刪除不再受信任的證書(shū)。
client 程序從 Google Web 服務(wù)器收到了三個(gè)證書(shū),但是我的計(jì)算機(jī)上的 OpenSSL 信任庫(kù)并不包含完全匹配的證書(shū)。如目前所寫(xiě),client 程序不會(huì)通過(guò)例如驗(yàn)證 Google 證書(shū)上的數(shù)字簽名(一個(gè)用來(lái)證明該證書(shū)的簽名)來(lái)解決此問(wèn)題。如果該簽名是受信任的,則包含該簽名的證書(shū)也應(yīng)受信任。盡管如此,client 程序仍繼續(xù)獲取頁(yè)面,然后打印出 Google 的主頁(yè)。下一節(jié)將更詳細(xì)地介紹這些。
客戶端程序中隱藏的安全性
讓我們從客戶端示例中可見(jiàn)的安全工件(數(shù)字證書(shū))開(kāi)始,然后考慮其他安全工件如何與之相關(guān)。數(shù)字證書(shū)的主要格式標(biāo)準(zhǔn)是 X509,生產(chǎn)級(jí)的證書(shū)由諸如 Verisign 的 證書(shū)頒發(fā)機(jī)構(gòu)(Certificate Authority)(CA)頒發(fā)。
數(shù)字證書(shū)中包含各種信息(例如,激活日期和失效日期以及所有者的域名),也包括發(fā)行者的身份和數(shù)字簽名(這是加密過(guò)的加密哈希值)。證書(shū)還具有未加密的哈希值,用作其標(biāo)識(shí)指紋。
哈希值來(lái)自將任意數(shù)量的二進(jìn)制位映射到固定長(zhǎng)度的摘要。這些位代表什么(會(huì)計(jì)報(bào)告、小說(shuō)或數(shù)字電影)無(wú)關(guān)緊要。例如, 消息摘要版本 5(Message Digest version 5)(MD5)哈希算法將任意長(zhǎng)度的輸入位映射到 128 位哈希值,而 SHA1( 安全哈希算法版本 1(Secure Hash Algorithm version 1))算法將輸入位映射到 160 位哈希值。不同的輸入位會(huì)導(dǎo)致不同的(實(shí)際上在統(tǒng)計(jì)學(xué)上是唯一的)哈希值。下一篇文章將會(huì)進(jìn)行更詳細(xì)的介紹,并著重介紹什么使哈希函數(shù)具有加密功能。
數(shù)字證書(shū)的類型有所不同(例如根證書(shū)、中間證書(shū)和最終實(shí)體證書(shū)),并形成了反映這些證書(shū)類型的層次結(jié)構(gòu)。顧名思義,根證書(shū)位于層次結(jié)構(gòu)的頂部,其下的證書(shū)繼承了根證書(shū)所具有的信任。OpenSSL 庫(kù)和大多數(shù)現(xiàn)代編程語(yǔ)言都具有 X509 數(shù)據(jù)類型以及處理此類證書(shū)的函數(shù)。來(lái)自 Google 的證書(shū)具有 X509 格式,client 程序會(huì)檢查該證書(shū)是否為 X509_V_OK。
X509 證書(shū)基于 公共密鑰基礎(chǔ)結(jié)構(gòu)(public-key infrastructure)(PKI),其中包括的算法(RSA 是占主導(dǎo)地位的算法)用于生成密鑰對(duì):公共密鑰及其配對(duì)的私有密鑰。公鑰是一種身份: Amazon 的公鑰對(duì)其進(jìn)行標(biāo)識(shí),而我的公鑰對(duì)我進(jìn)行標(biāo)識(shí)。私鑰應(yīng)由其所有者負(fù)責(zé)保密。
成對(duì)出現(xiàn)的密鑰具有標(biāo)準(zhǔn)用途??梢允褂霉€對(duì)消息進(jìn)行加密,然后可以使用同一個(gè)密鑰對(duì)中的私鑰對(duì)消息進(jìn)行解密。私鑰也可以用于對(duì)文檔或其他電子工件(例如程序或電子郵件)進(jìn)行簽名,然后可以使用該對(duì)密鑰中的公鑰來(lái)驗(yàn)證簽名。以下兩個(gè)示例補(bǔ)充了一些細(xì)節(jié)。
在第一個(gè)示例中,Alice 將她的公鑰分發(fā)給全世界,包括 Bob。然后,Bob 用 Alice 的公鑰加密郵件,然后將加密的郵件發(fā)送給 Alice。用 Alice 的公鑰加密的郵件將可以用她的私鑰解密(假設(shè)是她自己的私鑰),如下所示:
+------------------+ encrypted msg+-------------------+Bob's msg--->|Alice's public key|--------------->|Alice's private key|---> Bob's msg +------------------++-------------------+
理論上可以在沒(méi)有 Alice 的私鑰的情況下解密消息,但在實(shí)際情況中,如果使用像 RSA 這樣的加密密鑰對(duì)系統(tǒng),則在計(jì)算上做不到。
現(xiàn)在,第二個(gè)示例,請(qǐng)對(duì)文檔簽名以證明其真實(shí)性。簽名算法使用密鑰對(duì)中的私鑰來(lái)處理要簽名的文檔的加密哈希:
+-------------------+Hash of document--->|Alice's private key|--->Alice's digital signature of the document+-------------------+
假設(shè) Alice 以數(shù)字方式簽署了發(fā)送給 Bob 的合同。然后,Bob 可以使用 Alice 密鑰對(duì)中的公鑰來(lái)驗(yàn)證簽名:
+------------------+Alice's digital signature of the document--->|Alice's public key|--->verified or not +------------------+
假若沒(méi)有 Alice 的私鑰,就無(wú)法輕松偽造 Alice 的簽名:因此,Alice 有必要保密她的私鑰。
在 client 程序中,除了數(shù)字證書(shū)以外,這些安全性都沒(méi)有明確展示。下一篇文章使用使用 OpenSSL 實(shí)用程序和庫(kù)函數(shù)的示例填充更多詳細(xì)的信息。
命令行的 OpenSSL
同時(shí),讓我們看一下 OpenSSL 命令行實(shí)用程序:特別是在 TLS 握手期間檢查來(lái)自 Web 服務(wù)器的證書(shū)的實(shí)用程序。調(diào)用 OpenSSL 實(shí)用程序可以使用 openssl 命令,然后添加參數(shù)和標(biāo)志的組合以指定所需的操作。
看看以下命令:
openssl list-cipher-algorithms
該輸出是組成 加密算法套件(cipher suite)()的相關(guān)算法的列表。下面是列表的開(kāi)頭,加了澄清首字母縮寫(xiě)詞的注釋:
AES-128-CBC ## Advanced Encryption Standard, Cipher Block ChainingAES-128-CBC-HMAC-SHA1 ## Hash-based Message Authentication Code with SHA1 hashesAES-128-CBC-HMAC-SHA256 ## ditto, but SHA256 rather than SHA1...
下一條命令使用參數(shù) s_client 將打開(kāi)到 www.google.com 的安全連接,并在屏幕上顯示有關(guān)此連接的所有信息:
openssl s_client -connect www.google.com:443 -showcerts
端口號(hào) 443 是 Web 服務(wù)器用于接收 HTTPS(而不是 HTTP 連接)的標(biāo)準(zhǔn)端口號(hào)。(對(duì)于 HTTP,標(biāo)準(zhǔn)端口為 80)Web 地址 www.google.com:443 也出現(xiàn)在 client 程序的代碼中。如果嘗試連接成功,則將顯示來(lái)自 Google 的三個(gè)數(shù)字證書(shū)以及有關(guān)安全會(huì)話、正在使用的加密算法套件以及相關(guān)項(xiàng)目的信息。例如,這是開(kāi)頭的部分輸出,它聲明證書(shū)鏈即將到來(lái)。證書(shū)的編碼為 base64:
Certificate chain 0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com i:/C=US/O=Google Trust Services/CN=Google Internet Authority G3-----BEGIN CERTIFICATE-----MIIEijCCA3KgAwIBAgIQdCea9tmy/T6rK/dDD1isujANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZpY2VzMSUw...
諸如 Google 之類的主要網(wǎng)站通常會(huì)發(fā)送多個(gè)證書(shū)進(jìn)行身份驗(yàn)證。
輸出以有關(guān) TLS 會(huì)話的摘要信息結(jié)尾,包括加密算法套件的詳細(xì)信息:
SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES128-GCM-SHA256 Session-ID: A2BBF0E4991E6BBBC318774EEE37CFCB23095CC7640FFC752448D07C7F438573...
client 程序中使用了協(xié)議 TLS 1.2,Session-ID 唯一地標(biāo)識(shí)了 openssl 實(shí)用程序和 Google Web 服務(wù)器之間的連接。Cipher 條目可以按以下方式進(jìn)行解析:
ECDHE( 橢圓曲線 Diffie-Hellman(臨時(shí))(Elliptic Curve Diffie Hellman Ephemeral))是一種用于管理 TLS 握手的高效的有效算法。尤其是,ECDHE 通過(guò)確保連接雙方(例如,client 程序和 Google Web 服務(wù)器)使用相同的加密/解密密鑰(稱為會(huì)話密鑰)來(lái)解決“密鑰分發(fā)問(wèn)題”。后續(xù)文章會(huì)深入探討該細(xì)節(jié)。
RSA(Rivest Shamir Adleman)是主要的公共密鑰密碼系統(tǒng),并以 1970 年代末首次描述了該系統(tǒng)的三位學(xué)者的名字命名。這個(gè)正在使用的密鑰對(duì)是使用 RSA 算法生成的。
AES128( 高級(jí)加密標(biāo)準(zhǔn)(Advanced Encryption Standard))是一種 塊式加密算法(block cipher),用于加密和解密 位塊(blocks of bits)。(另一種算法是 流式加密算法(stream cipher),它一次加密和解密一個(gè)位。)這個(gè)加密算法是對(duì)稱加密算法,因?yàn)槭褂猛粋€(gè)密鑰進(jìn)行加密和解密,這首先引起了密鑰分發(fā)問(wèn)題。AES 支持 128(此處使用)、192 和 256 位的密鑰大?。好荑€越大,安全性越好。通常,像 AES 這樣的對(duì)稱加密系統(tǒng)的密鑰大小要小于像 RSA 這樣的非對(duì)稱(基于密鑰對(duì))系統(tǒng)的密鑰大小。例如,1024 位 RSA 密鑰相對(duì)較小,而 256 位密鑰則當(dāng)前是 AES 最大的密鑰。
GCM( 伽羅瓦計(jì)數(shù)器模式(Galois Counter Mode))處理在安全對(duì)話期間重復(fù)應(yīng)用的加密算法(在這種情況下為 AES128)。AES128 塊的大小僅為 128 位,安全對(duì)話很可能包含從一側(cè)到另一側(cè)的多個(gè) AES128 塊。GCM 非常有效,通常與 AES128 搭配使用。
SHA256( 256 位安全哈希算法(Secure Hash Algorithm 256 bits))是我們正在使用的加密哈希算法。生成的哈希值的大小為 256 位,盡管使用 SHA 甚至可以更大。
加密算法套件正在不斷發(fā)展中。例如,不久前,Google 使用 RC4 流加密算法(RSA 的 Ron Rivest 后來(lái)開(kāi)發(fā)的 Ron’s Cipher 版本 4)。 RC4 現(xiàn)在有已知的漏洞,這大概部分導(dǎo)致了 Google 轉(zhuǎn)換為 AES128。
總結(jié)
我們通過(guò)安全的 C Web 客戶端和各種命令行示例對(duì) OpenSSL 做了首次了解,使一些需要進(jìn)一步闡明的主題脫穎而出。 下一篇文章會(huì)詳細(xì)介紹 ,從加密散列開(kāi)始,到對(duì)數(shù)字證書(shū)如何應(yīng)對(duì)密鑰分發(fā)挑戰(zhàn)為結(jié)束的更全面討論。
-
Linux
+關(guān)注
關(guān)注
87文章
11292瀏覽量
209322 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136683 -
SSL
+關(guān)注
關(guān)注
0文章
125瀏覽量
25737
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論