英文:
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
, andserver_cacerts.pem
The server code looks as follows:
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)
}
and the client certificates and keys named:
client_cert.pem
,client_key.pem
, andclient_cacerts.pem
Client code follows:
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)))
}()
}
}
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论