如何通过OpenSSL API获取TLS 1.3握手使用的密钥协商算法?
TLS 1.3 下获取实际密钥交换与认证算法的方法
问题根源
TLS 1.3的密码套件设计不再与特定密钥交换、认证方式绑定,因此SSL_CIPHER相关接口返回Kx=any属于预期行为,无法通过SSL_CIPHER_get_kx_nid这类接口拿到实际协商的算法。
解决方案
使用OpenSSL提供的SSL_SESSION相关接口即可读取握手完成后实际协商的参数,相关接口在OpenSSL 1.1.1及以上版本(即首个支持TLS 1.3的正式版本)均可用。
核心接口说明
SSL_get_session(ssl):从SSL对象中获取当前会话的SSL_SESSION实例,需在握手完成后调用SSL_SESSION_get_kx_nid(session):返回实际使用的密钥交换算法NID,如NID_kx_ecdhe、NID_kx_dheSSL_SESSION_get_auth_nid(session):返回实际使用的认证算法NID,如NID_auth_rsa、NID_auth_ecdsa
代码示例
// 需确保握手已完成后再执行以下代码 if (SSL_is_init_finished(ssl)) { SSL_SESSION *sess = SSL_get_session(ssl); if (sess != NULL) { // 获取密钥交换算法 int kx_nid = SSL_SESSION_get_kx_nid(sess); printf("实际密钥交换算法NID: %d\n", kx_nid); printf("实际密钥交换算法名称: %s\n", OBJ_nid2ln(kx_nid)); // 获取认证算法 int auth_nid = SSL_SESSION_get_auth_nid(sess); printf("实际认证算法NID: %d\n", auth_nid); printf("实际认证算法名称: %s\n", OBJ_nid2ln(auth_nid)); } }
输出示例(连接random.org的实际返回)
实际密钥交换算法NID: 1034 实际密钥交换算法名称: ECDH 实际认证算法NID: 1057 实际认证算法名称: RSA
注意事项
- 若握手使用了PSK类无证书认证方式,认证算法会返回对应PSK相关的NID
- 如果需要区分普通ECDH和临时ECDH(ECDHE),可额外调用
SSL_SESSION_get_flags判断是否设置了SSL_SESS_FLAG_EARLY_DATA之外的临时密钥相关标识,TLS 1.3默认使用的都是临时密钥交换模式。
内容的提问来源于stack exchange,提问作者Teja Juluru
相关产品推荐
相关产品推荐

