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 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题
  • ¥15 请完成下列相关问题!
  • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
  • ¥15 求daily translation(DT)偏差订正方法的代码
  • ¥15 js调用html页面需要隐藏某个按钮
  • ¥15 ads仿真结果在圆图上是怎么读数的
  • ¥20 Cotex M3的调试和程序执行方式是什么样的?
  • ¥20 java项目连接sqlserver时报ssl相关错误