如何通过OpenSSL的ssl_st结构体获取Client Hello哈希或计算client_early_traffic_secret
问题(翻译自英文)
根据RFC 8446定义,client_early_traffic_secret和early_exporter_master_secret的推导规则如下:
client_early_traffic_secret = Derive-Secret(Early Secret, "c e traffic", ClientHello) early_exporter_master_secret = Derive-Secret(Early Secret, "e exp master", ClientHello)
在OpenSSL 1.1.1稳定版本中,early_exporter_master_secret会在tls13_enc.c的tls13_change_cipher_state()函数中计算并保存到ssl_st结构体中,但client_early_traffic_secret仅被计算却未存储。计算client_early_traffic_secret需要已保存为ssl_st->early_secret的Early Secret,以及未被存储的Client Hello消息哈希。请问:
- 如何仅通过
ssl_st结构体获取Client Hello消息的哈希? - 有没有其他方式通过
ssl_st结构体计算client_early_traffic_secret?
1. 获取Client Hello消息哈希
在OpenSSL 1.1.1的内部实现中,Client Hello的哈希值已经被存储在ssl_st的TLS 1.3专属子结构中,直接访问以下私有字段即可:
- 哈希数据指针:
ssl->s3.tls13->client_hello_hash(类型为unsigned char *) - 哈希数据长度:
ssl->s3.tls13->client_hello_hash_len(类型为size_t)
注意:这些属于OpenSSL内部私有字段,公共头文件
ssl.h不会暴露,因此只有在OpenSSL源码补丁、自定义模块或依赖内部头文件(如ssl/ssl_local.h)的场景下才能直接访问。
2. 计算client_early_traffic_secret
拿到ssl->early_secret(Early Secret)和上述Client Hello哈希后,可通过两种方式推导目标密钥:
方式一:调用OpenSSL内部推导函数
直接使用OpenSSL内置的tls13_derive_secret函数(定义在tls13_enc.c),示例代码如下:
unsigned char client_early_traffic_secret[EVP_MAX_MD_SIZE]; size_t secret_len; tls13_derive_secret(ssl, client_early_traffic_secret, sizeof(client_early_traffic_secret), ssl->early_secret, ssl->s3.tls13->early_secret_len, "c e traffic", ssl->s3.tls13->client_hello_hash, ssl->s3.tls13->client_hello_hash_len, &secret_len);
方式二:手动实现RFC 8446的Derive-Secret流程
Derive-Secret基于HKDF-Expand-Label算法,可复用OpenSSL的HKDF_expand_label函数实现,示例代码:
// 握手使用的哈希算法(如SHA-256) EVP_MD *md = ssl->s3.tls13->hash; unsigned char client_early_traffic_secret[EVP_MAX_MD_SIZE]; size_t secret_len = EVP_MD_size(md); HKDF_expand_label(md, client_early_traffic_secret, secret_len, ssl->early_secret, ssl->s3.tls13->early_secret_len, "c e traffic", ssl->s3.tls13->client_hello_hash, ssl->s3.tls13->client_hello_hash_len);
注意事项
- 以上操作依赖OpenSSL 1.1.1的内部私有结构与函数,若版本升级或内部实现变更,代码可能失效。
- 若在OpenSSL外部程序中调用,需链接静态库或包含内部头文件,同时需注意API兼容性风险。
内容的提问来源于stack exchange,提问作者Blaise Wang

