如何使用 libopenssl 重放加密流量?

Gri*_*lov 6 c++ ssl https openssl tcpdump

我们有一个基于 libuv 和 libopenssl 的 HTTP 客户端,用于 TLS,用 C++ 编写 - 它有自己的 TCP 包装器围绕 lubuv 和 HTTP 解析器。

通常它可以正常工作,我们的服务器使用它向社交网络发出数百万个成功的 HTTPS 请求。并且单连接请求从来没有出现过问题,它以“连接:关闭”状态结束。但是,尽管很少见,对于保持活动的连接,有时会发生奇怪的 ssl 错误:

任何一个 error:04067084:rsa routines:rsa_ossl_public_decrypt:data too large for modulus

或者 error:04067072:rsa routines:rsa_ossl_public_decrypt:padding check failed

我相信这是一个非常罕见的问题,百万分之一。当从服务器接收到新数据时,从 SSL_read 返回错误。它永远不会在第一次响应时发生,通常在错误发生之前连接中有十多次请求-响应交换。

我们有使用SSL_CTX_set_keylog_callback接口捕获的此类交换和键盘日志的 tcpdump 。Wireshark 使用 keylog 作为预主密钥文件打开和解密转储,没有任何问题,并包含正常的 HTTP 响应,“200 OK”。对于我们的 HTTP 客户端,最后一个数据包会产生错误。通过检查交易所,我们没有发现任何问题或数据损坏的迹象。这个事实让我假设数据没问题,但我们的 OpenSSL 使用可能不完全正确。

模拟使用 tcpdump 数据发送完全相同响应的服务器是没有问题的。但是我需要使用客户端键盘日志中的预主密钥。我找不到任何将密钥设置为 SSL_CTX* 或 SSL* 的函数。有吗?

我还修改了 libopenssl 以使用常量键。我已经输入memcpy(s->session->master_key, overriden_secret, 48)ssl_generate_master_secrettls13_generate_secret。同样memcpy(s->s3->client_random, overriden_random, 32);tls_construct_client_hellotls_early_post_process_client_hello 中。它不起作用并在握手阶段产生一个 ssl 错误,错误为error:1416C095:SSL routines:tls_process_finished:digest check failed。这个打过补丁的 libopenssl 产生的“Client Hello”总是不同的,这可能意味着我没有替换所有的键。在 s->tmp 结构中还有一些我不太明白能够替换所有出现和值的东西。

似乎在相同条件下不重播交换实际上是不可能找到问题的。

无论如何: 我想通过重放为 HTTP 客户端捕获的 tcpdump 来重现这种情况——这需要我在正确的位置或以正确的方式设置密钥。或者了解问题的真实性质。