文章介绍了 OpenSSL 4.0.0 中新增的 ECH(Encrypted Client Hello)相关能力,并演示了如何用 openssl ech 命令生成 ECH 配置、导出公私钥配置、指定 HPKE/KEM 套件,以及查看支持的 ML-KEM 与混合算法。

我一直很喜欢迎来 OpenSSL 的新版本,而本周我们看到了一个重大版本升级:OpenSSL 4.0.0。
> openssl version
OpenSSL 4.0.0 14 Apr 2026 (Library: OpenSSL 4.0.0 14 Apr 2026)
对于这些选项,我们得到:
> openssl ech -help
Usage: ech [options]
General options options:
-help 显示此摘要
-verbose 提供额外输出
-text 提供人类可读输出
Key generation options:
-out outfile Private key 和/或 ECHConfig [default: echconfig.pem]
-public_name val public_name 值
-max_name_len int 最大主机名长度值 [default: 0]
-suite val HPKE 密码套件:例如 "0x20,1,3"
-ech_version int ECHConfig 版本 [default: 0xff0d (13)]
ECH PEM file downselect/display options:
-in infile 一个 ECH PEM 文件
-select int 下选到编号对应的 ECH config
如果我们想生成一对密钥,首先要定义一个 public name:
> openssl ech -public_name asecuritysite.com -out echconfig.pem
然后我们可以查看 ECH 配置的详细信息:
C:\openssl_4_0\bin>openssl ech -in echconfig.pem -text
ECH entry: 0 public_name: asecuritysite.com age: 0 (has private key) (will be sent in retry-configs)
[fe0d,e2,asecuritysite.com,[0020,0001,0001],\
9db1f8695deb7a7757745cc8661a118b66f5bd4f91a4fedf044652b3de025803,00,00]
接下来我们可以只导出公钥:
C:\openssl_4_0\bin>openssl ech -in echconfig.pem -out ech-public.pem
C:\openssl_4_0\bin>openssl ech -in echconfig.pem -text
> type ech-public.pem
-----BEGIN ECHCONFIG-----
AET+DQBA4gAgACCdsfhpXet6d1d0XMhmGhGLZvW9T5Gk/t8ERlKz3gJYAwAEAAEA
AQARYXNlY3VyaXR5c2l0ZS5jb20AAA==
-----END ECHCONFIG-----
以及私钥(和配置):
C:\openssl_4_0\bin>type echconfig.pem
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VuBCIEIEDG41OApI2ecZeZHX1O2afxtphctAcUw5oYk/G1wOx2
-----END PRIVATE KEY-----
-----BEGIN ECHCONFIG-----
AET+DQBA4gAgACCdsfhpXet6d1d0XMhmGhGLZvW9T5Gk/t8ERlKz3gJYAwAEAAEA
AQARYXNlY3VyaXR5c2l0ZS5jb20AAA==
-----END ECHCONFIG-----
如果愿意,我们还可以为特定的 cipher suite 生成配置,例如使用 KEM_ID、HKDF_ID 和 SYMMETRIC_KEY_ID。在这种情况下,我们定义了 X25519、HKDF-SHA256 和 AES-128-GCM:
openssl ech -public_name example.com -suite x25519,hkdf-sha256,aes-128-gcm
-out echconfig.pem
OpenSSL 4.0.0 的另一个新增内容是加入了中国的 SM2 曲线与 ML-KEM-768:
>openssl list -kem-algorithms
{ 1.2.840.113549.1.1.1, 2.5.8.1.1, RSA, rsaEncryption } @ default
{ 1.2.840.10045.2.1, EC, id-ecPublicKey } @ default
{ 1.3.101.110, X25519 } @ default
{ 1.3.101.111, X448 } @ default
{ 2.16.840.1.101.3.4.4.1, id-alg-ml-kem-512, ML-KEM-512, MLKEM512 } @ default
{ 2.16.840.1.101.3.4.4.2, id-alg-ml-kem-768, ML-KEM-768, MLKEM768 } @ default
{ 2.16.840.1.101.3.4.4.3, id-alg-ml-kem-1024, ML-KEM-1024, MLKEM1024 } @ default
X25519MLKEM768 @ default
X448MLKEM1024 @ default
SecP256r1MLKEM768 @ default
SecP384r1MLKEM1024 @ default
curveSM2MLKEM768 @ default
使用 TLS 的一个主要问题是,当有人连接到某个服务器时,服务器名称会被中间方看到——因为 TLS 握手的前几个部分是明文、可被捕获的。这意味着你的 ISP 和咖啡店的 Wi-Fi 网络可以窥探你的访问行为(但看不到你正在查看的内容细节)。
记住我,以便更快登录
IETF 为 ESNI(Encrypted server name indication)提出了替代方案,并在 TLS 连接中对 Server Name Identification(SNI)进行掩码处理 [ 这里]:

最终,只有用户、受信任的加密主机以及服务器能够看到正在连接的主机。咖啡店仍然可以通过其他方式窥探你,例如目标 IP 地址以及 DNS 查询;但至少这是在支持隐私方面向前迈出的一步。如果你关心 DNS 的隐私,你应该研究 DNS over HTTP(DoH);而对于 IP 地址的遮蔽,可以使用代理。
TLS 连接的问题在于,在建立加密隧道之前,会话的加密密钥尚未定义,因此连接的所有细节都会暴露出来。但是,借助 ECH(Encrypted Hello),我们现在可以与一个代理实体执行握手,这样就无法看到最终服务器连接,而服务器也无法看到是哪个客户端正在连接。最早实现集成 ECH 和 DoH 方案的公司之一是 Cloudflare,他们将这一过程概述如下:

https://blog.cloudflare.com/announcing-encrypted-client-hello/
下面是 TLS 握手的概要:
Cloudflare 最近宣布他们已经实现了 ESNI (encrypted Server Name Indication (SNI) TLS extension)。这旨在阻止 ISP 和公共 Wi-Fi 提供商窥探你的 Web 访问(或任何其他监听你网络数据包的人)。最初的集成是在 Firefox Nightly 中,你可以在这里测试你的浏览器:

Cloudflare 也在推动保护 DNS 请求,同时推进 DNSSEC 和 TLS 1.3。启用 ESNI 后,它应该显示如下:

Cloudflare 已发布 Wireshark 抓包来展示其中的差异。下面显示的是普通 TLS,在 TLS 数据包中我们可以看到服务器名称(cloudflare.com):

如果现在加入加密的 SNI 扩展,我们会得到:

TLS 连接本应是安全并经过隧道传输的,但在最初协商时,通过 Client Hello 我们会暴露服务器名称,而任何监听我们网络数据包的人都能看到它。
使用 ESNI 时,拥有 DNS 记录的服务器会发布其公钥。然后客户端会将 SNI 扩展改为加密版本。所使用的密钥是从服务器公钥派生出的对称密钥(使用 Elliptic Curve Diffie Hellman 密钥交换)。持有对应私钥的服务器也可以派生出相同的对称密钥,并解密该扩展。这只能在 TLS 1.3 及以上版本中工作。在 TLS 1.2 及以下版本中,窃听者可以检查服务器发送给客户端的数字证书,从而确定用户正在连接的网站。
OpenSSL 在修复 TLS 协议中的一个弱点方面做得很好。
- 原文链接: billatnapier.medium.com/...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!