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. 生成一把基于 P-256 椭圆曲线的 EC 私钥,并保存为 key_sec1.pem
openssl ecparam -genkey -name prime256v1 -out key_sec1.pem
参数解释
ecparam 椭圆曲线参数工具,支持生成 EC 私钥
-genkey 生成 EC 私钥
-name prime256v1 指定使用的椭圆曲线
-out key_sec1.pem 将生成的私钥写入指定文件
2. 把 key_sec1.pem 中的 EC 私钥转换为 PKCS#8 格式,并保存为 server_key.pem
openssl pkcs8 -topk8 -nocrypt -in key_sec1.pem -out server_key.pem
参数解释
pkcs8 处理 PKCS#8 格式的私钥
-topk8 将输入私钥转换为 PKCS#8 格式
-nocrypt 输出私钥不使用密码加密
-in key_sec1.pem 指定输入的 SEC1 私钥文件
-out server_key.pem 指定输出文件名
3. 使用 server_key.pem 中的 EC 私钥,生成一张有效期为 3650 天的自签名 X.509 服务器证书 server_cert.pem
openssl req -new -x509 -key server_key.pem -out server_cert.pem -days 3650 -subj "/CN=SEM Meter HTTPS Server" -addext "subjectAltName=DNS:eastron-meter.local" -addext "basicConstraints=critical,CA:FALSE" -addext "keyUsage=critical,digitalSignature" -addext "extendedKeyUsage=serverAuth"
参数解释
参数 含义
openssl OpenSSL 密码学工具
req 处理证书请求及相关证书操作
-new 创建新的证书相关对象
-x509 直接生成 X.509 证书,而不是普通 CSR
-key server_key.pem 使用已有的服务器私钥
-out server_cert.pem 将生成的证书写入文件
-days 3650 设置有效期为 3650 天,约 10 年
-subj "/CN=SEM Meter HTTPS Server" 设置证书主题中的通用名称
-addext 添加 X.509 扩展字段
验证命令:
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),方便你以后查?