HTTPS

目录

一、基础核心

[1. HTTPS 的定义:HTTP + TLS/SSL](#1. HTTPS 的定义:HTTP + TLS/SSL)

[2. HTTP vs HTTPS](#2. HTTP vs HTTPS)

[3. HTTPS 的核心三要素:对称加密、非对称加密、数字证书](#3. HTTPS 的核心三要素:对称加密、非对称加密、数字证书)

[4. HTTPS 的加密组合逻辑](#4. HTTPS 的加密组合逻辑)

二、补充知识点

[1. HTTPS 的核心作用是什么?与 HTTP 的本质区别是什么?](#1. HTTPS 的核心作用是什么?与 HTTP 的本质区别是什么?)

[2. 为什么 HTTPS 要同时使用对称加密和非对称加密?](#2. 为什么 HTTPS 要同时使用对称加密和非对称加密?)

[3. HTTPS 完整握手流程](#3. HTTPS 完整握手流程)

[阶段 1:客户端问候(Client Hello)](#阶段 1:客户端问候(Client Hello))

[阶段 2:服务端问候(Server Hello)](#阶段 2:服务端问候(Server Hello))

[阶段 3:客户端验证证书 + 生成会话密钥](#阶段 3:客户端验证证书 + 生成会话密钥)

[阶段 4:服务端生成会话密钥 + 双向确认](#阶段 4:服务端生成会话密钥 + 双向确认)

握手完成后:对称加密传输数据

[4. 前向保密(Forward Secrecy)](#4. 前向保密(Forward Secrecy))

[5. 易错点](#5. 易错点)

[三、基于 OpenSSL 实现 HTTPS 通信](#三、基于 OpenSSL 实现 HTTPS 通信)

[1. 环境搭建与依赖安装](#1. 环境搭建与依赖安装)

[2. 生成自签名证书(用于测试)](#2. 生成自签名证书(用于测试))

[3. HTTPS 服务端实现(C++)](#3. HTTPS 服务端实现(C++))

[4. HTTPS 客户端实现(C++)](#4. HTTPS 客户端实现(C++))

[5. 编译与运行(Linux 环境)](#5. 编译与运行(Linux 环境))

四、优化

[1. 性能优化:降低 TLS 握手开销](#1. 性能优化:降低 TLS 握手开销)

[会话复用(Session Resumption)](#会话复用(Session Resumption))

[OCSP Stapling(在线证书状态协议装订)](#OCSP Stapling(在线证书状态协议装订))

[2. 安全加固:抵御常见攻击](#2. 安全加固:抵御常见攻击)

[3. Linux 调试工具:排查 HTTPS 问题](#3. Linux 调试工具:排查 HTTPS 问题)


一、基础核心

1. HTTPS 的定义:HTTP + TLS/SSL

HTTPS 不是新协议,而是HTTP 协议的安全版本 ------ 在 HTTP 与 TCP 之间增加了TLS/SSL(传输层安全 / 安全套接层)协议层,核心作用是:

  • 加密通信:防止数据在传输过程中被窃听、篡改;
  • 身份认证:验证服务端(可选客户端)的真实身份,避免中间人攻击;
  • 数据完整性:确保数据传输过程中未被修改。
2. HTTP vs HTTPS
维度 HTTP HTTPS
安全级别 明文传输,无加密、无认证,高危 加密传输,身份认证,安全
端口 默认 80 默认 443
核心层 应用层直接基于 TCP 应用层→TLS/SSL 层→TCP 层
加密方式 对称加密 + 非对称加密 + 数字证书
性能 无额外开销,速度快 TLS 握手有额外开销,速度略慢(可优化)
证书需求 无需 需 CA 签发的数字证书(测试可用自签名)
3. HTTPS 的核心三要素:对称加密、非对称加密、数字证书

HTTPS 的安全基石是 "对称加密 + 非对称加密 + 数字证书" 的组合拳,单独使用某一种加密方式都存在缺陷:

对称加密:高效的 "会话密钥" 传输

  • 原理 :通信双方共用一个会话密钥,加密和解密使用同一密钥(如 AES 算法);
  • 优点:加密 / 解密速度极快(适合大数据量传输),CPU 开销小;
  • 缺点:密钥传输存在风险 ------ 若密钥在网络中明文传输,会被中间人截获,导致加密失效。

非对称加密:安全的 "密钥交换"

  • 原理 :生成一对密钥 ------公钥 (公开给所有人)和私钥 (服务端私藏);
    • 公钥加密的数据,只有私钥能解密;
    • 私钥加密的数据,只有公钥能解密(用于数字签名);
  • 优点:无需传输密钥,公钥公开,私钥不泄露,解决了对称加密的密钥传输问题;
  • 缺点:加密 / 解密速度极慢(比对称加密慢 100-1000 倍),不适合大数据量传输。

数字证书:解决 "公钥信任" 问题

  • 核心痛点:若中间人伪造服务端公钥,客户端无法区分真假;
  • 数字证书作用:由权威 CA(证书颁发机构)签发,证明 "服务端公钥与服务端身份的绑定关系";
  • 证书内容:服务端公钥、服务端域名、CA 签名、证书有效期等。
4. HTTPS 的加密组合逻辑

握手阶段用非对称加密传输 "对称加密的会话密钥",数据传输阶段用对称加密传输实际数据

  • 非对称加密解决 "会话密钥的安全传输" 问题;
  • 对称加密解决 "大数据量传输的性能" 问题;
  • 数字证书解决 "公钥的信任" 问题。

二、补充知识点

1. HTTPS 的核心作用是什么?与 HTTP 的本质区别是什么?

HTTPS 的核心作用是加密通信、身份认证、数据完整性校验 ;与 HTTP 的本质区别是增加了TLS/SSL 协议层

  1. HTTP 明文传输,数据可被窃听、篡改;HTTPS 加密传输,数据安全;
  2. HTTP 默认 80 端口,HTTPS 默认 443 端口;
  3. HTTP 无需证书,HTTPS 需 CA 签发的数字证书;
  4. HTTP 性能无额外开销,HTTPS 因 TLS 握手存在一定性能开销。
2. 为什么 HTTPS 要同时使用对称加密和非对称加密?
  • 非对称加密速度慢,仅用于握手阶段传输对称加密的会话密钥------ 避免密钥明文传输的风险;
  • 对称加密速度快,用于实际数据传输阶段------ 解决非对称加密的性能瓶颈;
  • 二者结合,兼顾安全性性能
3. HTTPS 完整握手流程

TLS 1.2 单向认证(服务端认证,客户端不认证,最常用)为例,完整握手分为4 个阶段

阶段 1:客户端问候(Client Hello)
  1. 客户端向服务端发送 TLS 版本(如 TLS 1.2)、支持的加密套件(如 AES_256_GCM_SHA384)、随机数 1(Client Random);
  2. 加密套件:包含对称加密算法、非对称加密算法、哈希算法的组合。
阶段 2:服务端问候(Server Hello)
  1. 服务端确认 TLS 版本、选择加密套件、发送随机数 2(Server Random);
  2. 服务端发送数字证书(包含服务端公钥、域名、CA 签名等);
  3. 服务端发送 "Server Hello Done",表示问候结束。
阶段 3:客户端验证证书 + 生成会话密钥
  1. 客户端验证证书合法性 (核心步骤,防中间人攻击):
    • 验证证书是否过期;
    • 验证证书中的域名是否与服务端域名一致;
    • 验证 CA 签名是否有效(用 CA 公钥解密签名,对比证书内容的哈希值);
    • (可选)验证证书链(避免证书伪造);
  2. 客户端生成预主密钥 (Pre-Master Secret),用服务端公钥加密后发送给服务端;
  3. 客户端用随机数 1 + 随机数 2 + 预主密钥 ,通过加密套件约定的算法生成会话密钥(对称加密密钥)。
阶段 4:服务端生成会话密钥 + 双向确认
  1. 服务端用私钥解密预主密钥;
  2. 服务端用同样的 "随机数 1 + 随机数 2 + 预主密钥" 生成会话密钥(与客户端一致);
  3. 服务端发送 "Change Cipher Spec",通知客户端后续用会话密钥加密通信;
  4. 服务端发送 "Finished" 消息(用会话密钥加密),客户端验证通过后,确认服务端合法;
  5. 客户端发送 "Change Cipher Spec" 和 "Finished" 消息,服务端验证通过后,握手完成。
握手完成后:对称加密传输数据

后续所有 HTTP 请求和响应,都通过会话密钥进行对称加密,实现高效、安全的传输。

4. 前向保密(Forward Secrecy)

普通 RSA 握手的问题:若服务端私钥泄露,历史通信数据可被解密;

ECDHE 握手:每次握手生成全新的临时密钥对,预主密钥基于临时密钥对生成,即使私钥泄露,历史数据也无法解密 ------ 工业级项目建议优先使用 ECDHE 加密套件。

5. 易错点
  • 误区 1:HTTPS 是完全加密的,中间人无法破解 → 错!若客户端跳过证书验证(如代码中设置 SSL_VERIFY_NONE),中间人可伪造证书,实现数据窃听;
  • 误区 2:数字证书是加密数据的 → 错!数字证书不加密数据,仅用于证明公钥的合法性;
  • 误区 3 :TLS 握手只需要一次 → 错!若会话过期或客户端重启,需重新握手;可通过会话复用优化;
  • 误区 4:HTTPS 的性能瓶颈在对称加密 → 错!性能瓶颈在 TLS 握手(非对称加密),数据传输的对称加密开销极小;
  • 误区 5:自签名证书可用于生产环境 → 错!自签名证书无法通过 CA 验证,客户端会提示 "不安全",仅用于测试。

三、基于 OpenSSL 实现 HTTPS 通信

1. 环境搭建与依赖安装
cpp 复制代码
# Ubuntu/Debian
sudo apt-get install libssl-dev openssl -y

# CentOS/RHEL
sudo yum install openssl-devel openssl -y
2. 生成自签名证书(用于测试)

生产环境需使用 CA 签发的证书(如 Let's Encrypt 免费证书),测试环境用自签名证书:

cpp 复制代码
# 生成服务端私钥(2048位,RSA算法,权限600防止泄露)
openssl genrsa -out server.key 2048
chmod 600 server.key

# 生成证书签名请求(CSR),填写域名(如localhost)、组织等信息
openssl req -new -key server.key -out server.csr

# 生成自签名证书(有效期365天)
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

# 查看证书信息
openssl x509 -in server.crt -text -noout
3. HTTPS 服务端实现(C++)

核心逻辑:创建 SSL 上下文→加载证书和私钥→创建 TCP socket→TLS 握手→数据通信。

cpp 复制代码
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

// 初始化OpenSSL库(工业级必做,仅调用一次)
void init_openssl() {
    SSL_library_init();          // 初始化SSL库
    OpenSSL_add_all_algorithms();// 加载所有加密算法
    SSL_load_error_strings();    // 加载错误信息
}

// 创建SSL上下文(指定TLS版本,禁用老旧版本)
SSL_CTX* create_ssl_context() {
    // TLSv1_2_server_method:仅支持TLS 1.2,禁用TLS 1.0/1.1
    const SSL_METHOD* method = TLSv1_2_server_method();
    SSL_CTX* ctx = SSL_CTX_new(method);
    if (!ctx) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
    return ctx;
}

// 配置SSL上下文:加载证书和私钥
void configure_ssl_context(SSL_CTX* ctx, const char* cert_file, const char* key_file) {
    // 加载服务端证书(.crt)
    if (SSL_CTX_use_certificate_file(ctx, cert_file, SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
    // 加载服务端私钥(.key)
    if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
    // 验证私钥与证书是否匹配(工业级必做)
    if (!SSL_CTX_check_private_key(ctx)) {
        fprintf(stderr, "Private key does not match the certificate public key\n");
        exit(EXIT_FAILURE);
    }
}

int main(int argc, char** argv) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <port>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    int port = atoi(argv[1]);

    // 1. 初始化OpenSSL
    init_openssl();
    SSL_CTX* ctx = create_ssl_context();
    configure_ssl_context(ctx, "server.crt", "server.key");

    // 2. 创建TCP socket(IPv4,流式,TCP)
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 3. 绑定socket到端口(复用端口,避免TIME_WAIT导致的绑定失败)
    int opt = 1;
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
        perror("setsockopt failed");
        exit(EXIT_FAILURE);
    }
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY; // 监听所有网卡
    server_addr.sin_port = htons(port);
    if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 4. 监听端口(最大等待队列长度10)
    if (listen(sockfd, 10) < 0) {
        perror("listen failed");
        exit(EXIT_FAILURE);
    }
    printf("HTTPS server listening on port %d...\n", port);

    // 5. 接受客户端连接并处理
    while (true) {
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        // 接受TCP连接
        int client_fd = accept(sockfd, (struct sockaddr*)&client_addr, &client_len);
        if (client_fd < 0) {
            perror("accept failed");
            continue;
        }
        printf("Client connected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        // 6. 创建SSL对象,关联客户端socket
        SSL* ssl = SSL_new(ctx);
        SSL_set_fd(ssl, client_fd);

        // 7. TLS握手(服务端调用SSL_accept)
        if (SSL_accept(ssl) <= 0) {
            ERR_print_errors_fp(stderr);
        } else {
            // 8. 读取客户端请求(HTTPS请求,已加密)
            char buf[1024] = {0};
            int bytes_read = SSL_read(ssl, buf, sizeof(buf) - 1);
            if (bytes_read > 0) {
                buf[bytes_read] = '\0';
                printf("Received from client:\n%s\n", buf);

                // 9. 发送响应(HTTP 200 OK,加密传输)
                const char* response = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 16\r\n\r\nHello HTTPS Client!";
                SSL_write(ssl, response, strlen(response));
            }
        }

        // 10. 释放资源(工业级必做,避免内存泄漏)
        SSL_shutdown(ssl);
        SSL_free(ssl);
        close(client_fd);
    }

    // 11. 清理全局资源
    SSL_CTX_free(ctx);
    close(sockfd);
    return 0;
}
4. HTTPS 客户端实现(C++)

核心逻辑:创建 SSL 上下文→加载 CA 证书(验证服务端证书)→连接服务端→TLS 握手→数据通信。

cpp 复制代码
#include <iostream>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

// 初始化OpenSSL库
void init_openssl() {
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
}

// 创建SSL上下文(客户端)
SSL_CTX* create_ssl_context() {
    const SSL_METHOD* method = TLSv1_2_client_method();
    SSL_CTX* ctx = SSL_CTX_new(method);
    if (!ctx) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
    return ctx;
}

// 配置SSL上下文:加载CA证书(验证服务端证书)
// 测试环境:加载自签名证书作为CA;生产环境:加载系统CA证书(如/etc/ssl/certs)
void configure_ssl_context(SSL_CTX* ctx, const char* ca_file) {
    // 加载CA证书(用于验证服务端证书)
    if (SSL_CTX_load_verify_locations(ctx, ca_file, NULL) <= 0) {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
    // 开启证书验证(工业级必做,禁止设置为SSL_VERIFY_NONE)
    SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
    SSL_CTX_set_verify_depth(ctx, 1);
}

int main(int argc, char** argv) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <server_ip> <port>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    const char* server_ip = argv[1];
    int port = atoi(argv[2]);

    // 1. 初始化OpenSSL
    init_openssl();
    SSL_CTX* ctx = create_ssl_context();
    // 测试环境:加载自签名的server.crt作为CA证书
    configure_ssl_context(ctx, "server.crt");

    // 2. 创建TCP socket
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 3. 连接服务端
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    if (inet_pton(AF_INET, server_ip, &server_addr.sin_addr) <= 0) {
        perror("invalid server ip");
        exit(EXIT_FAILURE);
    }
    if (connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("connect failed");
        exit(EXIT_FAILURE);
    }
    printf("Connected to %s:%d\n", server_ip, port);

    // 4. 创建SSL对象,关联socket
    SSL* ssl = SSL_new(ctx);
    SSL_set_fd(ssl, sockfd);
    // 设置服务端域名(用于SNI,多域名证书必备)
    SSL_set_tlsext_host_name(ssl, server_ip);

    // 5. TLS握手(客户端调用SSL_connect)
    if (SSL_connect(ssl) <= 0) {
        ERR_print_errors_fp(stderr);
    } else {
        printf("TLS handshake success\n");
        // 打印服务端证书信息(工业级调试用)
        X509* cert = SSL_get_peer_certificate(ssl);
        if (cert) {
            char* subject = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0);
            printf("Server certificate subject: %s\n", subject);
            free(subject);
            X509_free(cert);
        }

        // 6. 发送HTTPS请求(GET /)
        const char* request = "GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n";
        SSL_write(ssl, request, strlen(request));

        // 7. 读取服务端响应
        char buf[1024] = {0};
        int bytes_read = SSL_read(ssl, buf, sizeof(buf) - 1);
        if (bytes_read > 0) {
            buf[bytes_read] = '\0';
            printf("Received from server:\n%s\n", buf);
        }
    }

    // 8. 释放资源
    SSL_shutdown(ssl);
    SSL_free(ssl);
    close(sockfd);
    SSL_CTX_free(ctx);
    return 0;
}
5. 编译与运行(Linux 环境)

编译命令(链接 OpenSSL 库)

cpp 复制代码
# 编译服务端
g++ -std=c++17 https_server.cpp -o https_server -lssl -lcrypto
# 编译客户端
g++ -std=c++17 https_client.cpp -o https_client -lssl -lcrypto

运行服务端

cpp 复制代码
./https_server 4433  # 监听4433端口(普通用户无法使用443端口)

运行客户端

cpp 复制代码
./https_client 127.0.0.1 4433

输出

  • 服务端:HTTPS server listening on port 4433...Client connected: 127.0.0.1:xxxx → 打印客户端请求;
  • 客户端:Connected to 127.0.0.1:4433TLS handshake success → 打印服务端响应。

四、优化

1. 性能优化:降低 TLS 握手开销

TLS 握手是 HTTPS 的性能瓶颈,工业级项目需通过以下手段优化:

会话复用(Session Resumption)
  • 原理:握手成功后,服务端和客户端保存会话信息(会话 ID / 会话票据),下次连接时复用会话,无需重新握手;
  • 实现
    • 会话 ID:服务端保存会话信息,客户端下次握手携带会话 ID;
    • 会话票据(TLS Ticket):服务端用密钥加密会话信息发送给客户端,客户端保存票据,无需服务端存储;
  • 代码配置SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
OCSP Stapling(在线证书状态协议装订)
  • 问题:客户端验证证书时,需向 CA 查询证书是否吊销,增加网络延迟;
  • 原理:服务端主动从 CA 获取证书吊销状态,绑定到 TLS 握手过程中发送给客户端,减少客户端查询次数;
  • 代码配置SSL_CTX_set_tlsext_status_type(ctx, TLSEXT_STATUSTYPE_ocsp);
2. 安全加固:抵御常见攻击
  • 加密套件选择 :优先选择支持前向保密的套件(如ECDHE-RSA-AES256-GCM-SHA384),禁用弱加密套件(如RC4MD5);
    • 配置:SSL_CTX_set_cipher_list(ctx, "ECDHE-RSA-AES256-GCM-SHA384:HIGH:!aNULL:!MD5:!RC4");
  • 私钥保护 :服务端私钥权限设置为600,避免泄露;生产环境建议用硬件安全模块(HSM)存储私钥;
  • 防重放攻击:TLS 握手的随机数保证每次会话密钥唯一,防止重放攻击;
  • 证书链配置:若使用 CA 签发的证书,需配置完整的证书链(包含根证书、中间证书),避免客户端验证失败。
3. Linux 调试工具:排查 HTTPS 问题

OpenSSL 命令行工具(最常用)

cpp 复制代码
# 测试服务端TLS配置
openssl s_client -connect localhost:4433 -tls1_2 -CAfile server.crt

# 查看服务端支持的加密套件
openssl ciphers -v 'ECDHE-RSA-AES256-GCM-SHA384'

# 验证证书与私钥是否匹配
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5
# 输出一致则匹配

Wireshark 抓包分析

  • 过滤条件:tls → 可查看 TLS 握手的每个阶段的数据包,分析握手过程是否正常;
  • 关键点:查看Client HelloServer HelloCertificateFinished等数据包。
相关推荐
筱谙4 小时前
BES BLE低功耗蓝牙技术实现分析
服务器·网络·网络协议
2301_780789664 小时前
2025年UDP洪水攻击防护实战全解析:从T级流量清洗到AI智能防御
服务器·网络·人工智能·网络协议·安全·web安全·udp
Anthony_2315 小时前
二、IP地址与子网划分
服务器·网络·网络协议·tcp/ip·http·https·udp
H_ZMY6 小时前
前端实现 HTTPS 强制跳转与移动端域名自动适配
前端·网络协议·https
vHXIxsckCTh7 小时前
C#与产电PLC串口通信库,本库支持多线程访问 C# For LS PLC Serial Port
https
德迅云安全杨德俊7 小时前
安全加速SCDN防护原理及其与DDoS攻击的协同防御策略方案
安全·web安全·https·ddos
水上冰石8 小时前
测试环境生成https自签名证书tls的步骤
linux·服务器·https
徐同保8 小时前
OnlyOffice HTTPS 代理配置总结
redis·网络协议·https
zzZ··*8 小时前
自动登录上海大学校园
python·网络协议·selenium