繁体   English   中英

把简单的插座变成SSL插座

[英]Turn a simple socket into an SSL socket

我编写了简单的 C 程序,这些程序使用 sockets(“客户端”和“服务器”)。 (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添加到我的项目中,但我找不到一种简单的方法来实现我想要的。

使用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);

更新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。

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

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

像我这样的人:

demos/ssl/目录中的SSL源代码中曾经有一个示例,其中包含C ++中的示例代码。 现在它只能通过历史记录获得: https//github.com/openssl/openssl/tree/691064c47fd6a7d11189df00a0d1b94d8051cbe0/demos/ssl

您可能必须找到一个工作版本,我最初在2015年11月6日发布了这个答案。我不得不编辑源代码 - 不多。

证书:.PEM在demos/certs/apps/https://github.com/openssl/openssl/tree/master/demos/certs/apps

这里是我的示例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;
}

就像你看到的那样,它很毛茸茸。 But the "easy" part is, after you've set up your SSL/TLS session with OpenSSL, the pattern you follow to read/write on a socket for HTTPS is the same as the one you follow for HTTP.

不同之处在于您使用SSL_read/SSL_write函数,而不是read/write函数。 SSL_read/SSL_write函数将SSL指针作为其第一个参数,而不是文件描述符。

无论如何,这里是 Unix 环境的完整工作 OpenSSL 示例,带有编译/运行说明、APT 依赖项和参考。 这只是一些更多的工作代码供您使用。

编译成功后,您将看到一条关于已弃用的 OpenSSL function 的警告。

成功运行后,您将看到 example.com 的 TLS 证书主题打印为标准 output,然后是 example.com 的 HTML 内容。

https://github.com/angstyloop/c-web/blob/main/openssl-fetch-example.c

在 Ubuntu 22.04 上测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM