最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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加密通信是一種常見(jiàn)的做法,它允許客戶端和服務(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加密通信是一種常見(jiàn)的做法。它允許客戶端和服務(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)出私鑰。常見(jiàn)的非對(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)聽(tīng)
    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)文章

  • OpenCV相機(jī)標(biāo)定的全過(guò)程記錄

    OpenCV相機(jī)標(biāo)定的全過(guò)程記錄

    這篇文章主要給大家介紹了關(guān)于OpenCV相機(jī)標(biāo)定的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-03-03
  • 解析VScode在Windows環(huán)境下c_cpp_properties.json文件配置問(wèn)題(推薦)

    解析VScode在Windows環(huán)境下c_cpp_properties.json文件配置問(wèn)題(推薦)

    這篇文章主要介紹了解析VScode在Windows環(huán)境下c_cpp_properties.json文件配置問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 深入淺出理解C語(yǔ)言初識(shí)結(jié)構(gòu)體

    深入淺出理解C語(yǔ)言初識(shí)結(jié)構(gòu)體

    C?數(shù)組允許定義可存儲(chǔ)相同類型數(shù)據(jù)項(xiàng)的變量,結(jié)構(gòu)是?C?編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲(chǔ)不同類型的數(shù)據(jù)項(xiàng),本篇讓我們來(lái)了解C?的結(jié)構(gòu)體
    2022-02-02
  • C語(yǔ)言字符串的模式匹配之BF與KMP

    C語(yǔ)言字符串的模式匹配之BF與KMP

    這篇文章記錄一下串里面的模式匹配,模式匹配,顧名思義就是給定一個(gè)被匹配的字符串,然后用一個(gè)字符串模式(模型)去匹配上面說(shuō)的字符串,看后者是否在前者里面出現(xiàn)。常用的有2種算法可以實(shí)現(xiàn),下面我們來(lái)具體探討下
    2021-09-09
  • C++ 逗號(hào)運(yùn)算符的具體使用

    C++ 逗號(hào)運(yùn)算符的具體使用

    本文主要介紹了C++ 逗號(hào)運(yùn)算符的具體使用,使用逗號(hào)運(yùn)算符是為了把幾個(gè)表達(dá)式放在一起,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-08-08
  • C語(yǔ)言圖書管理系統(tǒng)課程設(shè)計(jì)

    C語(yǔ)言圖書管理系統(tǒng)課程設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言圖書管理系統(tǒng)課程設(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 淺析C++中前置聲明的應(yīng)用與陷阱

    淺析C++中前置聲明的應(yīng)用與陷阱

    以下是對(duì)C++中前置聲明的應(yīng)用與陷阱進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-07-07
  • 詳解C++中的內(nèi)存同步模式(memory order)

    詳解C++中的內(nèi)存同步模式(memory order)

    這篇文章主要介紹了C++中的內(nèi)存同步模式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • c++中inline的用法分析

    c++中inline的用法分析

    本篇文章是對(duì)c++中inline的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C語(yǔ)言中堆空間的生成與釋放詳解

    C語(yǔ)言中堆空間的生成與釋放詳解

    以下是對(duì)C語(yǔ)言中堆空間的生成與釋放進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下
    2013-08-08

最新評(píng)論

营山县| 高要市| 云梦县| 南陵县| 淳安县| 武胜县| 聂拉木县| 晋中市| 上蔡县| 舟山市| 绥中县| 昌宁县| 西林县| 山阳县| 丰镇市| 大方县| 澎湖县| 娱乐| 桐乡市| 古交市| 古交市| 青海省| 铜山县| 桐乡市| 青海省| 玉溪市| 铁岭县| 木里| 咸宁市| 刚察县| 五常市| 三台县| 视频| 冕宁县| 健康| 曲阳县| 满洲里市| 博乐市| 航空| 临江市| 富阳市|