跳到主要内容
ecdsa.com
Python ssl module (OpenSSL, security level 2)Python cryptography 库

错误信息

[SSL: DH_KEY_TOO_SMALL] dh key too small

后面跟着源代码位置,例如“(_ssl.c:1082)”。curl 和其他基于 OpenSSL 的客户端会把同一原因打印为“dh key too small”。

Python ssl module (OpenSSL, security level 2) — ssl.SSLError, SSL_R_DH_KEY_TOO_SMALL

含义

服务器选择了有限域 Diffie-Hellman(DHE)密钥交换,而所用的组小于客户端可接受的大小,通常是 1024 位。Python 3.10 及更高版本使用 OpenSSL 安全级别 2,要求 DH 至少为 2048 位,因此客户端中止了握手。问题不在服务器证书上。

原因

修复方法

  1. 1.

    确认密钥交换使用的位数

    用 openssl s_client 在安全级别 1 下连接一次,查看“Server Temp Key”。

    bash
    # "Server Temp Key: DH, 1024 bits" confirms the weak group
    openssl s_client -connect legacy.example.com:443 -servername legacy.example.com \
      -cipher 'DEFAULT:@SECLEVEL=1' </dev/null 2>/dev/null | grep 'Server Temp Key'
  2. 2.

    服务器所有者:使用 ECDHE 或 2048 位的组

    优先使用 ECDHE 套件(以及 TLS 1.3);如果必须使用 DHE,就配置至少 2048 位的 RFC 7919 组。

    text
    # nginx: prefer ECDHE; if DHE must stay, use a 2048-bit (or larger) group
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_dhparam /etc/nginx/ffdhe2048.pem;   # RFC 7919 group
  3. 3.

    临时解决办法:只为一台主机降低安全级别

    在专用的上下文中设置“DEFAULT:@SECLEVEL=1”,只对该主机接受 1024 位 DH。不要把它用在共享或默认的上下文中:它还会接受其他弱参数。

    python
    # Temporary workaround for one legacy host: security level 1 accepts 1024-bit DH
    import ssl, urllib.request
    
    ctx = ssl.create_default_context()
    ctx.set_ciphers("DEFAULT:@SECLEVEL=1")
    urllib.request.urlopen("https://legacy.example.com/", context=ctx)

相关错误

浏览完整的签名错误库