我正在尝试开发一个跨平台应用程序(windows/mac os x),该应用程序需要签署 XML 文件并使用 ClientCertificate 身份验证在服务器上发出 Web 请求......
主要限制是我需要在智能卡上使用证书......
我目前正在使用 dotnet core 2.1。
首先,我确实尝试使用 dotnet core X509Store,但在 MacOs 上我无论如何都无法访问 PrivateKey 对象(XML 签名所必需的),然后我放弃了这条线索。
然后我使用 pkcs11interop 和特定于供应商的 dll 来访问智能卡,它适用于 XML 签名(我将 pkcs11interop 调用包装在 RSA 对象中,然后我将此对象用作 SignedXml 中的 SigningKey),但它不适用于 ClientCertificate联系。
通常我使用这种方法连接到服务器(dotnet framework 4.6.1,仅限 windows):
HttpWebRequest req = WebRequest.Create("https://sometlsserver.com/") as HttpWebRequest;
req.ClientCertificates.Add(cert);
HttpWebResponse res = req.GetResponse() as HttpWebResponse;
using (StreamReader sr = new StreamReader(res.GetResponseStream(), new UTF8Encoding(false)))
{
return sr.ReadToEnd();
}
并生成证书:
var certAttr = session.GetAttributeValue(handle, new List<CKA>
{
CKA.CKA_VALUE,
};
var cert = new X509Certificate2(certAttr[0].GetValueAsByteArray());
当我尝试连接我的经典方法时,我有几个例外:
System.Net.WebException: The SSL connection could not be established, see inner exception. Authentication failed, see inner exception.
---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
---> System.ComponentModel.Win32Exception: Le message reçu était inattendu ou formaté de façon incorrecte
--- End of inner exception stack trace ---
at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Security.SslState.ThrowIfExceptional()
at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__47_1(IAsyncResult iar)
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.CreateConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.WaitForCreatedConnectionAsync(ValueTask`1 creationTask)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at System.Net.HttpWebRequest.SendRequest()
at System.Net.HttpWebRequest.GetResponse()
--- End of inner exception stack trace ---
at System.Net.HttpWebRequest.GetResponse()
...
我认为在 TLS 握手期间所需的私钥进行的加密操作丢失了,它只是失败了......
我确实尝试在私钥属性中添加用于 XML 签名的 RSA 对象,但使用 dotnet core 它以 PlatformNotSupportedException 结尾...
cert.PrivateKey = myRSAObject; // simple
我想知道是否可以在不使用第三方库的情况下做到这一点......
注意:法语错误消息“消息意外或格式不正确”的翻译。
谢谢。
(编辑:更好的格式)