欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++中如何實(shí)現(xiàn)SSL/TLS加密通信

 更新時(shí)間:2025年01月11日 09:47:42   作者:希望睿智的技術(shù)小屋  
在互聯(lián)網(wǎng)時(shí)代,確保信息傳輸過(guò)程中的機(jī)密性、完整性和可用性成為了開發(fā)者必須考慮的關(guān)鍵因素,在C++網(wǎng)絡(luò)編程中,使用SSL/TLS加密通信是一種常見的做法,它允許客戶端和服務(wù)器之間通過(guò)互聯(lián)網(wǎng)安全地交換信息,從而為網(wǎng)絡(luò)通信提供隱私性和數(shù)據(jù)完整性

概述

在互聯(lián)網(wǎng)時(shí)代,數(shù)據(jù)的安全性變得尤為重要。隨著網(wǎng)絡(luò)安全威脅的不斷增加,確保信息傳輸過(guò)程中的機(jī)密性、完整性和可用性成為了開發(fā)者必須考慮的關(guān)鍵因素。在C++網(wǎng)絡(luò)編程中,使用SSL/TLS加密通信是一種常見的做法。它允許客戶端和服務(wù)器之間通過(guò)互聯(lián)網(wǎng)安全地交換信息,從而為網(wǎng)絡(luò)通信提供隱私性和數(shù)據(jù)完整性。

SSL,英文全稱為Secure Sockets Layer,最初由Netscape公司在1990年代開發(fā),用于保護(hù)Web瀏覽器與服務(wù)器間的通信。TLS,英文全稱為Transport Layer Security,是IETF標(biāo)準(zhǔn)化后的版本,可以看作是SSL的繼承者。盡管名字不同,但兩者提供的功能非常相似,通常會(huì)把它們統(tǒng)稱為“SSL/TLS”。

C++網(wǎng)絡(luò)編程之SSL/TLS加密通信_(tái)網(wǎng)絡(luò)編程

基本概念

SSL/TLS:一種用于在兩個(gè)通信應(yīng)用程序之間提供保密性和數(shù)據(jù)完整性的協(xié)議。

證書:一種數(shù)字文檔,包含了一個(gè)實(shí)體的信息及其公鑰。它由一個(gè)可信賴的第三方機(jī)構(gòu)(CA,即Certificate Authority)簽發(fā),以證明該實(shí)體的身份。

公鑰/私鑰: 每個(gè)參與者都有一對(duì)密鑰,主要用于非對(duì)稱加密算法。公鑰公開給所有人,用于加密或驗(yàn)證簽名。私鑰則保密保存,僅用于解密或創(chuàng)建簽名。這保證了即使數(shù)據(jù)被攔截,沒(méi)有私鑰也無(wú)法讀取其內(nèi)容。非對(duì)稱加密算法的安全性在于:計(jì)算上難以從公鑰推導(dǎo)出私鑰。常見的非對(duì)稱加密算法包括:RSA、ECC等。

會(huì)話密鑰:一旦客戶端與服務(wù)器建立了信任關(guān)系,就會(huì)生成一個(gè)臨時(shí)的對(duì)稱密鑰,來(lái)進(jìn)行后續(xù)的數(shù)據(jù)加密和解密工作。對(duì)稱加密算法因?yàn)槠浼用芙饷芩俣瓤欤诖罅繑?shù)據(jù)傳輸中非常有用。常用的對(duì)稱加密算法有:AES、DES等。

公鑰/私鑰與會(huì)話密鑰之間的主要關(guān)系在于:安全地建立對(duì)稱加密會(huì)話。具體來(lái)說(shuō),有如下兩個(gè)主要步驟。

1、使用非對(duì)稱加密來(lái)安全地交換會(huì)話密鑰。比如:小王可以使用小張的公鑰加密一個(gè)會(huì)話密鑰,并將它發(fā)送給小張;只有擁有相應(yīng)私鑰的小張,才能解密該會(huì)話密鑰。

2、一旦會(huì)話密鑰被安全地交換,小王和小張就可以使用這個(gè)會(huì)話密鑰,并通過(guò)對(duì)稱加密算法來(lái)加密實(shí)際傳輸?shù)臄?shù)據(jù)。

API接口

OpenSSL是一個(gè)開源軟件包,提供了豐富的函數(shù)用于實(shí)現(xiàn)SSL/TLS加密通信,一些常用的API如下。

SSL_CTX_new:創(chuàng)建一個(gè)新的SSL上下文。

SSL_CTX_use_certificate_file:用于設(shè)置證書文件路徑。

SSL_CTX_use_PrivateKey_file:用于設(shè)置私鑰文件路徑。

SSL_new:根據(jù)給定的SSL上下文創(chuàng)建一個(gè)新的SSL結(jié)構(gòu)體實(shí)例。

SSL_set_fd:將已有的socket描述符綁定至SSL對(duì)象上。

SSL_connect:客戶端調(diào)用此函數(shù)開始SSL握手過(guò)程。

SSL_accept:服務(wù)端調(diào)用此函數(shù)開始SSL握手過(guò)程。

SSL_read:用于讀取加密后的數(shù)據(jù)流。

SSL_write:用于寫入加密后的數(shù)據(jù)流。

SSL_shutdown:發(fā)起關(guān)閉SSL連接的過(guò)程。

使用OpenSSL庫(kù)進(jìn)行SSL/TLS加密通信的主要步驟如下。

1、初始化OpenSSL庫(kù)。通常情況下,我們需要調(diào)用SSL_library_init等函數(shù)來(lái)初始化環(huán)境。

2、創(chuàng)建SSL上下文。使用SSL_CTX_new創(chuàng)建一個(gè)新的SSL_CTX對(duì)象,并配置相關(guān)的選項(xiàng)。比如:選擇使用的協(xié)議版本為TLSv1.2、TLSv1.3等。

3、加載證書文件。如果作為服務(wù)端運(yùn)行,則需要加載自己的證書及私鑰。如果是客戶端,則可能需要指定CA證書列表,以驗(yàn)證服務(wù)器的身份。

4、建立普通套接字連接。與普通的TCP/IP編程一樣,先完成兩臺(tái)機(jī)器之間的基本連接。

5、將普通套接字轉(zhuǎn)換成SSL套接字。通過(guò)SSL_set_fd函數(shù),關(guān)聯(lián)已有的Socket句柄與SSL結(jié)構(gòu)體。

6、握手。雙方交換各自的信息,并協(xié)商加密算法、生成共享的密鑰等。這一過(guò)程,通過(guò)SSL_connect或SSL_accept函數(shù)完成。

7、數(shù)據(jù)傳輸。使用SSL_read和SSL_write代替標(biāo)準(zhǔn)的read和write操作,以確保所有發(fā)送和接收的數(shù)據(jù)都是加密的。

8、關(guān)閉連接。正常情況下,應(yīng)先調(diào)用SSL_shutdown()進(jìn)行優(yōu)雅斷開,之后再關(guān)閉底層socket。

在C++中如何進(jìn)行SSL/TLS加密通信,可參考下面服務(wù)端的代碼。

#include <iostream>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstdlib>

using namespace std;

int main()
{
    if (OPENSSL_init_crypto(0, nullptr) != 1)
    {
        cout << "Failed to initialize OpenSSL crypto library." << endl;
        exit(EXIT_FAILURE);
    }

    if (OPENSSL_init_ssl(0, nullptr) != 1)
    {
        cout << "Failed to initialize OpenSSL SSL library." << endl;
        exit(EXIT_FAILURE);
    }

    // 使用最新的TLS版本
    const SSL_METHOD *method = TLS_server_method();
    SSL_CTX *ctx = SSL_CTX_new(method);
    if (ctx == nullptr)
    {
        ERR_print_errors_fp(stdout);
        exit(EXIT_FAILURE);
    }

    // 配置服務(wù)器證書
    if (SSL_CTX_use_certificate_file(ctx, "server.crt", SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stdout);
        exit(EXIT_FAILURE);
    }

    // 配置服務(wù)器私鑰
    if (SSL_CTX_use_PrivateKey_file(ctx, "server.key", SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stdout);
        exit(EXIT_FAILURE);
    }

    // 檢查私鑰是否匹配證書
    if (!SSL_CTX_check_private_key(ctx))
    {
        cout << "Private key does not match the certificate public key." << endl;
        exit(EXIT_FAILURE);
    }

    // 開啟監(jiān)聽
    int serverSock = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSock < 0)
    {
        cout << "Failed to create socket." << endl;
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(443);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(serverSock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
    {
        cout << "Failed to bind socket." << endl;
        exit(EXIT_FAILURE);
    }

    listen(serverSock, 5);
    while (true)
    {
        cout << "Wait client connecting..." << endl;

        struct sockaddr_in client_addr;
        socklen_t addr_len = sizeof(client_addr);
        int clientSock = accept(serverSock, (struct sockaddr*)&client_addr, &addr_len);

        SSL *pSsl = SSL_new(ctx);
        // 關(guān)聯(lián)已有的Socket句柄與SSL結(jié)構(gòu)體
        SSL_set_fd(pSsl, clientSock);

        // 執(zhí)行握手
        if (SSL_accept(pSsl) <= 0)
        {
            ERR_print_errors_fp(stdout);
        }
        else
        {
            char pBuff[1024] = { 0 };
            int nBytesReceived = SSL_read(pSsl, pBuff, sizeof(pBuff) - 1);
            if (nBytesReceived > 0)
            {
                cout << "Received msg: " << pBuff << endl;

                // 向客戶端回傳消息
                string strRsp = "Hello from Hope Wisdom";
                SSL_write(pSsl, strRsp.c_str(), strRsp.size());
            }
        }

        SSL_free(pSsl);
        close(clientSock);
    }

    close(serverSock);
    SSL_CTX_free(ctx);
    return 0;
}

雙向認(rèn)證

通常情況下,對(duì)于標(biāo)準(zhǔn)的HTTPS連接(比如:瀏覽器訪問(wèn)一個(gè)安全網(wǎng)站),客戶端并不需要提供自己的證書或私鑰。服務(wù)器會(huì)向客戶端發(fā)送其證書,客戶端使用預(yù)置的信任根證書來(lái)驗(yàn)證服務(wù)器的身份。

然而,在某些對(duì)安全性要求更高的場(chǎng)景下,比如:企業(yè)內(nèi)部網(wǎng)絡(luò)、金融交易系統(tǒng)等,服務(wù)器可能會(huì)要求客戶端也提供證書以證明自己的身份。這種機(jī)制,被稱為雙向認(rèn)證。當(dāng)客戶端也需要進(jìn)行身份驗(yàn)證時(shí),除了要驗(yàn)證服務(wù)器提供的證書外,還需要準(zhǔn)備好自己的證書和私鑰,并將它們配置到SSL/TLS上下文中。

下面的示例代碼,演示了客戶端程序如何設(shè)置證書與私鑰來(lái)完成雙向認(rèn)證。

#include <iostream>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

using namespace std;

int main() 
{
    if (OPENSSL_init_crypto(0, nullptr) != 1)
    {
        cout << "Failed to initialize OpenSSL crypto library." << endl;
        exit(EXIT_FAILURE);
    }

    if (OPENSSL_init_ssl(0, nullptr) != 1)
    {
        cout << "Failed to initialize OpenSSL SSL library." << endl;
        exit(EXIT_FAILURE);
    }

    // 使用最新的TLS版本
    const SSL_METHOD *method = TLS_client_method();
    SSL_CTX *ctx = SSL_CTX_new(method);
    if (ctx == NULL)
    {
        ERR_print_errors_fp(stdout);
        exit(EXIT_FAILURE);
    }

    // 配置客戶端證書
    if (SSL_CTX_use_certificate_file(ctx, "client.crt", SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stdout);
        exit(EXIT_FAILURE);
    }

    // 配置客戶端私鑰
    if (SSL_CTX_use_PrivateKey_file(ctx, "client.key", SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stdout);
        exit(EXIT_FAILURE);
    }

    // 創(chuàng)建socket
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        cout << "Failed to create socket." << endl;
        return -1;
    }

    // 設(shè)置服務(wù)器地址
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(443);
    // 假設(shè)服務(wù)器IP為本地回環(huán)地址
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);

    // 連接到服務(wù)器
    if (connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
    {
        cout << "Failed to connect" << endl;
        close(sock);
        return -1;
    }

    SSL *pSsl = SSL_new(ctx);
    // 關(guān)聯(lián)已有的Socket句柄與SSL結(jié)構(gòu)體
    SSL_set_fd(pSsl, sock);

    // 執(zhí)行握手
    if (SSL_connect(pSsl) <= 0)
    {
        ERR_print_errors_fp(stdout);
        goto end;
    }

    // 發(fā)送消息給服務(wù)器
    const char* pMsg = "Hi, Hope Wisdom";
    SSL_write(pSsl, pMsg, strlen(pMsg));

    // 接收響應(yīng)
    char pBuff[1024] = {0};
    int nBytesReceived = SSL_read(pSsl, pBuff, sizeof(pBuff) - 1);
    if (nBytesReceived > 0)
    {
        cout << "Received msg: " << pBuff << endl;
    }
    else
    {
        cout << "Failed to receive msg" << endl;
    }

end:
    SSL_free(pSsl);
    close(sock);
    SSL_CTX_free(ctx);
    return 0;
}

在上面的示例代碼中,client.crt和client.key表示客戶端的證書和私鑰文件。這些文件必須預(yù)先生成好,并放置于程序可以訪問(wèn)的位置。另外,還需要確保服務(wù)端已正確配置允許客戶端認(rèn)證,并且加載了用于驗(yàn)證客戶端證書的CA證書。

至于服務(wù)端如何配置,可參考下面的示例代碼。

// 設(shè)置驗(yàn)證模式為需要客戶端證書
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);

// 加載CA證書
if (SSL_CTX_load_verify_locations(ctx, "ca.crt", nullptr) != 1)
{
    ERR_print_errors_fp(stdout);
    exit(EXIT_FAILURE);
}

在上面的示例代碼中,SSL_CTX_set_verify設(shè)置了客戶端驗(yàn)證策略。我們?cè)O(shè)置了標(biāo)志位SSL_VERIFY_PEERh和SSL_VERIFY_FAIL_IF_NO_PEER_CERT,這意味著服務(wù)端會(huì)強(qiáng)制要求客戶端提供證書。如果客戶端沒(méi)有提供證書,則握手失敗。SSL_CTX_load_verify_locations函數(shù)指定了一個(gè)或多個(gè)CA證書文件的位置,這些證書用于驗(yàn)證客戶端提供的證書是否有效。如果沒(méi)有找到合適的CA證書來(lái)驗(yàn)證客戶端證書,握手也會(huì)失敗。

總結(jié)

到此這篇關(guān)于C++中如何實(shí)現(xiàn)SSL/TLS加密通信的文章就介紹到這了,更多相關(guān)C++中SSL/TLS加密通信內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++實(shí)現(xiàn)簡(jiǎn)單計(jì)算器

    C++實(shí)現(xiàn)簡(jiǎn)單計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • C語(yǔ)言實(shí)現(xiàn)制作通訊錄(新手推薦)

    C語(yǔ)言實(shí)現(xiàn)制作通訊錄(新手推薦)

    本文推薦給C語(yǔ)言學(xué)習(xí)到結(jié)構(gòu)體的新手們,供其練習(xí)。這篇文章主要是利用C語(yǔ)言制作一個(gè)簡(jiǎn)單的通訊錄功能,感興趣的小伙伴可以跟隨小編一起了解一下
    2022-09-09
  • C語(yǔ)言實(shí)現(xiàn)通用數(shù)據(jù)結(jié)構(gòu)之通用鏈表

    C語(yǔ)言實(shí)現(xiàn)通用數(shù)據(jù)結(jié)構(gòu)之通用鏈表

    這篇文章主要為大家詳細(xì)介紹了c語(yǔ)言實(shí)現(xiàn)通用數(shù)據(jù)結(jié)構(gòu)之通用鏈表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • C++ 函數(shù)指針的實(shí)現(xiàn)

    C++ 函數(shù)指針的實(shí)現(xiàn)

    本文主要介紹了C++ 函數(shù)指針的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-02-02
  • C++中vector和數(shù)組之間的轉(zhuǎn)換及其效率問(wèn)題詳解

    C++中vector和數(shù)組之間的轉(zhuǎn)換及其效率問(wèn)題詳解

    c++?vector轉(zhuǎn)數(shù)組是一種將vector容器的元素轉(zhuǎn)換為數(shù)組的方法,主要能幫助提高程序的性能和效率,下面這篇文章主要給大家介紹了關(guān)于C++中vector和數(shù)組之間的轉(zhuǎn)換及其效率問(wèn)題的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • 淺談C++ IO流

    淺談C++ IO流

    這篇文章主要介紹了C++ IO流的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c++,感興趣的朋友可以了解下
    2020-08-08
  • C++使用一棵紅黑樹同時(shí)封裝出map和set實(shí)例代碼

    C++使用一棵紅黑樹同時(shí)封裝出map和set實(shí)例代碼

    紅黑樹(Red?Black?Tre)是一種自平衡二叉查找樹,是在計(jì)算機(jī)科學(xué)中用到的一種數(shù)據(jù)結(jié)構(gòu),典型的用途是實(shí)現(xiàn)關(guān)聯(lián)數(shù)組,下面這篇文章主要給大家介紹了關(guān)于C++使用一棵紅黑樹同時(shí)封裝出map和set的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • C++ 詳細(xì)講解對(duì)象的構(gòu)造順序

    C++ 詳細(xì)講解對(duì)象的構(gòu)造順序

    對(duì)象的構(gòu)造往往和構(gòu)造函數(shù)會(huì)牽扯在一起,構(gòu)造函數(shù)的函數(shù)可能會(huì)由非常復(fù)雜的邏輯所組成,不同類的構(gòu)造函數(shù)的程序邏輯很可能是相互依賴的,當(dāng)這種相互依賴一旦成立,那么對(duì)象的構(gòu)造順序很可能導(dǎo)致難以調(diào)試的Bug出現(xiàn)
    2022-04-04
  • 淺析C++中strlen函數(shù)的使用與模擬實(shí)現(xiàn)strlen的方法

    淺析C++中strlen函數(shù)的使用與模擬實(shí)現(xiàn)strlen的方法

    這篇文章主要介紹了strlen函數(shù)的使用與模擬實(shí)現(xiàn)strlen的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-03-03
  • C語(yǔ)言rand和srand函數(shù)使用方法介紹

    C語(yǔ)言rand和srand函數(shù)使用方法介紹

    rand()函數(shù)用來(lái)產(chǎn)生隨機(jī)數(shù),但是,rand()的內(nèi)部實(shí)現(xiàn)是用線性同余法實(shí)現(xiàn)的,是偽隨機(jī)數(shù),由于周期較長(zhǎng),因此在一定范圍內(nèi)可以看成是隨機(jī)的。srand()用來(lái)設(shè)置rand()產(chǎn)生隨機(jī)數(shù)時(shí)的隨機(jī)數(shù)種子。參數(shù)seed是整數(shù),通??梢岳胻ime(0)或geypid(0)的返回值作為seed
    2023-02-02

最新評(píng)論