Saltar al contenido
ecdsa.com
OpenSSLCLI de OpenSSL

Mensaje de error

SSL routines:ssl3_read_bytes:ssl/tls alert bad certificate

También se muestra como

  • SSL routines:ssl3_read_bytes:sslv3 alert bad certificate
  • error:0A000412:SSL routines::ssl/tls alert bad certificate

OpenSSL 3.3 y las versiones posteriores imprimen «ssl/tls alert bad certificate», y las anteriores, «sslv3 alert bad certificate» (código 0A000412; 1.1.1 usaba 14094412), seguido de «SSL alert number 42». Los propios clientes OpenSSL envían unknown_ca (48) o certificate_expired (45) ante los mismos rechazos.

OpenSSL — TLS alert 42 (bad_certificate) received from the peer

Qué significa

El otro extremo envió la alerta TLS 42 (bad_certificate): rechazó el certificado que presentó este lado. El paquete crypto/tls de Go envía esta alerta ante cualquier certificado de servidor que no consigue verificar (autoridad desconocida, caducado, nombre incorrecto), así que los servidores basados en OpenSSL (nginx, HAProxy, Postfix, s_server) la registran siempre que un cliente Go rechaza su certificado. En TLS mutuo, un servidor la envía cuando rechaza el certificado de cliente.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Encontrar el cliente que rechaza y el motivo

    La línea del registro indica la dirección del cliente; en ese cliente, el mensaje de error da la causa real. Verificar la cadena desde fuera suele mostrarla directamente.

    bash
    # Server log: which client rejected the certificate, and does the chain verify from outside?
    openssl s_client -connect api.example.com:443 -servername api.example.com </dev/null 2>/dev/null \
      | grep -E 'Verify return code'
  2. 2.

    Clientes Go: confiar en la CA o corregir la cadena

    Sirve una cadena completa de una CA de confianza o añade la CA privada a los RootCAs del cliente Go; nunca uses InsecureSkipVerify como solución.

    go
    // Go clients: trust the server's CA explicitly (keeps verification on)
    pool, _ := x509.SystemCertPool()
    caPEM, _ := os.ReadFile("internal-ca.pem")
    pool.AppendCertsFromPEM(caPEM)
    client := &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{RootCAs: pool}}}
  3. 3.

    TLS mutuo: comprobar el certificado de cliente

    Las fechas de validez, el emisor y el uso de clave del certificado de cliente deben coincidir con lo que espera el servidor.

    bash
    # Mutual TLS: check the client certificate the server rejected
    openssl x509 -in client.pem -noout -issuer -dates -ext extendedKeyUsage,keyUsage

Errores relacionados

Explorar toda la base de datos de errores de firma