【问题标题】:How to turn an x509.Certificate into a tls.Certificate in Go?如何在 Go 中将 x509.Certificate 转换为 tls.Certificate?
【发布时间】:2015-12-10 01:32:52
【问题描述】:

我正在使用 x/crypto/pkcs12 加载 DER 格式的 *.p12 文件。有an example in the documentation 使用tls.X509KeyPair 来创建一个tls.Certificate 可以用于HTTP 客户端。

这很完美,而且工作正常。但是我也想验证证书没有过期。 pkcs12 库还有一个 Decode function ,它返回一个 x509 证书,我可以使用 Verify 方法。这也很好用。

我对 DER 进行了两次解码,这对我来说似乎很奇怪。一次用于验证x509.Certificate,再次获取tls.Certificate。我不知道这两个证书结构之间的关系,但是看到 tls 包有一个名为 tls.X509KeyPair 的函数,它需要一些字节,不应该还有一种明显的方法从 x509 获取 tls.Certificate。证书还是反之?我错过了什么?

【问题讨论】:

    标签: go cryptography


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢马特。我会试一试。我是否需要对 tls.Certificate 的其他字段做任何事情或调用任何函数,还是应该“正常工作”?我注意到 x509.Certificate.Verify() 也返回链。
    • TLS 服务器需要设置PrivateKey 字段才能成功完成握手。我认为其余的都是可选的。
    • 看起来我需要一个 PrivateKey 供客户使用。调查它。 tls: 类型的客户端证书私钥不实现 crypto.Signer
    • 我很快就放弃了。 Wim Lewis 有一个回应,其中设置了 Leaf 和 ParsedKey。它现在似乎正在工作(至少在 Go 提示上)groups.google.com/forum/#!msg/golang-nuts/7l75mp2gh1o/…
    • Wim 的代码:thing := tls.Certificate{ Certificate: [][]byte{ parsedCert.Raw }, PrivateKey: parsedPrivateKey, Leaf: parsedCert, }
    【解决方案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
    }
    

    【讨论】:

      猜你喜欢
      • 2019-07-28
      • 1970-01-01
      • 1970-01-01
      • 2016-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-17
      相关资源
      最近更新 更多