将一个简单的套接字转换为SSL套接字

Dav*_*ape 108 c unix sockets linux ssl

我编写了简单的C程序,它们使用套接字('client'和'server').(UNIX/Linux用法)

服务器端只是创建一个套接字:

sockfd = socket(AF_INET, SOCK_STREAM, 0);
Run Code Online (Sandbox Code Playgroud)

然后将它绑定到sockaddr:

bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
Run Code Online (Sandbox Code Playgroud)

并倾听(并接受和阅读):

listen(sockfd,5);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
read(newsockfd,buffer,255);
Run Code Online (Sandbox Code Playgroud)

客户端创建套接字,然后写入它.

现在,我想将这个简单的连接转换为SSL连接,以最简洁,最田园,最新和最快的方式.

我试图将OpenSSL添加到我的项目中,但我找不到一种简单的方法来实现我想要的东西.

Cap*_*Bli 140

使用OpenSSL时有几个步骤.您必须拥有一个SSL证书,该证书可以包含带有私钥的证书,请务必指定证书的确切位置(此示例将其包含在根目录中).那里有很多很好的教程.

一些包括:

#include <openssl/applink.c>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
Run Code Online (Sandbox Code Playgroud)

您需要初始化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);
}
Run Code Online (Sandbox Code Playgroud)

现在是大部分功能.您可能希望在连接上添加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();
}
Run Code Online (Sandbox Code Playgroud)

然后您可以使用以下方式读取或写入:

SSL_read(cSSL, (char *)charBuffer, nBytesToRead);
SSL_write(cSSL, "Hi :3\n", 6);
Run Code Online (Sandbox Code Playgroud)

更新SSL_CTX_new应该是最适合以支持,而不是安全的新版本,你需要的TLS方法被调用SSLv23_server_method().请参阅: OpenSSL SSL_CTX_new说明

TLS_method(),TLS_server_method(),TLS_client_method(). 这些是通用版本灵活的 SSL/TLS方法.使用的实际协议版本将协商为客户端和服务器相互支持的最高版本.支持的协议是SSLv3,TLSv1,TLSv1.1,TLSv1.2和TLSv1.3.

  • 不像我想的那么"简单",但最后(感谢上帝!)我看到了一些代码.这是跨平台还是仅适用于unix/unix类系统? (9认同)
  • @DevNull`SSLv23_server_method()`表明服务器理解SSLv2和v3,现在已弃用.为了支持TLS 1.1和1.2,用`TLS_server_method()`替换该方法.[源(https://www.openssl.org/docs/manmaster/ssl/SSL_CTX_new.html) (5认同)
  • 我在多个平台上使用过类似的代码:arm,linux和windows. (3认同)
  • 最后`if`虽然错了.它应该是`if(ssl_err <= 0){`只有这样才会出错.`SSL_accept()`成功时返回"1","受控失败"返回"0","致命故障"返回"-1".请参见手册页. (2认同)
  • 此外,如果未调用`SSL_CTX_set_tmp_dh [_callback]()`,DH密码将无法工作.刚刚发现aNULL密码在没有密码的情况下无法正常工作,产生40号警报. (2认同)
  • 为什么要包含.c文件? (2认同)

Bra*_*ncy 16

OpenSSL非常困难.通过不完全正确地进行谈判,很容易意外地丢弃所有安全措施.(哎呀,我一直被个人咬了一个错误,因为curl没有完全正确地阅读OpenSSL警报,并且无法与某些网站交谈.)

如果你真的想要快速和简单,在你的程序前放置螺柱,每天打电话.在不同的流程中使用SSL不会减慢您的速度:http://vincent.bernat.im/en/blog/2011-ssl-benchmark.html

  • 这是一个实际的答案,但它并没有真正回答这个问题. (11认同)
  • STUD在2016年被废弃。自述文件建议:https://github.com/varnish/hitch (3认同)

184*_*615 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日发布了这个答案.我有编辑源 - 不多.

证书:.pem in demos/certs/apps/:https: //github.com/openssl/openssl/tree/master/demos/certs/apps