从pem文件加载X509Certificate2。结果作为ClientCertificates使用时没有凭据可用。

5
我需要向服务器发送请求。为了访问服务器,这个请求需要一个证书。
如果我加载P12文件并将其注册为我的http客户端上的证书,那么它可以正常工作。
var clientCertificate = new X509Certificate2(pathToTestCert, passToTestCert);
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(clientCertificate );

然而,如果我使用CreateFromPemFile从pem文件中加载证书。

var clientCertificate= X509Certificate2.CreateFromPemFile(purePem);
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(clientCertificate);

当向服务器发送请求时,我会收到什么信息。

System.IO.IOException: The read operation failed, see inner exception.
 ---> System.ComponentModel.Win32Exception (0x8009030E): No credentials are available in the security package
   at System.Net.SSPIWrapper.AcquireCredentialsHandle(ISSPIInterface secModule, String package, CredentialUse intent, SCH_CREDENTIALS* scc)
   at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(CredentialUse credUsage, SCH_CREDENTIALS* secureCredential)
   at System.Net.Security.SslStreamPal.AcquireCredentialsHandleSchCredentials(X509Certificate2 certificate, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer)
   at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(SslStreamCertificateContext certificateContext, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer)
   at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint)
   at System.Net.Security.SecureChannel.GenerateToken(ReadOnlySpan`1 inputBuffer, Byte[]& output)
   at System.Net.Security.SecureChannel.NextMessage(ReadOnlySpan`1 incomingBuffer)
   at System.Net.Security.SslStream.ProcessBlob(Int32 frameSize)
   at System.Net.Security.SslStream.ReceiveBlobAsync[TIOAdapter](TIOAdapter adapter)
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
   at System.Net.Security.SslStream.ReplyOnReAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Byte[] buffer)
   at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)
   --- End of inner exception stack trace ---
   at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)
   at System.Net.Http.HttpConnection.InitialFillAsync(Boolean async)
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken
        

请注意,如果在文本编辑器中打开pem文件,其内容应如下所示。

-----BEGIN PRIVATE KEY-----
.
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
.....
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
................
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
.................
-----END CERTIFICATE-----

看起来你的.pem文件包含两个证书。默认情况下使用第一个。那是正确的吗? - klekmek
不确定如何回答那个问题。我们使用openssl pkcs12 -in path.p12 -out newfile.key.pem -nocerts -nodes将p12导出为pem文件。 - Linda Lawton - DaImTo
您可以提取证书并将它们放在不同的文件中,在发出请求时使用公钥。 - klekmek
1个回答

12

在Windows上,TLS层要求私钥以特定的方式写入磁盘。使用基于PEM格式的证书加载不会这样做,只有基于PFX格式的加载才能实现。

让TLS层正常工作最简单的方法是执行:

cert = new X509Certificate2(cert.Export(X509ContentType.Pfx));

也就是说,将证书和密钥导出到PFX文件,然后立即重新导入(以获得密钥被临时写入磁盘并使SChannel能够找到的副作用)。您不需要打扰默认的PFX加载标志,尽管一些复杂限制的用户可能需要使用MachineKeySet。

1
这只是在Windows上的问题吗?如果我在Docker容器中运行它会发生什么?顺便说一句,谢谢,它起作用了。 - Linda Lawton - DaImTo
为了避免忘记如何操作,以下是如何使用 pem 文件与 X509Certificate2 的方法。链接 - Linda Lawton - DaImTo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接