golang client cert相关

尝试构建微信支付相关的模块,按照微信的安全要求,需要使用指定证书进行 https 通信,记录下遇到的问题及安全方面相关的事宜。

按照微信的文档,他提供了4份文件,分别是:*.p12, *_cert.pem, *_key.pem, *ca.pem

其中 *ca.pem 用于环境不具备 ca-certificates 时手动加载证书时使用。比如纯净的alpine下。这种情况一般 docker 较常见,但现在第三方接口基本已经 https 化,构建docker时会添加ca lib。

不多说,上代码。

var client *http.Client

func init() {
    fb, err := ioutil.ReadFile("apiclient_cert.p12")
    if err != nil {
        panic(err)
    }

    b, err := pkcs12.ToPEM(fb, "mchId") // the password is mchId
    if err != nil {
        panic(err)
    }

    if len(b) != 2 {
        panic(errors.New("check p12, len not match"))
    }

    cert, err := tls.X509KeyPair(pem.EncodeToMemory(b[0]), pem.EncodeToMemory(b[1]))
    if err != nil {
        panic(err)
    }

    // Load client cert using pem is not safe.
    //cert, err := tls.LoadX509KeyPair("apiclient_cert.pem", "apiclient_key.pem")
    //if err != nil {
    //  panic(err)
    //}

    // Load CA cert
    caCert, err := ioutil.ReadFile("rootca.pem")
    if err != nil {
        panic(err)
    }

    caCertPool := x509.NewCertPool()
    caCertPool.AppendCertsFromPEM(caCert)

    // Setup HTTPS client
    tlsConfig := &tls.Config{
        Certificates: []tls.Certificate{cert},
        RootCAs:      caCertPool,
    }
    tlsConfig.BuildNameToCertificate()
    transport := &http.Transport{TLSClientConfig: tlsConfig}

    client = &http.Client{Transport: transport}
}