【问题标题】:TLS 1.2 implementation in C++ Windows Application using OpenSSL使用 OpenSSL 在 C++ Windows 应用程序中实现 TLS 1.2
【发布时间】:2022-01-18 12:16:08
【问题描述】:

我有一个作为客户端工作并安装在多个设备上的 Windows 应用程序,它们可以相互通信,现在我想加密通信。我试图找出一些方法,比如微软的 SSPI 库和 SChannel,但没有找到一个简单的实现,所以我正在尝试使用 OpenSSL。

我正在尝试使用 winsocket 创建客户端和服务器,并在 Visual Studio 2019 中使用 OpenSSL 启用 TLS 通信。问题是它连接到服务器,服务器打印连接到客户端的消息,并且客户端代码显示已连接,但是在 SSL_Connect 方法上它失败并且在客户端代码中没有显示错误!我还创建了一个普通的 TCP 套接字服务器并尝试将其连接到此服务器,但连接后它也失败了。

怎么了!这是我的代码:

客户:

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <errno.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <WS2tcpip.h>
#include <string>
#include <iostream>

#pragma comment (lib, "ws2_32.lib")

#define FAIL    -1

//Added the LoadCertificates how in the server-side makes.    
void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
    /* set the local certificate from CertFile */
    if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    /* set the private key from KeyFile (may be the same as CertFile) */
    if (SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    /* verify private key */
    if (!SSL_CTX_check_private_key(ctx))
    {
        fprintf(stderr, "Private key does not match the public certificate\n");
        abort();
    }
}

int OpenConnection(const char* hostname, int port)
{
    int sd;
    struct hostent* host;
    struct sockaddr_in addr;
    WSAData data;
    WORD ver = MAKEWORD(2, 2);
    int wsResult = WSAStartup(ver, &data);
    if (wsResult != 0)
    {
        printf("winsock error");
        return 0;
    }

    if ((host = gethostbyname(hostname)) == NULL)
    {
        perror(hostname);
        abort();
    }
    sd = socket(PF_INET, SOCK_STREAM, 0);
    ZeroMemory(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = *(long*)(host->h_addr);
    if (connect(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0)
    {
        closesocket(sd);
        perror(hostname);
        abort();
    }
    return sd;
}

SSL_CTX* InitCTX(void)
{
    const SSL_METHOD* method = TLS_client_method(); /* Create new client-method instance */
    SSL_CTX* ctx;

    OpenSSL_add_all_algorithms();  /* Load cryptos, et.al. */
    SSL_load_error_strings();   /* Bring in and register error messages */
   // method = SSLv3_client_method();  /* Create new client-method instance */
    ctx = SSL_CTX_new(method);   /* Create new context */
    if (ctx == NULL)
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    return ctx;
}

void ShowCerts(SSL* ssl)
{
    X509* cert;
    char* line;

    cert = SSL_get_peer_certificate(ssl); /* get the server's certificate */
    if (cert != NULL)
    {
        printf("Server certificates:\n");
        line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
        printf("Subject: %s\n", line);
        free(line);       /* free the malloc'ed string */
        line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
        printf("Issuer: %s\n", line);
        free(line);       /* free the malloc'ed string */
        X509_free(cert);     /* free the malloc'ed certificate copy */
    }
    else
        printf("No certificates.\n");
}

int main()
{
    SSL_CTX* ctx;
    int server;
    SSL* ssl;
    char buf[1024];
    int bytes;
    char hostname[] = "127.0.0.1";
    char portnum[] = "54000";
    char CertFile[] = "C:/Users/cert/Documents/testing/ec_crt.pem";
    char KeyFile[] = "C:/Users/cert/Documents/testing/private-key.pem";

    SSL_library_init();

    ctx = InitCTX();
    LoadCertificates(ctx, CertFile, KeyFile);
    
    printf("clinet certificate loaded");
    server = OpenConnection(hostname, atoi(portnum));
    ssl = SSL_new(ctx);      /* create new SSL connection state */
    SSL_set_fd(ssl, server);    /* attach the socket descriptor */
    if (SSL_connect(ssl) == FAIL)   /* perform the connection */ {
        printf("Connection failed");
        ERR_print_errors_fp(stderr);
    }
    else
    {
        const char* msg = "Hello???";

        printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
        ShowCerts(ssl);        /* get any certs */
        SSL_write(ssl, msg, strlen(msg));   /* encrypt & send message */
        bytes = SSL_read(ssl, buf, sizeof(buf)); /* get reply & decrypt */
        buf[bytes] = 0;
        printf("Received: \"%s\"\n", buf);
        SSL_free(ssl);        /* release connection state */
    }
    closesocket(server);         /* close socket */
    SSL_CTX_free(ctx);        /* release context */
    return 0;
}

服务器:

//SSL-Server.c

#include <errno.h>

#include <malloc.h>
#include <string.h>

#include <sys/types.h>


#include "openssl/ssl.h"
#include "openssl/err.h"
#include <WS2tcpip.h>
#include <string>

#pragma comment (lib, "ws2_32.lib")


#define FAIL    -1

int OpenListener(int port)
{
    int sd;
    struct sockaddr_in addr;
    WSAData data;
    WORD ver = MAKEWORD(2, 2);
    int wsResult = WSAStartup(ver, &data);
    if (wsResult != 0)
    {
        printf("winsock error");
        return 0;
    }

    sd = socket(PF_INET, SOCK_STREAM, 0);
    ZeroMemory(&addr, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;
    if (bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0)
    {
        perror("can't bind port");
        abort();
    }
    if (listen(sd, 10) != 0)
    {
        perror("Can't configure listening port");
        abort();
    }
    listen(sd, SOMAXCONN);
    return sd;
}

SSL_CTX* InitServerCTX(void)
{
    const SSL_METHOD* method = TLS_client_method(); /* Create new client-method instance */
    SSL_CTX* ctx;

    OpenSSL_add_all_algorithms();  /* load & register all cryptos, etc. */
    SSL_load_error_strings();   /* load all error messages */
    
    ctx = SSL_CTX_new(method);   /* create new context from method */
    if (ctx == NULL)
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    return ctx;
}

void LoadCertificates(SSL_CTX* ctx, char* CertFile, char* KeyFile)
{
    //New lines 
    if (SSL_CTX_load_verify_locations(ctx, CertFile, KeyFile) != 1)
        ERR_print_errors_fp(stderr);

    if (SSL_CTX_set_default_verify_paths(ctx) != 1)
        ERR_print_errors_fp(stderr);
    //End new lines

    /* set the local certificate from CertFile */
    if (SSL_CTX_use_certificate_file(ctx, CertFile, SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    /* set the private key from KeyFile (may be the same as CertFile) */
    if (SSL_CTX_use_PrivateKey_file(ctx, KeyFile, SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
    /* verify private key */
    if (!SSL_CTX_check_private_key(ctx))
    {
        fprintf(stderr, "Private key does not match the public certificate\n");
        abort();
    }

    //New lines - Force the client-side have a certificate
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
    SSL_CTX_set_verify_depth(ctx, 4);
    //End new lines
}

void ShowCerts(SSL* ssl)
{
    X509* cert;
    char* line;

    cert = SSL_get_peer_certificate(ssl); /* Get certificates (if available) */
    if (cert != NULL)
    {
        printf("Server certificates:\n");
        line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
        printf("Subject: %s\n", line);
        free(line);
        line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
        printf("Issuer: %s\n", line);
        free(line);
        X509_free(cert);
    }
    else
        printf("No certificates.\n");
}

void Servlet(SSL* ssl) /* Serve the connection -- threadable */
{
    char buf[1024];
    char reply[1024];
    int sd, bytes;
    const char* HTMLecho = "<html><body><pre>%s</pre></body></html>\n\n";

    if (SSL_accept(ssl) == FAIL)     /* do SSL-protocol accept */
        ERR_print_errors_fp(stderr);
    else
    {
        ShowCerts(ssl);        /* get any certificates */
        bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
        if (bytes > 0)
        {
            buf[bytes] = 0;
            printf("Client msg: \"%s\"\n", buf);
           // sprintf(reply, HTMLecho, buf);   /* construct reply */
            SSL_write(ssl, reply, strlen(reply)); /* send reply */
        }
        else
            ERR_print_errors_fp(stderr);
    }
    sd = SSL_get_fd(ssl);       /* get socket connection */
    SSL_free(ssl);         /* release SSL state */
    closesocket(sd);          /* close connection */
}

int main()
{
    SSL_CTX* ctx;
    int server;
    char portnum[] = "54000";

    char CertFile[] = "C:/Users/cert/Documents/testing/ec_crt.pem";
    char KeyFile[] = "C:/Users/cert/Documents/testing/private-key.pem";

    SSL_library_init();

    ctx = InitServerCTX();        /* initialize SSL */
    LoadCertificates(ctx, CertFile, KeyFile); /* load certs */
    printf("Certificate loaded");
    server = OpenListener(atoi(portnum));    /* create server socket */
    while (1)
    {
        struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        SSL* ssl;

        int client = accept(server, (struct sockaddr*)&addr, &len);  /* accept connection as usual */
        //printf("Connection: %s:%d\n", inet_ntop(addr.sin_addr), ntohs(addr.sin_port));
        printf("Connected");
        ssl = SSL_new(ctx);              /* get new SSL state with context */
        SSL_set_fd(ssl, client);      /* set connection socket to SSL state */
        Servlet(ssl);         /* service connection */
    }
    closesocket(server);          /* close server socket */
    SSL_CTX_free(ctx);         /* release context */
}

【问题讨论】:

    标签: c++ visual-c++ openssl visual-studio-2019 tls1.2


    【解决方案1】:

    也许你需要使用:

    const SSL_METHOD* method = TLS_server_method();
    

    InitServerCtx()?

    【讨论】:

    • 它已经在那里了!
    猜你喜欢
    • 2021-10-26
    • 2016-06-26
    • 2015-09-01
    • 2019-08-03
    • 2020-08-21
    • 2017-11-15
    • 2018-12-23
    • 2019-02-14
    • 1970-01-01
    相关资源
    最近更新 更多