OpenSSL socket 服务端

Posted thinkinc999

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenSSL socket 服务端相关的知识,希望对你有一定的参考价值。

这是我从网上找来改好的,需要添加 include 和 lib 路径

需要自己手动生成 pem 文件,在注释里面有命行,自己动手。


  1 #define WIN32_LEAN_AND_MEAN
  2 
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <errno.h>
  6 #include <string.h>
  7 #include <sys/types.h>
  8 #include <Windows.h>
  9 #include <WinSock2.h>
 10 #include <MSWSock.h>
 11 #include <WS2tcpip.h>
 12 #include <openssl/ssl.h>
 13 #include <openssl/err.h>
 14 #pragma comment(lib, "ws2_32.lib")
 15 #pragma comment(lib, "libssl.lib")
 16 #pragma comment(lib, "libcrypto.lib")
 17 #pragma comment(lib, "Crypt32.lib")
 18 
 19 // openssl 生成公钥和私钥的方法:
 20 // openssl genrsa -out privkey.pem 2048 
 21 // openssl req -config openssl.cnf -new -x509 -key privkey.pem -out cacert.pem -days 1095
 22 
 23 #define MAXBUF 1024
 24 
 25 /************关于本文档*********************************************
 26  ************filename: ssl-server.c
 27  *************purpose: 演示利用 OpenSSL 库进行基于 IP层的 SSL 加密通讯的方法,这是服务器端例子
 28  **********************************************************************************/
 29 
 30 #define bzero ZeroMemory
 31 #define close closesocket
 32 
 33 SSL_CTX *ctx;
 34 bool InitSslAll(char* publicPem, char* privatePem)
 35 {
 36     /* SSL 库初始化 */
 37     SSL_library_init();
 38 
 39     /* 载入所有 SSL 算法 */
 40     OpenSSL_add_all_algorithms();
 41 
 42     /* 载入所有 SSL 错误消息 */
 43     SSL_load_error_strings();
 44 
 45     /* 以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Content Text */
 46     ctx = SSL_CTX_new(SSLv23_server_method());
 47 
 48     /* 也可以用 SSLv2_server_method() 或 SSLv3_server_method() 单独表示 V2 或 V3标准 */
 49     if (ctx == NULL) {
 50         ERR_print_errors_fp(stdout);
 51         return false;
 52     }
 53 
 54     /* 载入用户的数字证书, 此证书用来发送给客户端。 证书里包含有公钥 */
 55     if (SSL_CTX_use_certificate_file(ctx, publicPem, SSL_FILETYPE_PEM) <= 0)
 56     {
 57         ERR_print_errors_fp(stdout);
 58         return false;
 59     }
 60 
 61     /* 载入用户私钥 */
 62     if (SSL_CTX_use_PrivateKey_file(ctx, privatePem, SSL_FILETYPE_PEM) <= 0)
 63     {
 64         ERR_print_errors_fp(stdout);
 65         return false;
 66     }
 67 
 68     /* 检查用户私钥是否正确 */
 69     if (!SSL_CTX_check_private_key(ctx))
 70     {
 71         ERR_print_errors_fp(stdout);
 72         return false;
 73     }
 74     return true;
 75 }
 76 
 77 int main(int argc, char **argv){
 78     SOCKET sockfd, new_fd;
 79     socklen_t len;
 80     struct sockaddr_in my_addr, their_addr;
 81     unsigned int myport, lisnum;
 82     char buf[MAXBUF + 1];
 83 
 84     if (argv[1])
 85         myport = atoi(argv[1]);
 86     else
 87         myport = 7838;
 88     if (argv[2])
 89         lisnum = atoi(argv[2]);
 90     else
 91         lisnum = 2;
 92 
 93     InitSslAll(argv[4], argv[5]);
 94 
 95     WSADATA wsaData;
 96     int iResult = 0;
 97     iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
 98     if (iResult != NO_ERROR) {
 99         wprintf(L"Error at WSAStartup()
");
100         return 1;
101     }
102 
103     /* 开启一个 socket 监听 */
104     if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
105     {
106         perror("socket");
107         exit(1);
108     } else
109         printf("socket created
");
110 
111     bzero(&my_addr, sizeof(my_addr));
112     my_addr.sin_family = PF_INET;
113     my_addr.sin_port = htons(myport);
114     if (argv[3])
115             inet_pton(AF_INET, argv[3], &my_addr.sin_addr.s_addr);
116     else
117         my_addr.sin_addr.s_addr = INADDR_ANY;
118 
119     if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))        == -1)
120     {
121         printf("bind error:%d", WSAGetLastError());
122         exit(1);
123     }
124     else
125         printf("binded
");
126 
127     if (listen(sockfd, lisnum) == -1)
128     {
129         printf("listen error:%d", WSAGetLastError());
130         exit(1);
131     } else
132         printf("begin listen
");
133 
134         while (1)
135         {
136             SSL *ssl;
137             len = sizeof(struct sockaddr);
138 
139             /* 等待客户端连上来 */
140             if ((new_fd =accept(sockfd, (struct sockaddr *) &their_addr,&len)) == -1)
141             {
142                 printf("accept error:%d", WSAGetLastError());
143                 exit(errno);
144             }
145             else
146             {
147                 char addr[64] = { 0 };
148 
149                 inet_ntop(AF_INET, &their_addr.sin_addr, addr, 64);
150                 printf("server: got connection from %s, port %d, socket %d
"
151                     , addr,    ntohs(their_addr.sin_port), new_fd);
152             }
153 
154 
155             /* 基于 ctx 产生一个新的 SSL */
156             ssl = SSL_new(ctx);
157 
158             /* 将连接用户的 socket 加入到 SSL */
159 
160             SSL_set_fd(ssl, new_fd);
161 
162             /* 建立 SSL 连接 */
163 
164             if (SSL_accept(ssl) == -1)
165             {
166                 perror("accept");
167                 close(new_fd);
168                 break;
169             }
170 
171             /* 开始处理每个新连接上的数据收发 */
172 
173             bzero(buf, MAXBUF + 1);
174             strcpy_s(buf, MAXBUF, "server->client");
175 
176             /* 发消息给客户端 */
177             len = SSL_write(ssl, buf, strlen(buf));
178             if (len <= 0) {
179                 char err[256] = { 0 };
180                 strerror_s(err, errno);
181                 printf("消息‘%s‘发送失败!错误代码是%d,错误信息是‘%s‘
",
182                     buf, errno, err);
183                 goto finish;
184             } else
185                 printf("消息‘%s‘发送成功,共发送了%d个字节!
",
186                     buf, len);
187             bzero(buf, MAXBUF + 1);
188 
189             /* 接收客户端的消息 */
190             len = SSL_read(ssl, buf, MAXBUF);
191             if (len > 0)
192                 printf("接收消息成功:‘%s‘,共%d个字节的数据
",
193                     buf, len);
194             else
195             {
196                 char err[256] = { 0 };
197                 strerror_s(err, errno);
198                 printf("消息接收失败!错误代码是%d,错误信息是‘%s‘
",
199                     errno, err);
200             }
201 
202 
203             /* 处理每个新连接上的数据收发结束 */
204         finish:
205 
206             /* 关闭 SSL 连接 */
207             SSL_shutdown(ssl);
208             /* 释放 SSL */
209             SSL_free(ssl);
210 
211             /* 关闭 socket */
212 
213             close(new_fd);
214         }
215 
216     /* 关闭监听的 socket */
217 
218     close(sockfd);
219 
220     /* 释放 CTX */
221 
222     SSL_CTX_free(ctx);
223 
224     return 0;
225 
226 }
227 
228 

以上是关于OpenSSL socket 服务端的主要内容,如果未能解决你的问题,请参考以下文章

golang代码片段(摘抄)

linux openssl 编程 Client端

用openssl生成SSL使用的私钥和证书,并自己做CA签名

用openssl生成的ssl证书和付费的有啥区别

[网络编程]Win32 Socket+OpenSSL实例

java socket编写服务端