我编写了简单的C程序,它们使用套接字('client'和'server')。 (UNIX / Linux用法)
服务器端只是创建一个套接字:
sockfd = socket(AF_INET, SOCK_STREAM, 0);
然后将其绑定到sockaddr:
bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
并倾听(并接受和阅读):
listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
read(newsockfd,buffer,255);
客户端创建套接字,然后写入它。
现在,我想将这个简单的连接转换为SSL连接,以最简洁,最田园,最新和最快的方式。
我尝试将OpenSSL添加到我的项目中,但我找不到一种简单的方法来实现我想要的内容。
答案 0 :(得分:132)
使用OpenSSL时有几个步骤。您必须拥有一个SSL证书,该证书可以包含带有私钥的证书,请务必指定证书的确切位置(此示例将其包含在根目录中)。那里有很多很好的教程。
有些包括:
#include <openssl/applink.c>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
您需要初始化OpenSSL:
void InitializeSSL()
{
SSL_load_error_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
}
void DestroySSL()
{
ERR_free_strings();
EVP_cleanup();
}
void ShutdownSSL()
{
SSL_shutdown(cSSL);
SSL_free(cSSL);
}
现在有大部分功能。您可能希望在连接上添加while循环。
int sockfd, newsockfd;
SSL_CTX *sslctx;
SSL *cSSL;
InitializeSSL();
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd< 0)
{
//Log and Error
return;
}
struct sockaddr_in saiServerAddress;
bzero((char *) &saiServerAddress, sizeof(saiServerAddress));
saiServerAddress.sin_family = AF_INET;
saiServerAddress.sin_addr.s_addr = serv_addr;
saiServerAddress.sin_port = htons(aPortNumber);
bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
sslctx = SSL_CTX_new( SSLv23_server_method());
SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE);
int use_cert = SSL_CTX_use_certificate_file(sslctx, "/serverCertificate.pem" , SSL_FILETYPE_PEM);
int use_prv = SSL_CTX_use_PrivateKey_file(sslctx, "/serverCertificate.pem", SSL_FILETYPE_PEM);
cSSL = SSL_new(sslctx);
SSL_set_fd(cSSL, newsockfd );
//Here is the SSL Accept portion. Now all reads and writes must use SSL
ssl_err = SSL_accept(cSSL);
if(ssl_err <= 0)
{
//Error occurred, log and close down ssl
ShutdownSSL();
}
然后您可以使用以下方式进行读写:
SSL_read(cSSL, (char *)charBuffer, nBytesToRead);
SSL_write(cSSL, "Hi :3\n", 6);
<强>更新强>
应使用最适合您需求的TLS方法调用SSL_CTX_new
,以支持较新版本的安全性,而不是SSLv23_server_method()
。看到:
OpenSSL SSL_CTX_new description
TLS_method(),TLS_server_method(),TLS_client_method()。 这些是通用的版本 - 灵活的 SSL / TLS方法。使用的实际协议版本将协商为客户端和服务器相互支持的最高版本。支持的协议是SSLv3,TLSv1,TLSv1.1,TLSv1.2和TLSv1.3。
答案 1 :(得分:16)
OpenSSL非常困难。通过不完全正确地进行谈判,很容易意外地丢弃所有安全措施。 (哎呀,我个人被一个卷曲没有完全正确读取OpenSSL警报的错误所困扰,并且无法与某些网站交谈。)
如果您真的想快速而简单,请将stud放在您的计划前面,每天拨打电话。在不同的流程中使用SSL不会减慢您的速度:http://vincent.bernat.im/en/blog/2011-ssl-benchmark.html
答案 2 :(得分:7)
对于像我这样的人:
如果您下载SSL源代码,则会有一个目录demos/ssl/
,其中包含c ++中的示例代码:
https://github.com/openssl/openssl/tree/master/demos/ssl
更新:他们已删除该演示。现在它只能通过历史记录获得: https://github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl 您可能必须找到一个可用的版本,我最初在2015年11月6日发布了这个答案。我不得不编辑源代码 - 并不多。
证书:demos/certs/apps/
中的.pem:
https://github.com/openssl/openssl/tree/master/demos/certs/apps
答案 3 :(得分:0)
这里是我的示例ssl套接字服务器线程(多个连接)https://github.com/breakermind/CppLinux/blob/master/QtSslServerThreads/breakermindsslserver.cpp
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <iostream>
#include <breakermindsslserver.h>
using namespace std;
int main(int argc, char *argv[])
{
BreakermindSslServer boom;
boom.Start(123,"/home/user/c++/qt/BreakermindServer/certificate.crt", "/home/user/c++/qt/BreakermindServer/private.key");
return 0;
}