OpenSSL API编程




相关代码:

server端:


  1. #
    include "stdafx.h"
  2. #include <winsock2.h> 
  3. #include <conio.h> 
  4. #include <stdio.h> 
  5. #include "openssl/x509.h" 
  6. #include "openssl/ssl.h" 
  7. #include "openssl/err.h" 
  8.  
  9. #define MSGLENGTH 1024 
  10. #define PORT 8888 
  11. #define CACERT "./private/ca.crt" 
  12. #define SVRCERTF "./certs/server.crt" 
  13. #define SVRKEYF "./private/server.key" 
  14.  
  15. #pragma comment(lib, "wsock32.lib")
  16. #pragma comment(lib, "libeay32.lib")
  17. #pragma comment(lib, "ssleay32.lib")

  18. int _tmain(int argc, _TCHAR* argv[])
  19. { 
  20.     WSADATA wsaData; 
  21.     WSAStartup(MAKEWORD(2,2), &wsaData); 
  22.     SOCKET sock; 
  23.     SSL_METHOD *meth; 
  24.     SSL_CTX* ctx; 
  25.     SSL* ssl; 
  26.     //SSL初始化 
  27.     OpenSSL_add_ssl_algorithms(); 
  28.     //SSL错误信息初始化  
  29.     SSL_load_error_strings(); 
  30.     //创建本次会话所使用的协议  
  31.     meth = (SSL_METHOD *)TLSv1_server_method(); 
  32.     //申请SSL会话的环境  
  33.     ctx = SSL_CTX_new(meth); 
  34.     if (NULL == ctx) 
  35.         exit(1); 
  36.  
  37.     //设置会话的握手方式并加载CA证书
  38.     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 
  39.     if (!SSL_CTX_load_verify_locations(ctx, CACERT, NULL))
  40.     {
  41.         printf("%d \n\n下载CA 证书出错!\n", SSL_CTX_load_verify_locations(ctx, CACERT, NULL));
  42.         exit(-1);
  43.     }
  44.     //加载服务器端的证书  
  45.     if (!SSL_CTX_use_certificate_file(ctx, SVRCERTF, SSL_FILETYPE_PEM)) { 
  46.         ERR_print_errors_fp(stderr); 
  47.         exit(1); 
  48.     } 
  49.     //加载服务器端的私钥 
  50.     if (!SSL_CTX_use_PrivateKey_file(ctx, SVRKEYF, SSL_FILETYPE_PEM)) { 
  51.         ERR_print_errors_fp(stderr); 
  52.         exit(1); 
  53.     } 
  54.     //检查服务器端的证书和私钥是否匹配 
  55.     if (!SSL_CTX_check_private_key(ctx)) { 
  56.         printf("\n\n私钥与证书公钥不匹配!\n"); 
  57.         exit(1); 
  58.     } 
  59.  
  60.     //加密方式 
  61.     SSL_CTX_set_cipher_list(ctx, "RC4-MD5"); 
  62.     //处理握手多次 
  63.     SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); 
  64.  
  65.     /*以下是正常的TCP socket建立过程.............................. */ 
  66.     sock = socket(AF_INET, SOCK_STREAM, 0); 
  67.     if (sock == INVALID_SOCKET) { 
  68.         printf("\n\nSOCKET有问题. \n"); 
  69.         return 0; 
  70.     } 
  71.  
  72.     sockaddr_in addr; 
  73.     memset(&addr, '\0', sizeof(addr)); 
  74.     addr.sin_family = AF_INET; 
  75.     addr.sin_port = htons(PORT); /* Server Port number */ 
  76.     addr.sin_addr.s_addr = INADDR_ANY; 
  77.  
  78.     //绑定sock 
  79.     int nResult = bind(sock, (sockaddr *)&addr, sizeof(addr)); 
  80.     if (nResult == SOCKET_ERROR) { 
  81.         printf("\n\n绑定SOCKET有问题.\n"); 
  82.         return 0; 
  83.     } 
  84.     printf("\n**************************************\n");
  85.     printf("\n服务器启动成功,端口:%d\n\n等待连接.....\n", PORT); 
  86.  
  87.     /*接受TCP链接*/
  88.     sockaddr_in sa_cli; 
  89.     int err = listen(sock, 5); 
  90.     if (-== err) 
  91.         exit(1); 
  92.     int client_len = sizeof(sa_cli); 
  93.     int ss = accept(sock, (struct sockaddr *) &sa_cli, &client_len); 
  94.     if (ss == -1) { 
  95.         exit(1); 
  96.     } 
  97.     closesocket(sock); 
  98.     printf("\n连接端口:%d, port %d\n", sa_cli.sin_addr.s_addr, sa_cli.sin_port); 
  99.     /* TCP 链接已建立.开始SSL 握手过程.......................... */
  100.     //绑定套接字
  101.     ssl = SSL_new(ctx); 
  102.     if (NULL == ssl) 
  103.         exit(1); 
  104.     if (!SSL_set_fd(ssl, ss)) { 
  105.         printf("\n连接失败\n"); 
  106.         exit(1); 
  107.     } 
  108.     //SSL握手
  109.     //SSL_accept(ssl); 
  110.     int k = SSL_accept(ssl); 
  111.     if ( k != 1) { 
  112.         printf("%d\n", k); 
  113.         printf("\n连接失败\n"); 
  114.         exit(1); 
  115.     } 
  116.     //进行信息验证 
  117.     X509 *client_cert; 
  118.     client_cert = SSL_get_peer_certificate(ssl); 
  119.  
  120.     printf("\n发现客户端尝试连接\n");
  121.     if (client_cert != NULL) { 
  122.         printf ("\n客服端证书:\n"); 
  123.         //读取证书subject名并显示
  124.         char *str = X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0); 
  125.         if (NULL == str) { 
  126.             printf("\n认证出错!\n"); 
  127.             exit(1); 
  128.         } 
  129.         printf("\n主题:%s\n", str); 
  130.         //读取证书的issuer名并显示 
  131.         str = X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0); 
  132.         if (NULL == str) { 
  133.             printf("\n证书名为空\n"); 
  134.             exit(1); 
  135.         } 
  136.         printf("\n颁发者:%s\n", str); 
  137.         printf("\n连接成功\n"); 
  138.  
  139.         X509_free (client_cert);/*如不再需要,需将证书释放*/
  140.         OPENSSL_free(str); 
  141.     } 
  142.     else { 
  143.         printf("\n找不到客户端的认证证书\n"); 
  144.         exit(1); 
  145.     } 
  146.  
  147.     char buf[MSGLENGTH]; 
  148.     SSL_write(ssl, "\n服务器连接成功!\n", strlen("\n服务器连接成功!\n")); 
  149.     printf("\n监听客服端:\n\n"); 
  150.     while (1) { 
  151.         err = SSL_read(ssl, buf, sizeof(buf)); 
  152.         buf[err] = '\0'; 
  153.         if (!strcmp(buf, "退出"))
  154.         {
  155.             //关闭套接字 
  156.             SSL_shutdown(ssl); 
  157.             SSL_free(ssl); 
  158.             SSL_CTX_free(ctx); 
  159.             WSACleanup(); 
  160.             getchar(); 
  161.             break;
  162.         }
  163.         else printf(">> %s\n", buf); 
  164.     } 

  165.     return 0; 
  166. }



客户端代码:

  1. //client 
  2. #include <winsock2.h> 
  3. //#include <winsock.h>
  4. #include <conio.h> 
  5. #include <stdio.h> 
  6. #include "openssl/x509.h" 
  7. #include "openssl/ssl.h" 
  8. #include "openssl/err.h" 
  9. #include "openssl/rand.h" 
  10. #include <openssl/applink.c>
  11.  
  12. #define PORT 8888 
  13. #define SERVER "127.0.0.1" 
  14. //#define SERVER "172.31.32.176" 
  15. #define CACERT "./private/ca.crt" 
  16. #define MYCERTF "./certs/client.crt" 
  17. #define MYKEYF "./private/client.key" 
  18. #define MSGLENGTH 1024 

  19. #pragma comment(lib, "wsock32.lib")
  20. #pragma comment(lib, "libeay32.lib")
  21. #pragma comment(lib, "ssleay32.lib")

  22. int _tmain(int argc, _TCHAR* argv[]) 
  23. { 
  24.     WSADATA wsadata; 
  25.     WSAStartup(MAKEWORD(2,2), &wsadata); 
  26.     sockaddr_in sin; 
  27.     int seed_int[100]; /*存放随机序列*/ 
  28.  
  29.     SSL *ssl; 
  30.     const SSL_METHOD *meth; 
  31.     SSL_CTX *ctx; 
  32.  
  33.     //SSL初始化 
  34.     OpenSSL_add_ssl_algorithms(); 
  35.     //SSL错误信息初始化 
  36.     SSL_load_error_strings(); 
  37.  
  38.     //创建本次会话所使用的协议
  39.     meth = TLSv1_client_method(); 
  40.     //申请SSL会话的环境 
  41.     ctx = SSL_CTX_new(meth); 
  42.     if (NULL == ctx) 
  43.         exit(1); 
  44.     
  45.     //设置会话的握手方式并加载CA证书
  46.     SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 
  47.     if (!SSL_CTX_load_verify_locations(ctx, CACERT, NULL))
  48.     {
  49.         printf("%d\n 下载CA 证书出错!\n", SSL_CTX_load_verify_locations(ctx, CACERT, NULL));
  50.         exit(-1);
  51.     }
  52.     
  53.     //加载自己的证书
  54.     if (!SSL_CTX_use_certificate_file(ctx, MYCERTF, SSL_FILETYPE_PEM)) { 
  55.         ERR_print_errors_fp(stdout); 
  56.         printf("\n错误1 %d\n", SSL_CTX_use_certificate_file(ctx, MYCERTF, SSL_FILETYPE_PEM));
  57.         exit(1); 
  58.     } 
  59.     //加载自己的私钥
  60.     if (!SSL_CTX_use_PrivateKey_file(ctx, MYKEYF, SSL_FILETYPE_PEM)) { 
  61.         ERR_print_errors_fp(stderr); 
  62.         exit(1); 
  63.     } 

  64.     //检查自己的证书和私钥是否匹配
  65.     if (!SSL_CTX_check_private_key(ctx)) { 
  66.         printf("\n私钥与证书公钥不匹配!\n"); 
  67.         exit(1); 
  68.     } 

  69.     /*构建随机数生成机制,WIN32平台必需*/ 
  70.     srand((unsigned)time(NULL)); 
  71.     for (int i = 0; i < 100; i++) 
  72.         seed_int[i] = rand(); 
  73.     RAND_seed(seed_int, sizeof(seed_int)); 
  74.  
  75.     //加密方式
  76.     SSL_CTX_set_cipher_list(ctx, "RC4-MD5"); 
  77.     //处理握手多次
  78.     SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); 
  79.  
  80.     /*以下是正常的TCP socket建立过程.............................. */
  81.     SOCKET sock; 
  82.     //printf("Begin tcp socket...\n"); 
  83.     sock = socket(AF_INET, SOCK_STREAM, 0); 
  84.     if (sock == INVALID_SOCKET) { 
  85.         printf("\nSOCKET有问题. \n"); 
  86.     } 
  87.  
  88.     memset(&sin, '\0', sizeof(sin)); 
  89.     sin.sin_family = AF_INET; 
  90.     sin.sin_addr.s_addr = inet_addr(SERVER); /* Server IP */ 
  91.     sin.sin_port = htons(PORT); /* Server Port number */ 
  92.  
  93.     int icnn = connect(sock, (sockaddr *)&sin, sizeof(sin)); 
  94.     if (icnn == SOCKET_ERROR) { 
  95.         printf("\n连不上服务器\n", GetLastError()); 
  96.         exit(1); 
  97.     } 
  98.  
  99.     /* TCP 链接已建立.开始SSL 握手过程.......................... */
  100.     //绑定套接字
  101.     ssl = SSL_new(ctx); 
  102.     if (NULL == ssl) 
  103.         exit(1); 
  104.     if (>= SSL_set_fd(ssl, sock)) { 
  105.         printf("\n连接失败!\n"); 
  106.         exit(1); 
  107.     } 
  108.     //SSL握手
  109.     //SSL_connect(ssl); 
  110.     printf("\n正在连接服务器......\n");
  111.     int k = SSL_connect(ssl); 
  112.     if (!= 1) { 
  113.         printf("%d\n", k); 
  114.         printf("\nSSL connect fail!\n"); 
  115.         exit(1); 
  116.     } 
  117.     printf("\n连接服务器成功\n"); 
  118.  
  119.     char sendmsg[MSGLENGTH] = "\0"; 
  120.     char revmsg[MSGLENGTH] = "\0"; 
  121.  
  122.     int err = SSL_read(ssl, revmsg, sizeof(revmsg)); 
  123.     revmsg[err] = '\0'; 
  124.     printf("%s\n", revmsg); 
  125.  
  126.     while (1) { 
  127.         printf("\n请输入所要发送的数据:\n\n>> "); 
  128.         gets(sendmsg); 
  129.         SSL_write(ssl, sendmsg, strlen(sendmsg)); 
  130.         printf("\n发送消息 %成功!\n", sendmsg); 
  131.         if (!strcmp(sendmsg, "exit"))
  132.         {
  133.             //关闭套接字
  134.             //sleep(1);
  135.             SSL_shutdown(ssl); 
  136.             SSL_free(ssl); 
  137.             SSL_CTX_free(ctx); 
  138.             closesocket(sock); 
  139.             WSACleanup(); 
  140.             getchar(); 
  141.             break;
  142.         }
  143.     } 
  144.     return 0; 
  145. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值