如何使用Go TLS手动验证客户端证书?

时间:2017-03-08 06:08:49

标签: ssl go tls1.2

我们正在Golang中构建一个服务器,通过SSL打开TCP端口。

我们希望在客户端和服务器之间启用相互身份验证。但是还检测客户端何时尝试连接到没有有效客户端证书的服务器并通过SSL返回错误消息 - 例如"检测到无效的客户端证书,请联系ABC公司获取帮助"。

请注意:我们坚持要求通过SSL将数据返回给无法与服务器进行相互身份验证的客户端。我们不想断开它们。

我们采取的方法是使用' VerifyClientCertIfGiven' TLS的配置设置。

因此,如果给出了客户端证书,我们会对其进行验证,但如果不是,则我们仍然允许建立SSL连接。

我们怎样才能找到:

  1. 是否提供了客户证书?
  2. 如果是,是否通过了TLS执行的相互认证检查?
  3. 以下是我们服务器的代码:

    package main
    
    import(
      "fmt"
      "io/ioutil"
      "crypto/tls"
      "crypto/x509"
    )
    
    func main(){
      // Configure SSL
      cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
      caCert, _ := ioutil.ReadFile("client.crt")
      caCertPool := x509.NewCertPool()
      caCertPool.AppendCertsFromPEM(caCert)
      config := &tls.Config{
        Certificates: []tls.Certificate{cert},
        ClientCAs: caCertPool,
        ClientAuth: tls.VerifyClientCertIfGiven,
      }
      config.BuildNameToCertificate()
      // Listen on port 443
      listener, _ := tls.Listen("tcp", ":443", config)
      defer listener.Close()
      // Accept incoming connection
      conn, _ := listener.Accept()
      defer conn.Close()
      // Print ConnectionState
      tlscon, _ := conn.(*tls.Conn)
      fmt.Println(tlscon.ConnectionState())
    }
    

    以下是我们客户的代码:

    package main
    import (
      "io/ioutil"
      "crypto/tls"
      "crypto/x509"
    )
    
    func main(){
      //Configure SSL
      cert, _ := tls.LoadX509KeyPair("client.crt", "client.key"
      caCert, _ := io.util.ReadFile("server.crt")
      caCertPool := x509.NewCertPool()
      caCertPool.AppendCertsFromPEM(caCert)
      config := &tls.Config{
        Certificates: []tls.Certificate{cert},
        RootCAs:      caCertPool,
      }
      config.BuildNameToCertificate()
      // Connect to server
      conn, _ := tls.Dial("tcp", "127.0.0.1:443", config)
      defer conn.Close()
    }
    

    输出:

    {0 false false 0  false  [] [] [] [] []}
    

    我们尝试在服务器上实现conn.ConnectionState()。PeerCertificates,但在我们所有的尝试中,它都是一个空字节数组。

    提前谢谢你。感谢您抽出时间帮助我们。

    亲切的问候,

    儒略

1 个答案:

答案 0 :(得分:0)

我也在下午度过了这一天。

服务器接受连接后,您需要明确地呼叫tlscon.Handshake()以获取客户端证书,否则tls包将在第一个i / o后自动执行。 https://golang.org/pkg/crypto/tls/#Conn.Handshake

您可以看到示例here