复用SSL_SESSION时是否保留原X.509对等证书?代码崩溃咨询
SSL会话复用后对等证书的获取与内存管理问题
先直接给你答案:复用SSL_SESSION后,默认通过SSL_get_peer_certificate()无法可靠获取原始的X.509对等证书,这也是你遇到certinfo->key->pkey字段混乱、程序崩溃的核心原因。
为什么会出现这个问题?
不管是OpenSSL还是LibreSSL,SSL_SESSION对象和对等X.509证书的耦合性确实很弱:
- 第一次握手后,你通过
SSL_get1_session()保存的会话,并不会持有对等证书的强引用。证书的内存生命周期默认和原始SSL连接绑定,当原始SSL对象被销毁、或者证书被自动释放后,会话里指向证书的指针就变成了悬空指针。 - 第二次简短握手时,服务端不会重新发送完整证书,客户端的SSL库也不会自动从会话中恢复完整证书数据,此时调用
SSL_get_peer_certificate()要么返回NULL,要么返回指向已被回收内存的无效指针,进而导致你看到的字段混乱和崩溃。
解决方法:手动管理对等证书的引用计数
要在会话复用后安全访问原始证书,你需要显式保存证书并维护其引用计数,具体步骤如下:
第一次握手后:保存会话+单独保存证书
握手完成后,除了调用SSL_get1_session()保存会话,还要调用SSL_get_peer_certificate()获取证书,并用X509_up_ref()增加引用计数,确保证书不会被自动释放:// 第一次握手成功后 SSL *ssl_conn = ...; // 你的SSL连接实例 SSL_SESSION *session = SSL_get1_session(ssl_conn); X509 *peer_cert = SSL_get_peer_certificate(ssl_conn); if (peer_cert != NULL) { X509_up_ref(peer_cert); // 增加引用,避免后续被SSL库自动释放 // 将session和peer_cert关联保存(比如用自定义结构体、哈希表等) save_session_with_cert(session, peer_cert); } else { // 处理证书获取失败的情况 SSL_SESSION_free(session); }第二次握手时:复用会话+使用保存的证书
设置会话完成简短握手后,如果SSL_get_peer_certificate()返回无效结果,直接使用你之前保存的证书:// 建立新的SSL连接并复用会话 SSL *new_ssl_conn = ...; SavedSessionPair *saved_pair = load_saved_session(); // 自定义加载逻辑 SSL_set_session(new_ssl_conn, saved_pair->session); // 执行简短握手... X509 *usable_cert = SSL_get_peer_certificate(new_ssl_conn); if (usable_cert == NULL || !is_certificate_valid(usable_cert)) { // 使用自己保存的证书,记得按需增加引用计数 usable_cert = saved_pair->cert; X509_up_ref(usable_cert); } // 安全使用证书的字段,比如certinfo->key->pkey... // 释放临时引用 X509_free(usable_cert); // 不再需要时释放会话和证书 SSL_SESSION_free(saved_pair->session); X509_free(saved_pair->cert);额外注意事项
- 务必记得在不再需要证书时调用
X509_free()释放,避免内存泄漏; - 即使复用会话成功,建议重新验证证书的有效性(比如有效期、签名、域名匹配等),防止会话劫持或证书过期带来的安全风险;
- OpenSSL和LibreSSL在这部分逻辑上表现一致,上述方案对两者都适用。
- 务必记得在不再需要证书时调用
内容的提问来源于stack exchange,提问作者Chul-Woong Yang
相关产品推荐
相关产品推荐

