openssl 建立連接

 

下面是server 和client 的代碼。用沒跑過,但是用類似的代碼跑了。流程是這樣的。要注意的是openssl中ssl連接建立前用阻塞的socket,建立後可以設置非阻塞。openssl每個操作後最好檢查下是否成功。

/************server*************************/
#include <string.h>
#include <iostream>
#include <winsock2.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/rand.h>
#include <openssl/err.h>
 
#pragma comment (lib,"WS2_32.lib")
#pragma comment( lib, "libeay32.lib" )
#pragma comment( lib, "ssleay32.lib" )
 
char buffer[10001] = {0};
 
int main()
{
SSL_library_init(); //初始化SSL庫
OpenSSL_add_all_algorithms(); //支持所有算法
SSL_load_error_strings();  //提供將錯誤號解析爲字符串的功能
SSL *ssl = NULL;
SSL_CTX *ssl_ctx = NULL;
SSL_METHOD *ssl_method = NULL;
X509 *client_cert = NULL;
//設置客戶端使用的SSL版本
//ssl_method = SSLv3_server_method();
ssl_method = SSLv23_server_method();
//創建SSL上下文環境 每個進程只需維護一個SSL_CTX結構體
ssl_ctx = SSL_CTX_new(ssl_method);
 
//驗證對方
SSL_CTX_set_verify(ssl_ctx,SSL_VERIFY_PEER,NULL);
 
//若驗證,則放置CA證書
SSL_CTX_load_verify_locations(ssl_ctx, "cacert.pem", NULL);
 
//設置pass phrase
SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, "pass phrase");
//讀取證書文件
SSL_CTX_use_certificate_file(ssl_ctx,"*****Cert.pem",SSL_FILETYPE_PEM);
 
//讀取密鑰文件
SSL_CTX_use_PrivateKey_file(ssl_ctx,"*****Key.pem",SSL_FILETYPE_PEM);
 
//驗證密鑰是否與證書一致
SSL_CTX_check_private_key(ssl_ctx);
 
/*構建隨機數生成機制,WIN32平臺必需*/
srand( (unsigned)time( NULL ) );
for( int i = 0;    i < 100;i++ )
seed_int[i] = rand();
RAND_seed(seed_int, sizeof(seed_int));
//設置加密方式
//SSL_CTX_set_cipher_list(ssl_ctx,"RC4-MD5");
//建立TCP服務器端、開始監聽並接受客戶端連接請求
 
// 初始化 Winsock.
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
if ( iResult != NO_ERROR )
{
//失敗
return -1;
}
// 建立socket
server = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( server == INVALID_SOCKET )
{
//失敗
WSACleanup();
return -2;
}
 
// 綁定socket
sockaddr_in service;
service.sin_family = AF_INET;
//service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_addr.s_addr = INADDR_ANY;
service.sin_port = htons( 8899 );
 
if ( bind( server, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR )
{
//失敗
closesocket(server);
return -3;
}
 
// 監聽 socket
if ( listen( server, 10 ) == SOCKET_ERROR )
{
//失敗
return -4;
}
 
do
{
sClient = accept(server,NULL,NULL);
Sleep(100);
}while(sClient == INVALID_SOCKET);
 
//創建當前連接的SSL結構體
ssl = SSL_new(ssl_ctx);
//將SSL綁定到套接字上
SSL_set_fd(ssl, sClient);
 
//接受SSL鏈接
SSL_accept(ssl);
 
//獲取和釋放客戶端證書
client_cert = SSL_get_peer_certificate(ssl);
//打印所有加密算法的信息(可選)
std::cout<<"SSL connection using"<<SSL_get_cipher(ssl)<<std::endl;
 
X509_free(client_cert);
 
//unsigned long cmd;
//if (SOCKET_ERROR == ioctlsocket(sClient, FIONBIO, &cmd))
//{
//創建套接字時發生錯誤,非阻塞設置失敗
//ErrorProcess();
//closesocket(sClient);
//}
 
while(true)
{
SSL_read(ssl, buffer, 10000);
memset(buffer,0,10000);
SSL_write(ssl, "hello, world!", sizeof("hello, world!"));
Sleep(1000);
 
}
 
//斷開SSL鏈接
SSL_shutdown(ssl);
//釋放當前SSL鏈接結構體
SSL_free(ssl);
//斷開TCP鏈接
closesocket(sClient);
//釋放SSL上下文
SSL_CTX_free(ssl_ctx);
 
return 0;
}
  1. /**************client*********************/  
  2. #include <iostream>  
  3. #include <string.h>  
  4. #include <winsock2.h>  
  5. #include <openssl/ssl.h>  
  6. #include <openssl/x509.h>  
  7. #include <openssl/rand.h>  
  8. #include <openssl/err.h>  
  9. #pragma comment (lib,"WS2_32.lib")  
  10. #pragma comment( lib, "libeay32.lib" )  
  11. #pragma comment( lib, "ssleay32.lib" )  
  12.    
  13. int main(int argc, _TCHAR* argv[])  
  14. {  
  15.    
  16. SOCKET client;  
  17. char buffer[256] = {0};  
  18. int  seed_int[100]; /*存放隨機序列*/  
  19.    
  20. SSL *ssl = NULL;  
  21. SSL_CTX *ssl_ctx = NULL;  
  22. SSL_METHOD *ssl_method = NULL;  
  23. X509 *server_cert = NULL;  
  24.    
  25. SSL_library_init();        //init libraries   
  26. OpenSSL_add_all_algorithms(); //支持所有算法   
  27. SSL_load_error_strings();  //提供將錯誤號解析爲字符串的功能   
  28.    
  29.    
  30. //設置客戶端使用的SSL版本   
  31. ssl_method = SSLv3_client_method();  
  32. //創建SSL上下文環境 每個進程只需維護一個SSL_CTX結構體   
  33. ssl_ctx = SSL_CTX_new(ssl_method);  
  34. /*構建隨機數生成機制,WIN32平臺必需*/  
  35. srand( (unsigned)time( NULL ) );  
  36. for( int i = 0;    i < 100;i++ )  
  37. seed_int[i] = rand();  
  38. RAND_seed(seed_int, sizeof(seed_int));  
  39.    
  40.    
  41. /* Load the RSA CA certificate into the SSL_CTX structure */  
  42. /* This will allow this client to verify the server's   */  
  43. /* certificate.                             */  
  44. SSL_CTX_load_verify_locations(ssl_ctx, "cacert.pem", NULL);  
  45.    
  46. /* Set flag in context to require peer (server) certificate verification */  
  47. SSL_CTX_set_verify(ssl_ctx,SSL_VERIFY_PEER,NULL);  
  48. SSL_CTX_set_verify_depth(ssl_ctx,1);  
  49. SSL_CTX_set_default_passwd_cb_userdata(ssl_ctx, "pass phrase");  
  50. //讀取證書文件   
  51. SSL_CTX_use_certificate_file(ssl_ctx,"******Cert.pem",SSL_FILETYPE_PEM);  
  52. //讀取密鑰文件   
  53. SSL_CTX_use_PrivateKey_file(ssl_ctx,"******Key.pem",SSL_FILETYPE_PEM);  
  54. //驗證密鑰是否與證書一致   
  55. SSL_CTX_check_private_key(ssl_ctx);  
  56.    
  57.    
  58. //建立TCP鏈接   
  59. // 初始化 Winsock.   
  60. WSADATA wsaData;  
  61. int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );  
  62. if ( iResult != NO_ERROR )  
  63. {  
  64. //AfxMessageBox("Error at WSAStartup()!");   
  65. return;  
  66. }  
  67.    
  68. // 建立socket socket.   
  69. client = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );  
  70. if ( client == INVALID_SOCKET )  
  71. {  
  72. //AfxMessageBox("Error at socket!");   
  73. WSACleanup();  
  74. return;  
  75. }  
  76.    
  77. // 連接到服務器.   
  78. sockaddr_in clientService;  
  79. clientService.sin_family = AF_INET;  
  80. clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );  
  81. clientService.sin_port = htons( 8899 );  
  82. if ( connect( client, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR)  
  83. {  
  84. //AfxMessageBox( "Failed to connect!" );   
  85. WSACleanup();  
  86. return;  
  87. }  
  88.    
  89. //unsigned long cmd;   
  90. //if (SOCKET_ERROR == ioctlsocket(client, FIONBIO, &cmd))   
  91. //{   
  92. //  //AfxMessageBox( "創建套接字時發生錯誤,非阻塞設置失敗:");   
  93. //  closesocket(client);   
  94. //}   
  95. //創建維護當前連接信息的SSL結構體   
  96. ssl = SSL_new(ssl_ctx);  
  97. //將SSL綁定到套接字上   
  98. SSL_set_fd(ssl, client);  
  99. //建立SSL鏈接   
  100. SSL_connect(ssl);  
  101.    
  102. //獲取服務器端證書   
  103. server_cert = SSL_get_peer_certificate(ssl);  
  104.    
  105. //釋放服務器端證書   
  106. X509_free(server_cert);  
  107.    
  108. unsigned long cmd;  
  109. if (SOCKET_ERROR == ioctlsocket(client, FIONBIO, &cmd))  
  110. {  
  111. //AfxMessageBox( "創建套接字時發生錯誤,非阻塞設置失敗:");   
  112. closesocket(client);  
  113. }  
  114. while(true)  
  115. {  
  116. SSL_write(ssl, "hello, world!", sizeof("hello, world!");  
  117. SSL_read(ssl, buffer, 255);  
  118. printf("received: %s\n",buffer);  
  119. memset(buffer,0,255);  
  120.    
  121. Sleep(1000);  
  122. }  
  123. //斷開SSL鏈接   
  124. SSL_shutdown(ssl);  
  125. //釋放當前SSL鏈接結構體   
  126. SSL_free(ssl);  
  127. closesocket(client);  
  128. //釋放上下文   
  129. SSL_CTX_free(ssl_ctx);  
  130.    
  131. return 0;  
  132. }  
  133.    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章