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

Mensagem de erro

[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate

Também aparece como

  • [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate

O Python acrescenta a localização no código-fonte em C, por exemplo, “(_ssl.c:1082)”. Não confunda com “self-signed certificate in certificate chain”, que indica uma cadeia de CAs que termina em uma raiz não confiável. O OpenSSL 1.1.1 escreve “self signed”.

Python ssl module (OpenSSL) — ssl.SSLCertVerificationError, X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT (18)

O que significa

O servidor apresentou um único certificado autoassinado (o emissor é ele mesmo) que não está no conjunto de CAs confiáveis deste contexto. Não há CA para consultar, então o OpenSSL falha na profundidade 0. É típico de servidores de desenvolvimento, appliances e instalações recém-feitas; a solução é confiar nesse certificado de forma deliberada ou substituí-lo.

Por que acontece

Como corrigir

  1. 1.

    Confiar apenas neste certificado, para este cliente

    Carregue o próprio certificado do servidor como cafile. As verificações de nome do host e de datas continuam ativas, e só esse certificado exato é aceito.

    python
    import ssl, urllib.request
    
    # Trust exactly this certificate (fetched and fingerprint-checked out of band)
    ctx = ssl.create_default_context(cafile="api.example.com.pem")
    urllib.request.urlopen("https://api.example.com:8443/", context=ctx)
  2. 2.

    Baixar o certificado e conferir a impressão digital dele

    Compare a impressão digital SHA-256 com o valor mostrado no console do dispositivo ou informado pelo administrador dele antes de confiar no arquivo.

    bash
    openssl s_client -connect api.example.com:8443 -servername api.example.com </dev/null 2>/dev/null \
      | openssl x509 -out api.example.com.pem
    openssl x509 -in api.example.com.pem -noout -fingerprint -sha256   # compare with the server's console
  3. 3.

    Desenvolvimento: usar uma CA local em vez disso

    Uma CA local permite confiar em uma única raiz e emitir certificados devidamente assinados para todos os hosts de desenvolvimento, de modo que nenhum cliente precise de exceções por certificado.

    bash
    # Development: one local CA, many certificates (mkcert installs the CA for you)
    mkcert -install
    mkcert api.example.test
    export SSL_CERT_FILE="$(mkcert -CAROOT)/rootCA.pem"
  4. 4.

    Diagnóstico temporário: desligar a verificação em um teste

    check_hostname = False e CERT_NONE desativam todas as verificações e aceitam qualquer certificado, inclusive um apresentado por um atacante. Use isso apenas para confirmar que a confiança é o único problema e depois remova essa configuração.

    python
    # Temporary diagnostic only: proves trust is the sole problem. Never ship this.
    import ssl
    ctx = ssl.create_default_context()
    ctx.check_hostname = False
    ctx.verify_mode = ssl.CERT_NONE

Erros relacionados

Ver toda a base de erros de assinatura