双向 SSL - X509Certificate2.CreateFromPemFile - WINHTTP_CALLBACK_STATUS_REQUEST_ERROR

Two way SSL - X509Certificate2.CreateFromPemFile - WINHTTP_CALLBACK_STATUS_REQUEST_ERROR

我正在尝试调用需要双向 SSL (TLS 1.2) 的 API,并且我有以下代码:

var myCert = X509Certificate2.CreateFromPemFile(_publicFilename, _privateFilename);

using (var handler = new WinHttpHandler())
{
    handler.ClientCertificateOption = ClientCertificateOption.Manual;
    handler.ServerCertificateValidationCallback = (x, y, z, w) => true;
    handler.ClientCertificates.Add(myCert);
    handler.SslProtocols = SslProtocols.Tls12;

    using (var client = new HttpClient(handler))
    {
        var postData = new StringContent("", UnicodeEncoding.UTF8, "application/json");
        var response = await client.PostAsync("<API Endpoint>", postData);

        string responseString = await response.Content.ReadAsStringAsync();
        Console.WriteLine(responseString);
    }
}

但是,当我调用它时,出现以下 WinHttp 异常:

Error 12185 calling WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, 'No credentials were available in the client certificate.'.

同样在 windows 事件查看器中,我收到以下错误消息:

The TLS client credential's certificate does not have a private key information property attached to it. This most often occurs when a certificate is backed up incorrectly and then later restored. This message can also indicate a certificate enrollment failure.

无法弄清楚问题出在哪里。我在邮递员中使用完全相同的证书和密钥,它工作正常。

Windows 上的 TLS(WinHttpHandler、SslStream 或默认的 HTTP 处理程序(使用 SslStream))要求证书具有命名的私钥。

您可以通过在没有 PersistKeySet 的情况下导入 PFX 来临时执行此操作...但是您如何获得 PFX?嗯,很简单。

var myCert = X509Certificate2.CreateFromPemFile(_publicFilename, _privateFilename);

using (var tmpCert = new X509Certificate2(myCert.Export(X509ContentType.Pfx)))
using (var handler = new WinHttpHandler())
{
    ...
    handler.ClientCertificates.Add(tmpCert);
    ...
}

当 tmpCert 被处置时,指定的密钥将被删除。如果您的生命周期很复杂或很长,则可以不在 using 语句中创建证书。如果证书被垃圾收集并且进程保持活动状态足够长的时间以 运行 终结器,那么密钥将被清理。