Skip to content
ecdsa.com
Go crypto/tls clientGo

Error message

remote error: tls: handshake failure

In HTTP clients the line reads "Get \"https://…\": remote error: tls: handshake failure". Go uses the same "remote error: tls: <alert>" form on servers, in "http: TLS handshake error from …" log lines, when a client sends an alert.

Go crypto/tls client — the server sent TLS alert 40 (handshake_failure)

What it means

"remote error" means the other side sent a TLS alert; here the server sent alert 40 (handshake_failure) to the Go client. The server rejected the parameters Go offered (cipher suites, groups, signature algorithms) or required a client certificate that Go did not send. Go cannot tell which; the server's log can.

Why it happens

How to fix it

  1. 1.

    Compare cipher suites

    tls.CipherSuites() lists what Go considers secure and offers; compare with the server's configuration.

    go
    // What does this Go client offer by default?
    for _, s := range tls.CipherSuites() {
    	fmt.Println(s.Name)
    }
  2. 2.

    Send a client certificate for mutual TLS

    Load the certificate and key with tls.LoadX509KeyPair and set them in tls.Config.Certificates.

    go
    // Mutual TLS: present a client certificate
    cert, err := tls.LoadX509KeyPair("client.pem", "client.key")
    if err != nil {
    	log.Fatal(err)
    }
    client := &http.Client{Transport: &http.Transport{TLSClientConfig: &tls.Config{
    	Certificates: []tls.Certificate{cert},
    }}}
  3. 3.

    Server owners: modernise the suites

    TLS 1.3 and ECDHE-based TLS 1.2 suites work with every current Go release.

    text
    Server side: enable TLS 1.3 and TLS 1.2 ECDHE suites with AES-GCM or ChaCha20-Poly1305.

Related errors

Browse the full signature error database