概括:
当服务器在 DHE_RSA 服务器密钥交换消息中交出 127 字节的公钥时,TLS 客户端似乎无法协商,但在交出 128 字节的公钥时协商成功。公钥长度有什么问题,特别是服务器端的这种合法行为是什么?
血腥细节:
我有一个客户端(软件未知)在连接到我的 TLS 服务器(F5、TLS 1.2)时遇到间歇性故障。成功和失败的连接都取决于服务器 Hello 中的 Cipher Suite TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)。所有连接尝试都到达服务器 Hello Done 并且失败的连接在此之后立即由客户端进行 FIN。
查看数据包捕获,失败似乎都与服务器密钥交换握手中的“公钥长度”为 127 一致:
另一方面,与该客户端的每次成功协商都在服务器密钥交换握手中涉及 128 的“公钥长度”:
每当服务器发送 127 字节版本时,客户端都会以 FIN/ACK 而不是客户端密钥交换进行响应。我们得出的结论是客户端不能接受 127 字节的公钥长度。我已经阅读 了RFC 5246以了解我是否可以了解允许的内容并且它们没有帮助(至少对我来说!):
struct {
opaque dh_p<1..2^16-1>;
opaque dh_g<1..2^16-1>;
opaque dh_Ys<1..2^16-1>;
} ServerDHParams; /* Ephemeral DH parameters */
struct {
select (KeyExchangeAlgorithm) {
case dhe_rsa:
ServerDHParams params;
digitally-signed struct {
opaque client_random[32];
opaque server_random[32];
ServerDHParams params;
} signed_params;
};
} ServerKeyExchange;
所以具体的问题是:
DHE_RSA 服务器密钥交换中的公钥长度是怎么回事?具体来说,127 与 128 是否代表类似零截断以节省长度的东西,还是真的提供 127 字节的密钥?
更具体地说,127 是否是客户端应该能够处理的有效公钥长度,或者这是否代表需要解决的服务器问题?
澄清:
有问题的服务器是一个运行最新 (11.6) 软件的 F5 负载均衡器,因此在 TLS 出处方面它不仅是现成的,而且是现成的。这并不是说这不是问题,只是说这不像我在后端滚动我自己的 Lua-over-Django-with-third-Rails TLS 服务器:)
OpenSSL 的想法
我留下了一个脚本,openssl s_client用于在周末每分钟访问服务器,并捕获完整的数据包,以便我可以看到 OpenSSL 对这个特定服务器配置的看法。简单地说,对于 127 字节的 DHE“公钥”长度,OpenSSL 认为“服务器临时密钥”是 1024 位的。
这是 Wireshark 中显示的服务器密钥交换:
这是该连接的 OpenSSL 输出:
$ tail -25 20151107234244.txt
---
No client certificate CA names sent
Server Temp Key: DH, 1024 bits
---
SSL handshake has read 2014 bytes and written 291 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1.2
Cipher : DHE-RSA-AES256-GCM-SHA384
Session-ID: 8C48CAD47FC01AF350CF618E21AE9C7E8764BB7C7243D8D6204F95634523EF2F
Session-ID-ctx:
Master-Key: FB80D1070A3BB2435C2D4E50D6633DA3DE4FDCFA5C8A922E17EC6FB0EDC41E259F55DFC33345B51F9A90568B36CFBB7C
Key-Arg : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
Start Time: 1446957764
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
---
$
那么它是 1024 位还是 1016 位?'p' 长度是否表示密钥强度而不是公钥长度(对于那些在 Wireshark 中跟随的人来说,ssl.handshake.ys_len)?Diffie-Hellman 的“服务器密钥交换”在哪里定义?有人找到了足够的文档来编写 Wireshark 解析器,如果我可以查看他们使用的文档,也许我会更好地了解这些领域的期望。


