使用 OpenSSL API 進行安全編程,第 3 部分: 提供安全服務(三)

來源:互聯網
上載者:User

OpenSSL 提供必要的能力

文檔選項


層級: 中級

Kenneth Ballard (kballard@kennethballard.com), 軟體工程師, MediNotes Corp.

2006 年 11 月 09 日

如果沒有安全的伺服器應用程式,那麼也就不需要安全的客戶機應用程式。使用 OpenSSL,我們可以建立安全的伺服器應用程式,儘管文檔讓這一切看起來非常複雜,但實際上並非如此。本文中我們將學習如何使用在這個 3 部分系列文章 的 第 1 部分 中學習到的概念來構建安全的伺服器應用程式。

本系列文章的前兩部分討論了使用 OpenSSL 來建立客戶機端應用程式的內容。第 1 部分 討論了使用 OpenSSL 建立基本安全客戶機的問題,而 第 2 部分 則深入討論了有關數位憑證的問題。在閱讀本文的讀者給我發回很多 e-mail 和正面反饋之後,我非常清楚,接下來的一期理論介紹應該是有關伺服器的。

伺服器為網路和網際網路 提供了訪問諸如檔案和裝置之類的資源的訪問能力。有時我們必須要通過一個安全通道來提供這些服務。OpenSSL 讓我們可以使用安全通道和開放通道來編寫服務。

使用 OpenSSL 來建立基本的伺服器應用程式從本質上來說幾乎 等同於建立一個基本的客戶機應用程式。二者之間的區別不多。顯然,區別之一就是伺服器將被設定為接收到達的串連,而不是建立外發的串連。並且,正如我們可以從本系列的第 2 部分有關數位憑證的討論中看到的一樣,伺服器還必須要在握手過程中提供安全性憑證。

等待

伺服器基本上就是呆在那裡等待到達的串連。畢竟,這就是伺服器存在的原因。Web 服務器要等待瀏覽器請求頁面,FTP 伺服器要等待客戶機請求檔案,聊天伺服器要等待聊天客戶機所發出的串連。因此伺服器要做的事情就是等待。

在客戶機和伺服器通訊之間差別不大,惟一的差別就是對於握手來說,伺服器就像是硬幣的反面。其他東西都是相同的。

這讓我們可以使用 OpenSSL 來編寫安全的伺服器應用程式,再次假設您已經瞭解如何使用 OpenSSL 來編寫客戶機應用程式。(如果您還不瞭解相關知識,請參閱本系列第 1 部分 “API 概述” 來學習如何設定 OpenSSL 庫。)



回頁首

兩種形式的標識

SSL 上下文

要設定本文中使用的 SSL 上下文,請使用下面的代碼。這個函數在出錯時會返回 NULL:

SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());

也可以說是標識的兩部分。

伺服器要負責提供在握手過程中使用的安全性憑證。完整的伺服器憑證包括兩個部分:公開金鑰和私密金鑰。公開金鑰是發送給客戶機的,而私密金鑰則是保密的。

就像是信任認證必須要提供給客戶機應用程式使用的庫一樣,伺服器密鑰也必須要提供給伺服器應用程式使用的庫。有幾個函數都提供了這種功能:

清單 1. 載入伺服器憑證的函數

SSL_CTX_use_certificate(SSL_CTX *, X509 *)                        SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len, unsigned char *d);                        SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file, int type);                        

這個函數的 ASN1 變種可以將指定記憶體位置處的使用 ASN1 編碼的數位憑證載入到 SSL 環境中。這個函數會載入給定記憶體結構中所提供的一個 X.509 憑證;而最後一個函數,即帶有 _file 的那個,會從檔案中載入一個使用 PEM 編碼的數位憑證。這個函數的 type 參數讓我們可以載入使用 DER 編碼的認證。

要載入私密金鑰,請使用下面函數之一:

清單 2. 載入私密金鑰使用的函數

SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);                        SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx, unsigned char *d, long len);                        SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file, int type);                        SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);                        SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, unsigned char *d, long len);                        SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file, int type);                        


回頁首

需要的互動

私密金鑰最適合用來加密儲存。不過,問題是載入認證的函數並沒有請求使用加密認證的密碼。相反,OpenSSL 為獲得密碼提供了一種回調機制。

回調格式如下:

清單 3. 回調格式

int password_callback(char *buf, int size, int rwflag, void *userdata);                        

就本文的目的來說,最後一個參數 userdata 是不需要的。緩衝區在調用這個函數之前被調用,因此對於這個緩衝區的大小我們無法控制。

伺服器私密金鑰

注意對於伺服器憑證來說,私密金鑰不應該加密進行儲存。否則,管理員可能會被過於頻繁地要求輸入密碼。

參數 rwflag 是讀/寫標記。使用它的目的是使我們可以編程確定這個密碼是正在用來加密資訊(rwflag = 1)還是解密資訊(rwflag = 0)。如果正在使用回呼函數來請求對資料進行加密使用的密碼,最好是以某種方式請求兩次,這樣可以多一次機會接收使用者的輸入。

在認證載入時,這個密碼只會請求一次,這樣它就可以進行解密並儲存到記憶體中了。如何從使用者那裡擷取密碼,完全取決於您的實現。

一旦我們建立好密碼回呼函數,就可以按照下面的方法使用 SSL_CTX_set_default_passwd_cb 將其安裝到 SSL 環境中:

清單 4. 安裝回呼函數

/* ctx is a pointer to a previously created SSL context, and cb is the pointer                        * to the callback function you created.                        */                        SSL_CTX_set_default_passwd_cb(ctx, cb);                        


回頁首

發動引擎

現在提示使用者輸入密碼的回呼函數已經建立好了,然後我們就可以使用真正匯入認證的函數了。認證可以從現有的記憶體結構或檔案中匯入。

為了更加符合處理數位憑證的常用情況,例如 Apache HTTP Server Project 項目所作的一樣,我將展示如何從檔案中載入認證。如果我們已經閱讀了本系列文章的 第 1 部分,那麼載入認證的的方式就非常類似於在前面文章中給出的載入信任儲存的方式。

我們將從公用認證開始介紹,這個認證會發送給客戶機。

清單 5. 載入公用認證

/**                        * ctx is the SSL context created earlier                        */                        if(SSL_CTX_use_certificate_file(ctx, "/path/to/certificate.pem", SSL_FILETYPE_PEM) < 1)                        {                        /* Handle failed load here */                        }                        

在載入公用認證之後,就必須載入私人認證了。這是在握手過程中需要的,因為客戶機在這個過程中正將這些資訊發送給對公開金鑰進行加密的伺服器。這些資料只能使用私密金鑰進行解密。同樣,為了保持一致,我們也將從檔案中載入密鑰。

清單 6. 載入私密金鑰

if(SSL_CTX_use_PrivateKey_file(ctx, "/path/to/private.key", SSL_FILETYPE_PEM) < 1)                        {                        /* Handle failed load here */                        }                        


回頁首

完成設定

在設定好環境(請參看上面的 SSL 環境)和載入密鑰之後,現在應該通過建立 BIO 對象來完成設定了。我們可以回想一下在 第 1 部分 中是如何使用 OpenSSL BIO 庫來建立 SSL 和非 SSL 通訊的。為了與這篇文章保持一致,我們在本文中也將實現同樣的功能。

清單 7. BIO 指標

BIO *bio, *abio, *out;                        

3 個 BIO 對象?為什麼我們需要使用 3 個 BIO 對象呢?這麼做有一個目的,請相信我。(記住,信任和安全性的目標是一致的。)

第一個指標 bio 是主要的 BIO 對象,它可以從 SSL 環境中建立。第二個對象 abio 是接受串連使用的 BIO,用來接收到達的串連。第三個 BIO out,是伺服器發往客戶機使用的對象。

清單 8. 設定主要的 BIO 對象

bio = BIO_new_ssl(ctx, 0);                        if(bio == NULL)                        {                        /* Handle failure here */                        }                        /* Here, ssl is an SSL* (see Part 1) */                        BIO_get_ssl(bio, &ssl);                        SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);                        

此處對 BIO 對象的設定與客戶機串連使用的 BIO 設定稍有不同。我們可以回想一下第 1 部分中客戶機串連是使用 BIO_new_ssl_connect 建立的。

此處,設定是使用 BIO_new_ssl 加上兩個參數建立的:一個指向 SSL_CTX 對象的指標和一個標記。這個標記告訴 OpenSSL 要建立哪種 BIO 對象:0 用於伺服器,1 用於客戶機。由於這段代碼試圖建立客戶機串連,因此這個標記就應該設定為 0。

清單 9. 設定接收 BIO

abio = BIO_new_accept("4422");                        BIO_set_accept_bios(abio, bio);                        

其中 BIO_do_connect 為客戶機串連建立 BIO, BIO_new_accept 為伺服器串連建立 BIO。它只需要一個參數,就是監聽的連接埠,它被編碼在字串中。

由於這假設正在監聽安全連線,因此我們需要將一個安全 BIO 連結到這個接收 BIO 上。這是第二個函數調用 BIO_set_accept_bios 使用的地方。她將前面建立的 SSL BIO 串連到接收 BIO 上。

這個函數調用不需要釋放 SSL BIO。在銷毀接收 BIO 之後,它會自動被釋放。



回頁首

現在坐下來等待吧

伺服器就像是一個漁夫;它只需要坐在那裡等待客戶機上鉤就好了。伺服器玩的就是等待遊戲,只需要等待客戶機串連到達即可。

如果曾經有過使用 Winsock 或 BSD Socket 進行編程的經驗,就很可能具備 accept 函數的使用經驗。OpenSSL 中的對應部分是 BIO_do_accept,不過我們不是只調用一次 accept 然後等待,而是在等待之前,必須要調用 BIO_do_accept 兩次。

清單 10. 告訴伺服器 “坐下來”

/* First call to set up for accepting incoming connections... */                        if(BIO_do_accept(abio) <= 0)                        {                        /* Handle fail here */                        }                        /* Second call to actually wait */                        if(BIO_do_accept(abio) <= 0)                        {                        /* Handle fail here */                        }                        /* Any other call will cause it to wait automatically */                        

第一次調用 BIO_do_accept 會設定 BIO 來接收到達串連。第二次調用需要真正坐下來等待。此後任何時候都允許它等待。



回頁首

響應到達串連

BIO_do_accept 在接收到到達串連時會返回 1。不過我們不能只通過接收 BIO 進行通訊。相反,OpenSSL 會建立另外一個 BIO,它必須使用 BIO_pop 來彈出接收 BIO。

清單 11. 彈出串連進行通訊

out = BIO_pop(abio);                        if(BIO_do_handshake(out) <= 0)                        {                        /* Handle fail here */                        }                        

在彈出到達的串連到接收 BIO 之後,握手需要使用一個到 BIO_do_handshake 的調用進行處理。如果前面幾節中的設定成功了,那麼握手在這裡也應該會成功。

伺服器會通過 BIO 庫的各種讀寫函數真正與客戶機進行通訊。在 第 1 部分 中我們已經討論了有關這些問題的內容,因此我們可以在本文中找到更多討論內容。



回頁首

提供卓越的服務

總體來說,一旦理解這一切是如何工作的,使用 OpenSSL 建立安全的伺服器應用程式就沒什麼困難了。從現在開始,我們就可以對所提供的範例代碼進行擴充,從而建立一個完全版本的 SSL 伺服器應用程式來滿足我們的要求了。不過要預先警告一下,此處以及 下載一節 所提供的代碼範例都進行了盡量簡化,應該只適用於實驗的目的。在真正建立一個完整的 SSL 伺服器應用程式之前,請確保閱讀並研究最新的安全建議。



回頁首

下載

描述 名字 大小 下載方法
本文的範例程式碼 openssl3.tar.gz 4KB HTTP
關於下載方法的資訊

參考資料

學習

  • 您可以參閱本文在 developerWorks 全球網站上的 英文原文 。

  • 請閱讀本系列文章的第 1 部分 “API 概覽: 建立基本的安全連線和非安全連線”(developerWorks,2004 年 7 月),這是有關如何設定 OpenSSL 庫和建立簡單客戶機的基礎讀物。
  • 請閱讀本系列文章的第 1 部分 “使用 OpenSSL API 進行安全編程,第 2 部分: 安全握手”(developerWorks,2005 年 5 月),學習有關處理數位憑證的基本知識,包括如何從認證中擷取並驗證名字。
  • 在 developerWorks Linux 專區 中可以找到為 Linux 開發人員準備的更多資源。
  • 隨時關注最新的 developerWorks 技術活動和 Webcasts。

獲得產品和技術

  • 下載最新的 OpenSSL 庫 及相關文檔。

  • 定購免費的 SEK for Linux,這有兩張 DVD,包括最新的 IBM for Linux 的試用版軟體,包括 DB2、Lotus、Rational、Tivoli 和 WebSphere。
  • 在您的下一個開發項目中採用 IBM 試用版軟體,這可以從 developerWorks 上直接下載。

討論

  • 通過參與 developerWorks blogs 加入 developerWorks 社區。

關於作者

 

Kenneth Ballard 擁有 Peru State College(位於 Peru, Nebraska)的電腦科學專業學士學位,在這裡,他是校報 The Peru State Times 的專職作者。他還擁有 Southwestern Community College(位於 Creston, Iowa)的電腦編程專業副學士學位。Kenneth 已經編寫了多個應用程式和編程庫。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.