您好,登錄后才能下訂單哦!
這篇文章主要介紹了linux中OpenSSL密碼學基礎知識有哪些,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
安全套接字層(SSL)是 Netscape 在 1995 年發布的一種加密協議。該協議層可以位于 HTTP 之上,從而為 HTTPS 提供了 S:安全。SSL 協議提供了各種安全服務,其中包括兩項在 HTTPS 中至關重要的服務:
(也稱為相互質詢):連接的每一邊都對另一邊的身份進行身份驗證。如果 Alice 和 Bob 要通過 SSL 交換消息,則每個人首先驗證彼此的身份。
:發送者在通過通道發送消息之前先對其進行加密。然后,接收者解密每個接收到的消息。此過程可保護網絡對話。即使竊聽者 Eve 截獲了從 Alice 到 Bob 的加密消息(即中間人攻擊),Eve 會發現他無法在計算上解密此消息。
反過來,這兩個關鍵 SSL 服務與其他不太受關注的服務相關聯。例如,SSL 支持消息完整性,從而確保接收到的消息與發送的消息相同。此功能是通過哈希函數實現的,哈希函數也隨 OpenSSL 工具箱一起提供。
SSL 有多個版本(例如 SSLv2 和 SSLv3),并且在 1999 年出現了一個基于 SSLv3 的類似協議傳輸層安全性(TLS)。TLSv1 和 SSLv3 相似,但不足以相互配合工作。不過,通常將 SSL/TLS 稱為同一協議。例如,即使正在使用的是 TLS(而非 SSL),OpenSSL 函數也經常在名稱中包含 SSL。此外,調用 OpenSSL 命令行實用程序以 openssl
開始。
除了 man 頁面之外,OpenSSL 的文檔是零零散散的,鑒于 OpenSSL 工具包很大,這些頁面很難以查找使用。命令行和代碼示例可以將主要主題集中起來。讓我們從一個熟悉的示例開始(使用 HTTPS 訪問網站),然后使用該示例來選出我們感興趣的加密部分進行講述。
此處顯示的 client
程序通過 HTTPS 連接到 Google:
/* compilation: gcc -o client client.c -lssl -lcrypto */#include <stdio.h>#include <stdlib.h>#include <openssl/bio.h> /* BasicInput/Output streams */#include <openssl/err.h> /* errors */#include <openssl/ssl.h> /* core library */#define BuffSize 1024 void report_and_exit(const char* msg) { perror(msg); ERR_print_errors_fp(stderr); exit(-1);} void init_ssl() { SSL_load_error_strings(); SSL_library_init();} void cleanup(SSL_CTX* ctx, BIO* bio) { SSL_CTX_free(ctx); BIO_free_all(bio);} void secure_connect(const char* hostname) { char name[BuffSize]; char request[BuffSize]; char response[BuffSize]; const SSL_METHOD* method = TLSv1_2_client_method(); if (NULL == method) report_and_exit("TLSv1_2_client_method..."); SSL_CTX* ctx = SSL_CTX_new(method); if (NULL == ctx) report_and_exit("SSL_CTX_new..."); BIO* bio = BIO_new_ssl_connect(ctx); if (NULL == bio) report_and_exit("BIO_new_ssl_connect..."); SSL* ssl = NULL; /* 鏈路 bio 通道,SSL 會話和服務器端點 */ sprintf(name, "%s:%s", hostname, "https"); BIO_get_ssl(bio, &ssl); /* 會話 */ SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* 魯棒性 */ BIO_set_conn_hostname(bio, name); /* 準備連接 */ /* 嘗試連接 */ if (BIO_do_connect(bio) <= 0) { cleanup(ctx, bio); report_and_exit("BIO_do_connect..."); } /* 驗證信任庫,檢查證書 */ if (!SSL_CTX_load_verify_locations(ctx, "/etc/ssl/certs/ca-certificates.crt", /* 信任庫 */ "/etc/ssl/certs/")) /* 其它信任庫 */ report_and_exit("SSL_CTX_load_verify_locations..."); long verify_flag = SSL_get_verify_result(ssl); if (verify_flag != X509_V_OK) fprintf(stderr, "##### Certificate verification error (%i) but continuing...\n", (int) verify_flag); /* 獲取主頁作為示例數據 */ sprintf(request, "GET / HTTP/1.1\x0D\x0AHost: %s\x0D\x0A\x43onnection: Close\x0D\x0A\x0D\x0A", hostname); BIO_puts(bio, request); /* 從服務器讀取 HTTP 響應并打印到輸出 */ while (1) { memset(response, '\0', sizeof(response)); int n = BIO_read(bio, response, BuffSize); if (n <= 0) break; /* 0 代表流結束,< 0 代表有錯誤 */ puts(response); } cleanup(ctx, bio);} int main() { init_ssl(); const char* hostname = "www.google.com:443"; fprintf(stderr, "Trying an HTTPS connection to %s...\n", hostname); secure_connect(hostname); return 0;}
可以從命令行編譯和執行該程序(請注意 -lssl
和 -lcrypto
中的小寫字母 L
):
gcc -o client client.c -lssl -lcrypto
該程序嘗試打開與網站 www.google.com 的安全連接。在與 Google Web 服務器的 TLS 握手過程中,client
程序會收到一個或多個數字證書,該程序會嘗試對其進行驗證(但在我的系統上失敗了)。盡管如此,client
程序仍繼續通過安全通道獲取 Google 主頁。該程序取決于前面提到的安全工件,盡管在上述代碼中只著重突出了數字證書。但其它工件仍在幕后發揮作用,稍后將對它們進行詳細說明。
通常,打開 HTTP(非安全)通道的 C 或 C++ 的客戶端程序將使用諸如文件描述符或網絡套接字之類的結構,它們是兩個進程(例如,這個 client
程序和 Google Web 服務器)之間連接的端點。另一方面,文件描述符是一個非負整數值,用于在程序中標識該程序打開的任何文件類的結構。這樣的程序還將使用一種結構來指定有關 Web 服務器地址的詳細信息。
這些相對較低級別的結構不會出現在客戶端程序中,因為 OpenSSL 庫會將套接字基礎設施和地址規范等封裝在更高層面的安全結構中。其結果是一個簡單的 API。下面首先看一下 client
程序示例中的安全性詳細信息。
該程序首先加載相關的 OpenSSL 庫,我的函數 init_ssl
中對 OpenSSL 進行了兩次調用:
SSL_load_error_strings();
SSL_library_init();
下一個初始化步驟嘗試獲取安全上下文,這是建立和維護通往 Web 服務器的安全通道所需的信息框架。如對 OpenSSL 庫函數的調用所示,在示例中使用了 TLS 1.2:
如果調用成功,則將 method
指針被傳遞給庫函數,該函數創建類型為 SSL_CTX
的上下文:
client
程序會檢查每個關鍵的庫調用的錯誤,如果其中一個調用失敗,則程序終止。
SSL_CTX* ctx = SSL_CTX_new(method);
const SSL_METHOD* method = TLSv1_2_client_method(); /* TLS 1.2 */
現在還有另外兩個 OpenSSL 工件也在發揮作用:SSL 類型的安全會話,從頭到尾管理安全連接;以及類型為 BIO(基本輸入/輸出)的安全流,用于與 Web 服務器進行通信。BIO 流是通過以下調用生成的:
請注意,這個最重要的上下文是其參數。BIO
類型是 C 語言中 FILE
類型的 OpenSSL 封裝器。此封裝器可保護 client
程序與 Google 的網絡服務器之間的輸入和輸出流的安全。
BIO* bio = BIO_new_ssl_connect(ctx);
有了 SSL_CTX
和 BIO
,然后程序在 SSL 會話中將它們組合在一起。三個庫調用可以完成工作:
安全連接本身是通過以下調用建立的:
如果最后一個調用不成功,則 client
程序終止;否則,該連接已準備就緒,可以支持 client
程序與 Google Web 服務器之間的機密對話。
BIO_do_connect(bio);
BIO_get_ssl(bio, &ssl); /* 會話 */
SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); /* 魯棒性 */
BIO_set_conn_hostname(bio, name); /* 準備連接 */
在與 Web 服務器握手期間,client
程序會接收一個或多個數字證書,以認證服務器的身份。但是,client
程序不會發送自己的證書,這意味著這個身份驗證是單向的。(Web 服務器通常配置為不需要客戶端證書)盡管對 Web 服務器證書的驗證失敗,但 client
程序仍通過了連接到 Web 服務器的安全通道繼續獲取 Google 主頁。
為什么驗證 Google 證書的嘗試會失敗?典型的 OpenSSL 安裝目錄為 /etc/ssl/certs
,其中包含 ca-certificates.crt
文件。該目錄和文件包含著 OpenSSL 自帶的數字證書,以此構成信任庫。可以根據需要更新信任庫,尤其是可以包括新信任的證書,并刪除不再受信任的證書。
client
程序從 Google Web 服務器收到了三個證書,但是我的計算機上的 OpenSSL 信任庫并不包含完全匹配的證書。如目前所寫,client
程序不會通過例如驗證 Google 證書上的數字簽名(一個用來證明該證書的簽名)來解決此問題。如果該簽名是受信任的,則包含該簽名的證書也應受信任。盡管如此,client
程序仍繼續獲取頁面,然后打印出 Google 的主頁。下一節將更詳細地介紹這些。
讓我們從客戶端示例中可見的安全工件(數字證書)開始,然后考慮其他安全工件如何與之相關。數字證書的主要格式標準是 X509,生產級的證書由諸如 Verisign 的證書頒發機構(CA)頒發。
數字證書中包含各種信息(例如,激活日期和失效日期以及所有者的域名),也包括發行者的身份和數字簽名(這是加密過的加密哈希值)。證書還具有未加密的哈希值,用作其標識指紋。
哈希值來自將任意數量的二進制位映射到固定長度的摘要。這些位代表什么(會計報告、小說或數字電影)無關緊要。例如,消息摘要版本 5(MD5)哈希算法將任意長度的輸入位映射到 128 位哈希值,而 SHA1(安全哈希算法版本 1)算法將輸入位映射到 160 位哈希值。不同的輸入位會導致不同的(實際上在統計學上是唯一的)哈希值。下一篇文章將會進行更詳細的介紹,并著重介紹什么使哈希函數具有加密功能。
數字證書的類型有所不同(例如根證書、中間證書和最終實體證書),并形成了反映這些證書類型的層次結構。顧名思義,根證書位于層次結構的頂部,其下的證書繼承了根證書所具有的信任。OpenSSL 庫和大多數現代編程語言都具有 X509 數據類型以及處理此類證書的函數。來自 Google 的證書具有 X509 格式,client
程序會檢查該證書是否為 X509_V_OK
。
X509 證書基于公共密鑰基礎結構(PKI),其中包括的算法(RSA 是占主導地位的算法)用于生成密鑰對:公共密鑰及其配對的私有密鑰。公鑰是一種身份:Amazon 的公鑰對其進行標識,而我的公鑰對我進行標識。私鑰應由其所有者負責保密。
成對出現的密鑰具有標準用途。可以使用公鑰對消息進行加密,然后可以使用同一個密鑰對中的私鑰對消息進行解密。私鑰也可以用于對文檔或其他電子工件(例如程序或電子郵件)進行簽名,然后可以使用該對密鑰中的公鑰來驗證簽名。以下兩個示例補充了一些細節。
在第一個示例中,Alice 將她的公鑰分發給全世界,包括 Bob。然后,Bob 用 Alice 的公鑰加密郵件,然后將加密的郵件發送給 Alice。用 Alice 的公鑰加密的郵件將可以用她的私鑰解密(假設是她自己的私鑰),如下所示:
+------------------+ encrypted msg +-------------------+Bob's msg--->|Alice's public key|--------------->|Alice's private key|---> Bob's msg +------------------+ +-------------------+
理論上可以在沒有 Alice 的私鑰的情況下解密消息,但在實際情況中,如果使用像 RSA 這樣的加密密鑰對系統,則在計算上做不到。
現在,第二個示例,請對文檔簽名以證明其真實性。簽名算法使用密鑰對中的私鑰來處理要簽名的文檔的加密哈希:
+-------------------+Hash of document--->|Alice's private key|--->Alice's digital signature of the document +-------------------+
假設 Alice 以數字方式簽署了發送給 Bob 的合同。然后,Bob 可以使用 Alice 密鑰對中的公鑰來驗證簽名:
+------------------+Alice's digital signature of the document--->|Alice's public key|--->verified or not +------------------+
假若沒有 Alice 的私鑰,就無法輕松偽造 Alice 的簽名:因此,Alice 有必要保密她的私鑰。
在 client
程序中,除了數字證書以外,這些安全性都沒有明確展示。下一篇文章使用使用 OpenSSL 實用程序和庫函數的示例填充更多詳細的信息。
同時,讓我們看一下 OpenSSL 命令行實用程序:特別是在 TLS 握手期間檢查來自 Web 服務器的證書的實用程序。調用 OpenSSL 實用程序可以使用 openssl
命令,然后添加參數和標志的組合以指定所需的操作。
看看以下命令:
openssl list-cipher-algorithms
該輸出是組成加密算法套件的相關算法的列表。下面是列表的開頭,加了澄清首字母縮寫詞的注釋:
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...
下一條命令使用參數 s_client
將打開到 www.google.com 的安全連接,并在屏幕上顯示有關此連接的所有信息:
openssl s_client -connect www.google.com:443 -showcerts
端口號 443 是 Web 服務器用于接收 HTTPS(而不是 HTTP 連接)的標準端口號。(對于 HTTP,標準端口為 80)Web 地址 www.google.com:443 也出現在 client
程序的代碼中。如果嘗試連接成功,則將顯示來自 Google 的三個數字證書以及有關安全會話、正在使用的加密算法套件以及相關項目的信息。例如,這是開頭的部分輸出,它聲明證書鏈即將到來。證書的編碼為 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 之類的主要網站通常會發送多個證書進行身份驗證。
輸出以有關 TLS 會話的摘要信息結尾,包括加密算法套件的詳細信息:
SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES128-GCM-SHA256 Session-ID: A2BBF0E4991E6BBBC318774EEE37CFCB23095CC7640FFC752448D07C7F438573...
client
程序中使用了協議 TLS 1.2,Session-ID
唯一地標識了 openssl
實用程序和 Google Web 服務器之間的連接。Cipher
條目可以按以下方式進行解析:
ECDHE
(
)是一種用于管理 TLS 握手的高效的有效算法。尤其是,ECDHE 通過確保連接雙方(例如,client
程序和 Google Web 服務器)使用相同的加密/解密密鑰(稱為會話密鑰)來解決“密鑰分發問題”。后續文章會深入探討該細節。
RSA
(Rivest Shamir Adleman)是主要的公共密鑰密碼系統,并以 1970 年代末首次描述了該系統的三位學者的名字命名。這個正在使用的密鑰對是使用 RSA 算法生成的。
AES128
(高級加密標準)是一種塊式加密算法,用于加密和解密位塊。(另一種算法是流式加密算法,它一次加密和解密一個位。)這個加密算法是對稱加密算法,因為使用同一個密鑰進行加密和解密,這首先引起了密鑰分發問題。AES 支持 128(此處使用)、192 和 256 位的密鑰大小:密鑰越大,安全性越好。
通常,像 AES 這樣的對稱加密系統的密鑰大小要小于像 RSA 這樣的非對稱(基于密鑰對)系統的密鑰大小。例如,1024 位 RSA 密鑰相對較小,而 256 位密鑰則當前是 AES 最大的密鑰。
GCM
(伽羅瓦計數器模式)處理在安全對話期間重復應用的加密算法(在這種情況下為 AES128)。AES128 塊的大小僅為 128 位,安全對話很可能包含從一側到另一側的多個 AES128 塊。GCM 非常有效,通常與 AES128 搭配使用。
SHA256
(256 位安全哈希算法)是我們正在使用的加密哈希算法。生成的哈希值的大小為 256 位,盡管使用 SHA 甚至可以更大。
加密算法套件正在不斷發展中。例如,不久前,Google 使用 RC4 流加密算法(RSA 的 Ron Rivest 后來開發的 Ron’s Cipher 版本 4)。 RC4 現在有已知的漏洞,這大概部分導致了 Google 轉換為 AES128。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“linux中OpenSSL密碼學基礎知識有哪些”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。