GoLang: TLS客户端错误 `x509: 证书由未知机构签名`

huangapple go评论86阅读模式
英文:

GoLang: TLS client error `x509: certificate signed by unknown authority`

问题

我已经按照你的要求翻译了你提供的内容,以下是翻译好的部分:

我已经按照多个教程[1 , 2, 3]编写了一个使用Go语言编写的接受TLS身份验证的客户端-服务器程序。

我有以下命名的服务器证书和密钥:

  • server_cert.pem
  • server_key.pem
  • server_cacerts.pem

服务器端的代码如下所示:

	path, err := os.Getwd()
	if err != nil {
		log.Println(err)
	}
	CACert := path + "/server_cacerts.pem"
	log.Println(CACert)

	certs, err := ioutil.ReadFile(CACert)
	if err != nil {
		log.Fatal("Invalid CACert: %s", err)
	}

	rootCAs := x509.NewCertPool()
	ok := rootCAs.AppendCertsFromPEM(certs)
	if !ok {
		log.Println("Taking default certificates")
	}

	certPem := path + "/server_cert.pem"
	keyPem := path + "/server_key.pem"
	cert, err := tls.LoadX509KeyPair(certPem, keyPem)
	if err != nil {
		log.Fatal(err)
	}

	log.Println(certPem)
	log.Println(keyPem)

	config := &tls.Config{Certificates: []tls.Certificate{cert},
		                  // ServerName: "elxa3x9nxd3",
						  ClientAuth: tls.RequireAndVerifyClientCert,
		                  ClientCAs: rootCAs}

    ln, err := tls.Listen("tcp", ":8888", config)
    if err != nil {
        log.Fatal("listen failed: %s", err.Error())
        return
    }
    defer ln.Close()

    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Fatal("Accept Failed: %s", err.Error())
            continue
        }
		// log.Printf("connection open: %s", conn.RemoteAddr())
		// printConnState(conn.(*tls.Conn))
        go handleConnection(conn)
    }

客户端的证书和密钥命名为:

  • client_cert.pem
  • client_key.pem
  • client_cacerts.pem

客户端的代码如下所示:

func main() {
    log.SetFlags(log.Lshortfile)
	args := os.Args

	var numberHandshakes int
	var err error

	if len(args) > 1 {
        numberHandshakes, err = strconv.Atoi(args[1])
        if err != nil {
			log.Println("Error in number of arguments")
            panic(err)
        }
    } else {
        numberHandshakes = 1000
    }
	fmt.Println("Number of handshakes requested: " + strconv.Itoa(numberHandshakes))


	path, err := os.Getwd()
	if err != nil {
		log.Println(err)
	}
	CACert := path + "/client_cacerts.pem"
	certs, err := ioutil.ReadFile(CACert)
	if err != nil {
		log.Fatal(err)
	}

	// rootCAs := x509.NewCertPool()
	rootCAs, err := x509.SystemCertPool()
	ok := rootCAs.AppendCertsFromPEM(certs)
	if !ok {
		log.Println("Taking default certificates")
	}


	certPem := path + "/client_cert.pem"
	keyPem := path + "/client_key.pem"
	cert, err := tls.LoadX509KeyPair(certPem, keyPem)
	if err != nil {
		log.Fatal("Error loading KeyPair: %s", err)
	}

	conf := &tls.Config{ Certificates: []tls.Certificate{cert},
		                 // InsecureSkipVerify: true,
		                 ServerName: "elxa3x9nxd3",
		                 RootCAs: rootCAs,
						}

	ch := make(chan int)
	for i := 1; i <= numberHandshakes; i++ {
		go func(){
			conn, err := tls.Dial("tcp", ":8888", conf)      // ERROR HERE
			if err != nil {
				log.Println("Error in client", err.Error())
				return
			}

			conn.SetWriteDeadline(time.Time{})
			conn.Write([]byte(strconv.Itoa(i)))
		}()
	}
}

我运行了服务器,然后调用客户端执行一些查询操作。出现错误的地方标记为ERROR HERE,我看到的错误信息是:

tls-client.go:98: Error in client tls: failed to verify certificate: x509: certificate signed by unknown authority

我知道我使用的是自签名证书,但我认为根据我代码中的客户端和服务器选项,我不需要放弃任何安全性(我不想启用InsecureSkipVerify)。有什么建议吗?

英文:

I have followed multiple tutorials [1 , 2, 3] to write a client-server in Go that accepts TLS authentication.

I have my server certificates and keys named:

  • server_cert.pem,
  • server_key.pem, and
  • server_cacerts.pem

The server code looks as follows:

	path, err := os.Getwd()
	if err != nil {
		log.Println(err)
	}
	CACert := path + &quot;/server_cacerts.pem&quot;
	log.Println(CACert)

	certs, err := ioutil.ReadFile(CACert)
	if err != nil {
		log.Fatal(&quot;Invalid CACert: %s&quot;, err)
	}

	rootCAs := x509.NewCertPool()
	ok := rootCAs.AppendCertsFromPEM(certs)
	if !ok {
		log.Println(&quot;Taking default certificates&quot;)
	}

	certPem := path + &quot;/server_cert.pem&quot;
	keyPem := path + &quot;/server_key.pem&quot;
	cert, err := tls.LoadX509KeyPair(certPem, keyPem)
	if err != nil {
		log.Fatal(err)
	}

	log.Println(certPem)
	log.Println(keyPem)

	config := &amp;tls.Config{Certificates: []tls.Certificate{cert},
		                  // ServerName: &quot;elxa3x9nxd3&quot;,
						  ClientAuth: tls.RequireAndVerifyClientCert,
		                  ClientCAs: rootCAs}

    ln, err := tls.Listen(&quot;tcp&quot;, &quot;:8888&quot;, config)
    if err != nil {
        log.Fatal(&quot;listen failed: %s&quot;, err.Error())
        return
    }
    defer ln.Close()

    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Fatal(&quot;Accept Failed: %s&quot;, err.Error())
            continue
        }
		// log.Printf(&quot;connection open: %s&quot;, conn.RemoteAddr())
		// printConnState(conn.(*tls.Conn))
        go handleConnection(conn)
    }

and the client certificates and keys named:

  • client_cert.pem,
  • client_key.pem, and
  • client_cacerts.pem

Client code follows:

func main() {
    log.SetFlags(log.Lshortfile)
	args := os.Args

	var numberHandshakes int
	var err error

	if len(args) &gt; 1 {
        numberHandshakes, err = strconv.Atoi(args[1])
        if err != nil {
			log.Println(&quot;Error in number of arguments&quot;)
            panic(err)
        }
    } else {
        numberHandshakes = 1000
    }
	fmt.Println(&quot;Number of handshakes requested: &quot; + strconv.Itoa(numberHandshakes))


	path, err := os.Getwd()
	if err != nil {
		log.Println(err)
	}
	CACert := path + &quot;/client_cacerts.pem&quot;
	certs, err := ioutil.ReadFile(CACert)
	if err != nil {
		log.Fatal(err)
	}

	// rootCAs := x509.NewCertPool()
	rootCAs, err := x509.SystemCertPool()
	ok := rootCAs.AppendCertsFromPEM(certs)
	if !ok {
		log.Println(&quot;Taking default certificates&quot;)
	}


	certPem := path + &quot;/client_cert.pem&quot;
	keyPem := path + &quot;/client_key.pem&quot;
	cert, err := tls.LoadX509KeyPair(certPem, keyPem)
	if err != nil {
		log.Fatal(&quot;Error loading KeyPair: %s&quot;, err)
	}

	conf := &amp;tls.Config{ Certificates: []tls.Certificate{cert},
		                 // InsecureSkipVerify: true,
		                 ServerName: &quot;elxa3x9nxd3&quot;,
		                 RootCAs: rootCAs,
						}

	ch := make(chan int)
	for i := 1; i &lt;= numberHandshakes; i++ {
		go func(){
			conn, err := tls.Dial(&quot;tcp&quot;, &quot;:8888&quot;, conf)      // ERROR HERE
			if err != nil {
				log.Println(&quot;Error in client&quot;, err.Error())
				return
			}

			conn.SetWriteDeadline(time.Time{})
			conn.Write([]byte(strconv.Itoa(i)))
		}()
	}
}

I run the server and then call the client to perform some number of queries to the server.
The error seems to be in the line marked as ERROR HERE, and the error that I see says:

tls-client.go:98: Error in client tls: failed to verify certificate: x509: certificate signed by unknown authority

I know that I have self-signed a certificate, but I thought that given the client and server options that I have in my code, I do not need to throw out of the window any security (I do not want to enable InsecureSkipVerify).

Any tips?

答案1

得分: 2

我假设server_cacerts.pem包含用于创建server_cert.pem的根CA和可能的中间CA,client_*.pem也是同样的情况。

由于客户端需要验证服务器证书,并且使用server_cacerts.pem进行验证,所以客户端需要将其作为RootCA,而不是你的代码中使用的client_cacerts.pem。类似地,对于双向认证,服务器需要验证客户端证书,因此需要将client_cacerts.pem作为ClientCA,而不是你的代码中使用的server_cacerts.pem

英文:

I assume that server_cacerts.pem contains the root CA and possible intermediate CAs which are used to create server_cert.pem and the same for client_*.pem.

Since the client needs to verify the server certificate and this is done using server_cacerts.pem the client needs this as RootCA, not client_cacerts.pem as done in your code. Similar with mutual authentication the server needs to verify the client certificate and thus needs client_cacerts.pem as ClientCA, not server_cacerts.pem as done in your code.

huangapple
  • 本文由 发表于 2023年5月23日 02:43:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76309074.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定