duandaotuo5542 2017-03-08 06:08
浏览 318

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

We are building a server in Golang that opens a TCP port over SSL.

We would like to enable mutual-authentication between the client and the server. But also detect when a client attempts to connect to our server without a valid client certificate and return them a error message over SSL - such as "invalid client certificate detected, please contact company ABC for assistance".

Just to be clear: we are adamant about our requirement to return data over SSL to clients that fail to mutually authenticate with the server. We do not want to disconnect them.

The approach we have taken is to use the 'VerifyClientCertIfGiven' configuration setting for TLS.

Whereby, we verify the client certificate if it is given, but we still allow an SSL connection to be established if it isn't.

How can we find out:

  1. Was a client certificate provided?
  2. If so, did it pass the mutual authentication checks performed by TLS?

Below is the code of our server:

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())
}

And below is the code of our client:

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()
}

The output:

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

We've tried implementing conn.ConnectionState().PeerCertificates on the server but in all our attempts, it was an empty byte array.

Thank you in advance. We appreciate your time trying to help us.

Kind Regards,

Julian

  • 写回答

1条回答 默认 最新

  • douxian9706 2017-04-25 09:36
    关注

    I spent the best of my afternoon on this one too.

    Once the server accepts the connection you will need to explicitely call tlscon.Handshake() to get the client's certificate, otherwise the tls package will do it automatically after the first i/o. https://golang.org/pkg/crypto/tls/#Conn.Handshake

    You can see a example here.

    评论

报告相同问题?

悬赏问题

  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?