How to turn an x509.Certificate into a tls.Certificate in Go?

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

How to turn an x509.Certificate into a tls.Certificate in Go?

问题

我正在使用x/crypto/pkcs12来加载一个DER格式的*.p12文件。文档中有一个示例,使用tls.X509KeyPair创建了一个tls.Certificate,可以用于HTTP客户端。

这很完美,也能正常工作。但是我还想验证证书是否过期。pkcs12库还有一个Decode函数,它返回一个x509证书,然后我可以使用Verify方法进行验证。这也能正常工作。

但是我觉得奇怪的是,我要对DER进行两次解码。一次是为了验证x509.Certificate,另一次是为了获取tls.Certificate。我不知道这两个证书结构之间的关系,但是既然tls包有一个名为tls.X509KeyPair的函数可以接受一些字节,那么应该也有一种明显的方法可以从x509.Certificate获取tls.Certificate,或者反过来。我漏掉了什么?

英文:

I'm using x/crypto/pkcs12 to load a DER formatted *.p12 file. There is an example in the documentation that uses tls.X509KeyPair to make a tls.Certificate which can be used for an HTTP client.

That's perfect, and works fine. But then I also want to verify that the certificate hasn't expired. The pkcs12 library also has a Decode function which returns an x509 certificate, that I can than use the Verify method on. This also works fine.

It just seems odd to me that I'm decoding the DER twice. Once for an x509.Certificate to verify, and again to get a tls.Certificate. I don't know the relationship between these two Certificate structures, but seeing as the tls package has a function named tls.X509KeyPair that takes some bytes, shouldn't there also be an obvious way to get a tls.Certificate from an x509.Certificate or visa versa? What am I missing?

答案1

得分: 24

一个tls.Certificate通常存储一个证书,换句话说,大于1个证书。请注意它的Certificate字段的类型是[][]byte,其中每个证书是一个[]byte

tls包导入了x509包,所以在x509中没有一个函数可以获取tls.Certificate;那样会导致循环导入。但是如果你有一个x509.Certificate,你已经有了一个tls.Certificate;只需将x509.Certificate的Raw字节放入tls.Certificate的Certificate切片中即可。

英文:

A tls.Certificate often stores a certificate chain - in other words, > 1 certificate. Notice its Certificate field is of type [][]byte, where each certificate is a []byte.

The tls package imports the x509 package, so there isn't a function in x509 to get a tls.Certificate; that would cause an import cycle. But if you have an x509.Certificate, you already have a tls.Certificate; just put the x509.Certificate's Raw bytes into a tls.Certificate's Certificate slice.

答案2

得分: 2

你可以这样做:

func LoadP12TLSCfg(keystore, password string) (*x509.CertPool, tls.Certificate, error) {
	data, err := ioutil.ReadFile(keystore)
	if err != nil {
		return nil, tls.Certificate{}, err
	}

	pk, crt, caCrts, err := pkcs12.DecodeChain(data, password)
	if err != nil {
		return nil, tls.Certificate{}, err
	}

	pool := x509.NewCertPool()
	pool.AddCert(caCrts[0])

	tlsCrt := tls.Certificate{
		Certificate: [][]byte{crt.Raw},
		Leaf:        crt,
		PrivateKey:  pk,
	}

	return pool, tlsCrt, nil
}

func LoadServerTLSCfg(keystore, password string) (*tls.Config, error) {
	pool, crt, err := LoadP12TLSCfg(keystore, password)
	if err != nil {
		return nil, err
	}

	cfg := &tls.Config{
		ClientCAs:    pool,
		ClientAuth:   tls.RequireAndVerifyClientCert,
		Certificates: []tls.Certificate{crt},
	}

	return cfg, nil
}

func LoadClientTLSCfg(keystore, password string, serverName string) (*tls.Config, error) {
	pool, crt, err := LoadP12TLSCfg(keystore, password)
	if err != nil {
		return nil, err
	}

	cfg := &tls.Config{
		RootCAs:      pool,
		Certificates: []tls.Certificate{crt},
		ServerName:   serverName,
	}

	return cfg, nil
}

这段代码定义了三个函数:LoadP12TLSCfgLoadServerTLSCfgLoadClientTLSCfg。这些函数用于加载TLS配置和证书。LoadP12TLSCfg函数从P12格式的密钥库文件中加载证书和私钥,并返回证书池和TLS证书。LoadServerTLSCfg函数加载服务器端的TLS配置,包括客户端证书验证和服务器证书。LoadClientTLSCfg函数加载客户端的TLS配置,包括根证书、客户端证书和服务器名称。

英文:

you can do like this:

func LoadP12TLSCfg(keystore, password string) (*x509.CertPool, tls.Certificate, error) {
data, err := ioutil.ReadFile(keystore)
if err != nil {
return nil, tls.Certificate{}, err
}
pk, crt, caCrts, err := pkcs12.DecodeChain(data, password)
if err != nil {
return nil, tls.Certificate{}, err
}
pool := x509.NewCertPool()
pool.AddCert(caCrts[0])
tlsCrt := tls.Certificate{
Certificate: [][]byte{crt.Raw},
Leaf:        crt,
PrivateKey:  pk,
}
return pool, tlsCrt, nil
}
func LoadServerTLSCfg(keystore, password string) (*tls.Config, error) {
pool, crt, err := LoadP12TLSCfg(keystore, password)
if err != nil {
return nil, err
}
cfg := &tls.Config{
ClientCAs:    pool,
ClientAuth:   tls.RequireAndVerifyClientCert,
Certificates: []tls.Certificate{crt},
}
return cfg, nil
}
func LoadClientTLSCfg(keystore, password string, serverName string) (*tls.Config, error) {
pool, crt, err := LoadP12TLSCfg(keystore, password)
if err != nil {
return nil, err
}
cfg := &tls.Config{
RootCAs:      pool,
Certificates: []tls.Certificate{crt},
ServerName:   serverName,
}
return cfg, nil
}

huangapple
  • 本文由 发表于 2015年12月10日 09:32:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/34192230.html
匿名

发表评论

匿名网友

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

确定