英文:
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
}
这段代码定义了三个函数:LoadP12TLSCfg
、LoadServerTLSCfg
和LoadClientTLSCfg
。这些函数用于加载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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论