前面說了一大堆使用OpenSSL進行加密操作的東西,今天開始說說上層的SSL通信了,,從基本的程序結(jié)構談起,。SSL的理論就不說了,自己找RFC的TLS文檔看去,。SSL通信程序的基本結(jié)構和普通的客戶機/服務器模式相差不大,。今天比較偷懶,把錯誤處理一并省略^_^
先看客戶端,。 #include <openssl/ssl.h> #include <openssl/x509.h> #include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> int main(int argc, char** argv) { char buffer[256] = {0}; int socket_client = 0; struct sockaddr_in socket_address; SSL* ssl = NULL; SSL_CTX* ssl_ctx = NULL; SSL_METHOD* ssl_method = NULL; X509* server_cert = NULL; // 初始化SSL庫 SSL_library_init(); // 設置客戶端使用的SSL版本 ssl_method = SSLv3_client_method(); // 創(chuàng)建SSL上下文環(huán)境 // 每個進程只需維護一個SSL_CTX結(jié)構體 ssl_ctx = SSL_CTX_new(ssl_method); // 建立TCP連接 // 這一部分全部使用標準socket函數(shù) socket_client = socket(AF_INET, SOCK_STREAM, 0); socket_address.sin_family = AF_INET; socket_address.sin_addr.s_addr = inet_addr("127.0.0.1"); socket_address.sin_port = htons(1234); connect(socket_client, (struct sockaddr*)&socket_address, sizeof(socket_address)); // 創(chuàng)建維護當前連接信息的SSL結(jié)構體 ssl = SSL_new(ssl_ctx); // 將SSL綁定到套接字上 SSL_set_fd(ssl, socket_client); // 建立SSL連接 SSL_connect(ssl); // 獲取和釋放服務器端證書 // 關于證書的驗證放在下一次討論 server_cert = SSL_get_peer_certificate(ssl); X509_free(server_cert); // 與服務器端進行通信 SSL_write(ssl, "hello, world!", sizeof("hello, world!")); SSL_read(ssl, buffer, 255); printf("received: %s\n", buffer); // 斷開SSL連接 SSL_shutdown(ssl); // 釋放當前連接SSL結(jié)構體 SSL_free(ssl); // 斷開TCP連接 close(socket_client); // 釋放SSL上下文 SSL_CTX_free(ssl_ctx); return 0; } 再看服務器端,。 #include <openssl/ssl.h> #include <openssl/x509.h> #include <stdio.h> #include <sys/socket.h> #include <arpa/inet.h> int main() { int socket_server = 0; int socket_client = 0; struct sockaddr_in sa_serv, sa_cli; char buffer[256] = {0}; SSL* ssl = NULL; SSL_CTX* ssl_ctx = NULL; SSL_METHOD* ssl_method = NULL; X509* client_cert = NULL; // 初始化SSL庫 SSL_library_init(); // 設置客戶端使用的SSL版本 ssl_method = SSLv23_server_method(); // 創(chuàng)建SSL上下文環(huán)境 // 每個進程只需維護一個SSL_CTX結(jié)構體 ssl_ctx = SSL_CTX_new(ssl_method); // 讀取證書文件 SSL_CTX_use_certificate_file(ssl_ctx, "ca-cert.pem", SSL_FILETYPE_PEM); // 讀取密鑰文件 SSL_CTX_use_PrivateKey_file(ssl_ctx, "ca-cert.pem", SSL_FILETYPE_PEM); // 驗證密鑰是否與證書一致 SSL_CTX_check_private_key(ssl_ctx); // 建立TCP服務器端、開始監(jiān)聽并接受客戶端連接請求 // 這一部分全部使用標準socket函數(shù) socket_server = socket(AF_INET, SOCK_STREAM, 0); sa_serv.sin_family = AF_INET; sa_serv.sin_addr.s_addr = INADDR_ANY; sa_serv.sin_port = htons(1234); bind(socket_server, (struct sockaddr*)&sa_serv, sizeof(sa_serv)); listen(socket_server, 10); while (socket_client = accept(socket_server, NULL, NULL)) { // 創(chuàng)建當前連接的SSL結(jié)構體 ssl = SSL_new(ssl_ctx); // 將SSL綁定到套接字上 SSL_set_fd(ssl, socket_client); // 接受SSL連接 SSL_accept(ssl); // 獲取和釋放客戶端證書 // 這一步是可選的 client_cert = SSL_get_peer_certificate(ssl); X509_free(server_cert); // 與客戶端進行通信 SSL_read(ssl, buffer, 255); printf("received: %s\n", buffer); SSL_write(ssl, "reply", 5); // 斷開SSL連接 SSL_shutdown(ssl); // 斷開與客戶端的TCP連接 close(socket_client); // 釋放當前連接SSL結(jié)構體 SSL_free(ssl); } // 停止TCP監(jiān)聽 close(socket_server); // 釋放SSL上下文 SSL_CTX_free(ssl_ctx); return 0; } |
|