1. 程式人生 > >使用OpenSSL程式設計的基本方法

使用OpenSSL程式設計的基本方法

        SSL通訊模型為標準的C/S結構,除了在TCP層之上進行傳輸之外,與一般的通訊沒有什麼明顯的區別。在這裡,我們主要介紹如何使用OpenSSL進行安全通訊的程式設計。關於OpenSSL的一些詳細的資訊請參考OpenSSL的官方主頁http://www.openssl.org

  在使用OpenSSL前,必須先對OpenSSL進行初始化,以下的三個函式任選其一:

  SSL_library_init(void);
  OpenSSL_add_ssl_algorithms();
  SSLeay_add_ssl_algorithms();

  事實上後面的兩個函式只是第一個函式的巨集。

  如果要使用OpenSSL的出錯資訊,使用SSL_load_error_strings(void)進行錯誤資訊的初始化。以後可以使用void ERR_print_errors_fp(FILE* fp)列印SSL的錯誤資訊,也可以使用文獻[2]中的printf("Error: %s\n", ERR_reason_error_string(ERR_get_error()))方法列印資訊。

  一次SSL連線會話一般要先申請一個SSL環境,基本的過程是:

1.    SSL_METHOD* meth=TLSv1_client_method();建立本次會話連線所使用的協議,如果是客戶端可以使用

  SSL_METHOD* TLSv1_client_method(void);TLSv1.0協議
  SSL_METHOD* SSLv2_client_method(void);SSLv2協議
  SSL_METHOD* SSLv3_client_method(void);SSLv3協議
  SSL_METHOD* SSLv23_client_method(void);SSLv2/v3協議

  伺服器同樣需要建立本次會話所使用的協議:

  SSL_METHOD* TLSv1_server_method(void);
  SSL_METHOD* SSLv2_server_method(void);
  SSL_METHOD* SSLv3_server_method(void);
  SSL_METHOD* SSLv23_server_method(void);

  需要注意的是客戶端和伺服器需要使用相同的協議。

2. 申請SSL會話的環境CTX,使用不同的協議進行會話,其環境也是不同的。申請SSL會話環境的OpenSSL函式是

  SSL_CTX* SSL_CTX_new(SSL_METHOD*);

        引數就是前面我們申請的SSL通訊方式。返回當前的SSL連線環境的指標。然後根據自己的需要設定CTX的屬性,典型的是設定SSL握手階段證書的驗證方式和載入自己的證書。

       void SSL_CTX_set_verify(SSL_CTX*, int, int* (int, X509_STORE_CTX*));

       設定證書驗證的方式。第一個引數是當前的CTX指標,第二個是驗證方式,如果是要驗證對方的話,就使用SSL_VERIFY_PEER。不需要的話,使用SSL_VERIFY_NONE.一般情況下,客戶端需要驗證對方,而伺服器不需要。第三個引數是處理驗證的回撥函式,如果沒有特殊的需要,使用空指標就可以了。

  void SSL_CTX_load_verify_locations(SSL_CTX*, const char*, const char*);

       載入證書,第一個引數同上,引數二是證書檔案的名稱,引數三是證書檔案的路徑;

  int SSL_CTX_use_certificate_file(SSL_CTX* ctx, const char* file,int type);

  載入本地的證書;type指明證書檔案的結構型別;失敗返回-1

  int SSL_CTX_use_PrivateKey_file(SSL_CTX* ctx,const char* file,int type);

  載入自己的私鑰;type引數指明私鑰檔案的結構型別;失敗返回-1,載入了證書和檔案之後,就可以驗證私鑰和證書是否相符:

  int SSL_CTX_check_private_key(SSL_CTX*);

3. 既然SSL使用TCP協議,當然需要把SSLattach到已經連線的套接字上了:

  SSL* SSL_new(SSL_CTX*);申請一個SSL套節字;
  int SSL_set_rfd(SSL*, int);繫結只讀套接字
  int SSL_set_wfd(SSL*, int);繫結只寫套接字
  int SSL_set_fd(SSL*, int);繫結讀寫套接字
  繫結成功返回1,失敗返回0;

4. 接下來就是SSL握手的動作了

  int SSL_connect(SSL*);
       失敗返回-1

5.    握手成功之後,就可以進行通訊了,使用SSL_read和SS_write讀寫SSL套接字代替傳統的read、write:

  int SSL_read(SSL* ssl, char* buf, int num);
  int SSL_write(SSL* ssl, char* buf, int num);
  如果是伺服器,則使用SSL_accept代替傳統的accept呼叫
  int SSL_accept(SSL* ssl);

6.    通訊結束,需要釋放前面申請的SSL資源

  int SSL_shutdown(SSL* ssl);關閉SSL套接字;
  void SSL_free(ssl);釋放SSL套接字;
  void SSL_CTX_free(ctx);釋放SSL環境;