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

时间:2015-12-10 01:32:52

标签: go cryptography

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?

2 个答案:

答案 0 :(得分:6)

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

tls包导入x509包,因此x509中没有函数来获取tls.Certificate;这将导致进口周期。但是如果你有x509.Certificate,你已经有了tls.Certificate;只需将x509.Certificate的Raw字节放入tls.Certificate的Certificate切片。

答案 1 :(得分:0)

你可以这样做:

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
}