douyun1950 2019-05-14 11:36
浏览 269
已采纳

具有证书,私钥和通行短语的TLS

I am integrating with a bank server which has provided me with the certificates. I create a pem file out of the certificates, so now I have the Certificates, Private Key in a pem file and the Pass Phrase for the key separately.

The newly generated file pem is working for making an SSL connection using the OpenSSL command as follows:

openssl s_client -connect host:port -key key.pem -cert cert.pem

This command requests for the passphrase and I am able to connect. But I am not able to connect to the same using my Go code, which looks like this:

package main

import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "net/http"
)

func main() {
    caCert := []byte(`certs pem data`) // this contains both private key and certificates
    caCertPool := x509.NewCertPool()
    caCertPool.AppendCertsFromPEM(caCert)

    // Setup HTTPS client
    tlsConfig := &tls.Config{
        RootCAs:            caCertPool,
        InsecureSkipVerify: true,
    }
    tlsConfig.BuildNameToCertificate()
    transport := &http.Transport{TLSClientConfig: tlsConfig}
    client := &http.Client{Transport: transport}

    httpRequest, _ := http.NewRequest("GET", "https://test.com", nil)
    resp, err := client.Do(httpRequest)
    fmt.Printf("resp: [%v] 
 Error: [%v]", resp, err)
}

I am also not sure where to add the passphrase in my HTTP request.

The error I am getting: remote error: tls: bad certificate

  • 写回答

1条回答

  • drq1257 2019-05-14 13:03
    关注

    You seem to be confusing certificate authorities with client certificates. Client certificates prove to the server that you are who you say you are (much like a username and password would), and CAs are used so that you know that you're talking to the correct server.

    Judging from the openssl command that works for you, your bank gave you a client certificate and key (although that is highly unusal; no one except yourself should ever hold your private key and especially the passphrase).

    The tls.Config.Certificates field, if used by a client, is used to configure client certificates.

    Certificates contains one or more certificate chains to present to the other side of the connection. [...] Clients doing client-authentication may set either Certificates or GetClientCertificate.

    Certificates for TLS are typically loaded with tls.LoadX509KeyPair or tls.X509KeyPair. However, these functions do not directly support encrypted keys.

    Instead, you have to load the key yourself, decrypt it using x509.DecryptPEMBlock, and then you can use tls.X509KeyPair.

    The following example uses an EC key because its encoding is short, but it works the same with RSA keys.

    package main
    
    import (
        "crypto/tls"
        "crypto/x509"
        "encoding/pem"
        "fmt"
        "log"
        "net/http"
    )
    
    var bundle = []byte(`
    -----BEGIN EC PRIVATE KEY-----
    Proc-Type: 4,ENCRYPTED
    DEK-Info: AES-256-CBC,99586A658F5D2DAC4A8A3CA387CF71CE
    
    25EtKb7ycOI/5R47fYwpiaNERgYnCxCtcrMXJuOgueuxUXjiU0n93hpUpIQqaTLH
    dDKhsR1UHvGJVTV4h577RQ+nEJ5z8K5Y9NWFqzfa/Q5SY43kqqoJ/fS/OCnTmH48
    z4bL/dJBDE/a5HwJINgqQhGi9iUkCWUiPQxriJQ0i2s=
    -----END EC PRIVATE KEY-----
    -----BEGIN CERTIFICATE-----
    MIIB2TCCAX+gAwIBAgIUUTZvgwwnbC05WHgIHMXxrbZzr6wwCgYIKoZIzj0EAwIw
    QjELMAkGA1UEBhMCWFgxFTATBgNVBAcMDERlZmF1bHQgQ2l0eTEcMBoGA1UECgwT
    RGVmYXVsdCBDb21wYW55IEx0ZDAeFw0xOTA1MTQxMzAwMDJaFw0xOTA1MTUxMzAw
    MDJaMEIxCzAJBgNVBAYTAlhYMRUwEwYDVQQHDAxEZWZhdWx0IENpdHkxHDAaBgNV
    BAoME0RlZmF1bHQgQ29tcGFueSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
    AAScgLGx6SXchEo/s0X3AoF0mQkh3bGf9QY0s/2dPqf3/9irwz35DiDGoaP+FDZv
    HnUX+D3tUEPhxkLyzWKKT9HHo1MwUTAdBgNVHQ4EFgQU3eB8oRcmvzZrx9Dkb6ma
    MMtu1MkwHwYDVR0jBBgwFoAU3eB8oRcmvzZrx9Dkb6maMMtu1MkwDwYDVR0TAQH/
    BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiAvw/FqAmGbSlBklp6AHJy9kf9VPyhe
    RA93ccNQ+7m1fAIhAOXr8c2QsH2oOYRTbn6bPZjkYQ2jLMaxatKhChBIuyZA
    -----END CERTIFICATE-----
    `)
    
    func main() {
        keyBlock, certsPEM := pem.Decode(bundle)
    
        fmt.Println(x509.IsEncryptedPEMBlock(keyBlock)) // Output: true
    
        // Decrypt key
        keyDER, err := x509.DecryptPEMBlock(keyBlock, []byte("foobar"))
        if err != nil {
            log.Fatal(err)
        }
    
        // Update keyBlock with the plaintext bytes and clear the now obsolete
        // headers.
        keyBlock.Bytes = keyDER
        keyBlock.Headers = nil
    
        // Turn the key back into PEM format so we can leverage tls.X509KeyPair,
        // which will deal with the intricacies of error handling, different key
        // types, certificate chains, etc.
        keyPEM := pem.EncodeToMemory(keyBlock)
    
        cert, err := tls.X509KeyPair(certsPEM, keyPEM)
        if err != nil {
            log.Fatal(err)
        }
    
        config := &tls.Config{
            Certificates: []tls.Certificate{cert},
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题
  • ¥30 python代码,帮调试
  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊