HTTPS Server 加速
1. 证书在 ESP32 里的存在形式(新旧相同)
项目里证书是编译进固件的,不是运行时导入:
| 项 | 位置 |
|---|---|
| 证书/私钥文件 | main/server_cert.pem、main/server_key.pem |
| 嵌入方式 | main/CMakeLists.txt 的 EMBED_TXTFILES |
| 代码取用 | asm("_binary_server_cert_pem_start") / _binary_server_key_pem_start 符号,在 eastron_webserver_tls_init() 里填入 conf.servercert / conf.prvtkey_pem |
| 烧录 | 随固件 bin 直接写进 flash,不需要单独分区或文件系统步骤 |
2. 旧证书(RSA 2048)
从旧证书文件读到的特征:RSA 2048、sha256WithRSAEncryption 签名、CN=P1 HTTPS SERVER、有效期 2026-01-13 ~ 2125-12-20(100 年)、自签、无 SAN。
我这边看不到你当年的原始命令,等价的标准生成命令是:
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout server_key.pem -out server_cert.pem \
-days 36500 -subj "/CN=P1 HTTPS SERVER"
(-nodes 表示私钥不加密,mbedTLS 需要裸私钥。)
3. 新证书(ECDSA P-256)——本次更换
动机:ESP32-S3 没有 RSA 硬件加速,RSA-2048 私钥运算是纯软件,是握手最慢的一步;曲线 P-256 的签名只有 1~3ms,快一个量级。
生成命令(实测于本机 OpenSSL 3.6.3;注意 macOS 自带 LibreSSL 太老,建议用 openssl version 确认 ≥1.1.1,不支持 -addext 时可用 ext 文件):
# 1. 生成 EC 私钥(SEC1 格式)
openssl ecparam -genkey -name prime256v1 -out key_sec1.pem
# 2. 转成 PKCS8 裸私钥(与原来 RSA 私钥的文件格式一致)
openssl pkcs8 -topk8 -nocrypt -in key_sec1.pem -out server_key.pem
# 3. 生成自签证书(带 SAN,Chrome 才能"继续访问")
openssl req -new -x509 -key server_key.pem -out server_cert.pem -days 3650 \
-subj "/CN=P1 HTTPS SERVER" \
-addext "subjectAltName=IP:192.168.4.1,DNS:localhost" \
-addext "basicConstraints=critical,CA:FALSE" \
-addext "keyUsage=critical,digitalSignature" \
-addext "extendedKeyUsage=serverAuth"
验证命令:
openssl x509 -in server_cert.pem -noout -text | grep -E "Public Key Algorithm|Signature Algorithm"
openssl pkey -in server_key.pem -noout -text | head -3 # 确认 256 bit
openssl x509 -noout -pubkey -in server_cert.pem | cmp - <(openssl pkey -pubout -in server_key.pem) # 证书/私钥必须匹配
要点:文件名保持不变 → EMBED_TXTFILES 生成的符号不变 → 代码不用改。浏览器首次访问自签证书仍会提示"不受信任",点高级 → 继续访问;加了 IP:192.168.4.1 的 SAN 后 Chrome 允许继续。
4. ESP32 侧本次的配置改动
代码(eastron_platform/eastron_webserver.c 的 eastron_webserver_tls_init()):
conf.session_tickets = true; // 新增: 允许客户端session ticket快速重连
原有配置不变:keep_alive_enable = true、lru_purge_enable = true、max_open_sockets = 7、stack_size = 8192。
Kconfig(sdkconfig.defaults 和生成文件 sdkconfig 都要改,否则不生效):
CONFIG_ESP_TLS_SERVER_SESSION_TICKETS=y
CONFIG_ESP_TLS_SERVER_SESSION_TICKET_TIMEOUT=86400 # 票据有效期 1 天
依赖项(须已开启):CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y、CONFIG_ESP_TLS_USING_MBEDTLS=y。
踩过的坑(教训):只改 conf.session_tickets = true 而不同步开 Kconfig 选项 → httpd_ssl_start() 里 esp_tls_cfg_server_session_tickets_init() 返回 ESP_ERR_NOT_SUPPORTED,goto exit → 整个 HTTPS 服务器启动失败,表现为"完全访问不了"。所以这两处必须成对改。
session ticket 的效果:客户端重新建连时走 1-RTT 快速握手,跳过证书签名运算;如果浏览器 keep-alive 一直复用连接,影响较小,主要收益在页面刷新/重新打开时。
5. 排查遗留(确认稳定后记得还原)
| 配置 | 状态 | 说明 |
|---|---|---|
CONFIG_HEAP_POISONING_COMPREHENSIVE=y | 排查用 | 抓堆越界写,定位完应改回 CONFIG_HEAP_POISONING_DISABLED |
# CONFIG_MBEDTLS_DYNAMIC_BUFFER(已注释) | 排查用 | 当前 mbedTLS 用静态 16KB 缓冲,稳定后可考虑恢复动态缓冲 |
| 旧证书备份 | 在 /tmp/server_cert.pem.rsa.bak 等 | /tmp 重启会清空,建议挪回项目目录保存 |
要不要我把这份笔记落成一个文件(比如仓库里的 docs/https-cert-notes.md),方便你以后查?