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},
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 WPF 大屏看板表格背景图片设置
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示