在 SSL/TLS 中,客户端和服务器可以选择使用 Ephemeral Diffie-Hellman 交换来建立共享密钥,为其播种随后的主密钥和会话密钥。
在选择 DHE 作为两方之间的密钥交换的情况下,他们如何确定 DH ModP 组的大小(以便他们可以就 P 和 G 编号达成一致)?
在 SSL/TLS 中,客户端和服务器可以选择使用 Ephemeral Diffie-Hellman 交换来建立共享密钥,为其播种随后的主密钥和会话密钥。
在选择 DHE 作为两方之间的密钥交换的情况下,他们如何确定 DH ModP 组的大小(以便他们可以就 P 和 G 编号达成一致)?
使用 DHE 密码套件,DH 的模数大小完全由服务器选择,客户端没有关于可接受大小的输入(这确实是 TLS 协议中关于 DHE 密码套件的缺陷)。
一些历史客户端(包括 Java 7 之前附带的客户端)不支持超过 1024 位的 DH 模数。因此导致一些服务器实现坚持使用 1024 位 DH 模数。然而,其他一些人在某些时候认为这样的尺寸太小了。几年前,Apache+OpenSSL 实现了这一特殊的飞跃。有关详细信息,请参阅此。
使用 ECDHE(椭圆曲线版本),要使用的椭圆曲线仍然由服务器选择,但是有一个ClientHello 扩展,允许客户端指定它支持哪些曲线,从而允许服务器做出真正明智的决定。
为 DHE 配置服务器时,您必须生成 Diffie Hellman 参数。然后配置 OpenSSL/Apache/Nginx 等以使用您生成的 DH 参数。
要使用的 DH 参数在ServerKeyExchange消息中发送。在ServerHello和Certificate消息之后,但在ServerHelloDone之前。
该ServerKeyExchange消息包含以下内容:
struct {
select (KeyExchangeAlgorithm) {
case diffie_hellman:
ServerDHParams params;
Signature signed_params;
case rsa:
ServerRSAParams params;
Signature signed_params;
};
} ServerKeyExchange;
来源:RFC2246第 7.4.3 节
服务器选择组并告诉客户端。客户端不提供此过程的输入。
大多数服务器将附带一组默认参数(prime 和 generator),但出于两个原因,建议您生成自己的参数。
不幸的是,如果服务器使用大于 1024 位的素数,Java 7 和更早版本的握手将失败。
对于 Java 6,没有很好的解决方案。如果您需要支持 Java 6 客户端,则必须在不支持 ECDHE 的客户端的无前向保密或弱 1024 位 DSA 参数之间选择您的毒药。
对于 Java 7,您可以通过赋予 ECDHE 密码套件比 DHE 密码套件更高的优先级来避免此问题。