Pular para o conteúdo
ecdsa.com
Python ssl module (OpenSSL, security level 2)Python (cryptography)

Mensagem de erro

[SSL: DH_KEY_TOO_SMALL] dh key too small

Seguido de uma localização no código-fonte, como “(_ssl.c:1082)”. O curl e outros clientes baseados no OpenSSL imprimem o mesmo motivo como “dh key too small”.

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

O que significa

O servidor escolheu uma troca de chaves Diffie-Hellman de corpo finito (DHE) com um grupo menor do que o cliente aceita, normalmente de 1024 bits. O Python 3.10 e posteriores usam o nível de segurança 2 do OpenSSL, que exige DH de pelo menos 2048 bits, então o cliente aborta o handshake. O certificado do servidor não é o problema.

Por que acontece

Como corrigir

  1. 1.

    Confirmar o tamanho da troca de chaves

    Conecte uma vez no nível de segurança 1 com openssl s_client e leia “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.

    Donos do servidor: usar ECDHE ou um grupo de 2048 bits

    Prefira cipher suites ECDHE (e o TLS 1.3); se o DHE for obrigatório, configure um grupo da RFC 7919 de pelo menos 2048 bits.

    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.

    Solução temporária: reduzir o nível de segurança para um único host

    “DEFAULT:@SECLEVEL=1” em um contexto dedicado aceita DH de 1024 bits só para esse host. Não use essa string em contextos compartilhados ou padrão: ela também aceita outros parâmetros fracos.

    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)

Erros relacionados

Ver toda a base de erros de assinatura