在Golang中获取远程SSL证书

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

Get remote ssl certificate in golang

问题

我想要通过TLS接收一个TCP连接。我想要验证客户端证书,并将其用于对我的应用程序进行身份验证。
Go语言有标准的crypto/tls包。它可以验证客户端/服务器证书。但是我找不到获取远程(客户端)证书详细信息的方法,比如公共名称(common name)。

英文:

I want to receive a TCP connection over TLS. I want to validate client certificate and use it to authenticate the client to my application.
Go has the standard crypto/tls package. It can validate client/server certificates. But I can't find way to get details of the remote (client) certificate, like the common name.

答案1

得分: 17

以下代码可能会帮助您获得答案:

package main

import (
	"crypto/tls"
	"fmt"
	"log"
)

func main() {
	conf := &tls.Config{
		InsecureSkipVerify: true,
	}

	conn, err := tls.Dial("tcp", "www.google.com:443", conf)
	if err != nil {
		log.Println("拨号错误", err)
		return
	}
	defer conn.Close()
	certs := conn.ConnectionState().PeerCertificates
	for _, cert := range certs {
		fmt.Printf("颁发者名称:%s\n", cert.Issuer)
		fmt.Printf("到期时间:%s \n", cert.NotAfter.Format("2006年1月2日"))
		fmt.Printf("通用名称:%s \n", cert.Issuer.CommonName)

	}
}

希望对您有所帮助!

英文:

Following code may help you get your answer

package main

import (
	"crypto/tls"
	"fmt"
	"log"
)

func main() {
    conf := &tls.Config{
		InsecureSkipVerify: true,
	}

	conn, err := tls.Dial("tcp", "www.google.com:443", conf)
	if err != nil {
		log.Println("Error in Dial", err)
		return
	}
	defer conn.Close()
    certs := conn.ConnectionState().PeerCertificates
    for _, cert := range certs {
		fmt.Printf("Issuer Name: %s\n", cert.Issuer)
		fmt.Printf("Expiry: %s \n", cert.NotAfter.Format("2006-January-02"))
        fmt.Printf("Common Name: %s \n", cert.Issuer.CommonName)

	}
}

答案2

得分: 16

必须调用crypto/tls/Conn.Handshake
然后你可以读取对等证书:
tlsconn.ConnectionState().PeerCertificates[0].Subject.CommonName

英文:

Have to call crypto/tls/Conn.Handshake.
Then you can read peer certificate:
tlsconn.ConnectionState().PeerCertificates[0].Subject.CommonName

答案3

得分: 4

在使用crypto/tls时,您可以查询任何Conn对象的ConnectionState:

func (c *Conn) ConnectionState() ConnectionState

ConnectionState结构包含有关客户端证书的信息:

type ConnectionState struct {
    PeerCertificates []*x509.Certificate // 远程对等方呈现的证书链
}

x509.Certificate应该很容易使用。

在服务器请求客户端身份验证之前,您必须使用服务器证书、客户端CA(否则您将不得不手动验证信任链,您真的不希望这样做)和tls.RequireAndVerifyClientCert配置连接。例如:

// 加载我的SSL密钥和证书
cert, err := tls.LoadX509KeyPair(settings.MyCertificateFile, settings.MyKeyFile)
checkError(err, "LoadX509KeyPair")

// 加载用于客户端证书验证的CA证书
capool := x509.NewCertPool()
cacert, err := ioutil.ReadFile(settings.CAKeyFile)
checkError(err, "loadCACert")
capool.AppendCertsFromPEM(cacert)

// 准备服务器配置
config := tls.Config{Certificates: []tls.Certificate{cert}, ClientCAs: capool, ClientAuth: tls.RequireAndVerifyClientCert}
config.NextProtos = []string{"http/1.1"}
config.Rand = rand.Reader
英文:

When working with crypto/tls you can query any Conn object for ConnectionState:

func (c *Conn) ConnectionState() ConnectionState

The ConnectionState struct contains information about the client certificate:

type ConnectionState struct {
        PeerCertificates            []*x509.Certificate   // certificate chain presented by remote peer
}

The x509.Certificate should be pretty straightforward to work with.

Before the server requests for client authentication, you have to configure the connection with the server certificate, client CA (otherwise you will have to verify the trust chain manually, you really don't want that), and tls.RequireAndVerifyClientCert. For example:

// Load my SSL key and certificate
cert, err := tls.LoadX509KeyPair(settings.MyCertificateFile, settings.MyKeyFile)
checkError(err, "LoadX509KeyPair")

// Load the CA certificate for client certificate validation
capool := x509.NewCertPool()
cacert, err := ioutil.ReadFile(settings.CAKeyFile)
checkError(err, "loadCACert")
capool.AppendCertsFromPEM(cacert)

// Prepare server configuration
config := tls.Config{Certificates: []tls.Certificate{cert}, ClientCAs: capool, ClientAuth: tls.RequireAndVerifyClientCert}
config.NextProtos = []string{"http/1.1"}
config.Rand = rand.Reader

答案4

得分: 1

有一个更简单的方法来做到这一点:

func renewCert(w http.ResponseWriter, r *http.Request) {

  if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
    cn := strings.ToLower(r.TLS.PeerCertificates[0].Subject.CommonName)
    fmt.Println("CN: %s", cn)
  }

}
英文:

There is an easier way to do that:

func renewCert(w http.ResponseWriter, r *http.Request) {

  if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
	cn := strings.ToLower(r.TLS.PeerCertificates[0].Subject.CommonName)
	fmt.Println("CN: %s", cn)
  }

}

huangapple
  • 本文由 发表于 2015年8月1日 01:19:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/31751764.html
匿名

发表评论

匿名网友

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

确定