天天看點

OpenSSL程式設計指引,第一部分

Sep 01, 2001  By  Eric Rescorla  in

  • Software

Do you have a burning need to build a simple web client and server pair? Here's why OpenSSL is for you.

最快和最簡單的建立一個安全的基于TCP協定的網絡應用程式是使用SSL。如果你熟悉C語言,你最好選擇OpenSSL。OpenSSL是Eric Young 的SSLeay包的一個免費實作。遺憾的是,與OpenSSL釋出的文檔和示例代碼很少。在他們那裡,手冊頁面很好,但是他們缺少大圖,是以手冊隻是一個參考,而不是指南。

OpenSSL API是龐大何複雜的,是以我們并不想嘗試在這提供所有内容。目标是教會你足以從手冊頁面有效的工作。這篇文章,第一部分,我們建構一個示範OpenSSL功能的簡單的web用戶端和伺服器。在第二部分,我們将引進進階功能,例如會話恢複和用戶端驗證。

我假定你已經熟悉SSL和HTTP,至少在概念層。如果不是,一個開始的好地方是RFCs(參見引用)。

因為空間的原因,這篇文章僅包含源代碼的摘錄。完整的源碼在作者的網站:http://www.rtfm.com/openssl-examples/。

程式

我們的用戶端是一個簡單的HTTPS用戶端。它初始化一個SSL連接配接到伺服器,然後通過那個連接配接來傳輸HTTP請求。再然後它等待伺服器響應并把他們列印在螢幕上。這是像fetch和cURL程式功能的最簡化的版本。

伺服器程式是簡單的HTTPS伺服器。它等待用戶端的TCP連接配接。當他收到一個的話它産生一個SSL連接配接。一旦連接配接産生,它從用戶端讀取HTTP請求。然後它傳輸HTTP響應給用戶端。一旦響應傳輸完畢,它關閉連接配接。

我們的第一個任務是設定一個上下文對象(SSL_CTX)。這個上下文對象接下來用來建立每一個SSL連接配接的新連接配接對象。這些連接配接對象用來SSL握手,讀寫資料。

這有兩個好處。首先,連接配接對象允許許多結構體隻要被初始化一次,來提高性能。在大多數應用程式中,每個SSL連接配接使用相同的秘鑰材料,認證(CA)清單,等等。而不是為每隔連接配接都重新加載這些材料,我們僅僅在程式啟動的時候把他們加載到上下文對象中。當我們希望建立一個新連接配接的時候,我們可以簡單的吧連接配接指向上下文對象。第二個好處是一個單獨的上下文對象允許多個SSL連接配接共享資料,例如用來恢複會話的會話緩存。上下文初始化有四個主任務組成,都由_ctx()函數初始化,在清單1中顯示。

清單1.初始化_ctx()

在我們可以使用OpenSSL之前,SSL庫必須先初始化。這由SSL_Library_init()完成,這主要加載OpenSSL将要使用的算法。如果我們想報告錯誤,我們也需要使用SSL_load_error_strings()來加載錯誤字元。否則,我們不能映射OpenSSL錯誤為字元串。

我們也需要對象用作錯誤列印上下文。OpenSSL使用一個抽象的叫做BIO的對象來輸入和輸出。這允許程式設計人員簡單的使用不同的BIO對象來為不同的IO通道(sockets,終端,記憶體緩存,等等)使用相同的函數。現在我們建立附加在stderr的BIO對象來列印錯誤。

如果你寫一個的伺服器或可以執行用戶端驗證的用戶端,你需要加載你自己的公/私秘鑰對以及相關的證書。證書在内部存儲并使用SSL_CTX_use_certificate_chain_file()加載CA憑證鍊的形式。SSL_CTX_use_PrivateKey_file() 用來加載私鑰。由于安全的原因,私鑰通常用一個密碼加密。如果這樣,密碼回調函數(使用SSL_CTX_set_default_passwd_cb()設定)被調用來擷取密碼。

如果你準備驗證你連接配接的主機,OpenSSL需要知道你信任什麼CA。調用SSL_CTX_load_verify_locations()來加載CA。

為了好的安全性,SSL需要一個強健随機數源。一般,應用程式有責任提供随機數發生器的材料。然而,如果可用的話,OpenSSL自動使用 /dev/urandom來初始化随機數發生器。由于 /dev/urandom在Linux上是标準,我們不需要為它做任何額外的事,這很友善。因為收集随機數是麻煩并且容易糟糕的。注意如果你不在Linux系統上,你可能由于随機數發生器沒有初始化而在某些情況下出錯。OpenSSL的rand手冊頁提供了更多資訊。