无法获得双向 SSL 以与 HttpWebRequest 一起使用
Can't get two-way SSL to work with HttpWebRequest
我有一个 WCF 服务应用程序,它应该连接到另一个服务器 X 以检索数据。当服务器 X 配置了单向 SSL 时,WCF 服务应用程序能够毫无问题地连接到它。但是当服务器 X 配置了双向 SSL 时,WCF 服务应用程序将无法连接到它。
WCF 服务应用程序使用自签名证书。该证书在没有私钥的情况下导出到 .cer 文件中,并导入到服务器 X 的信任库中。 WCF 服务应用程序的代码中使用了相同的导出证书:
string URL = "https://11.205.112.49:5311/Ping";
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(URL);
X509Certificate2 Certificate = new X509Certificate2("F:\cert.cer");
Request.ClientCertificates.Add(Certificate);
Request.Method = "GET";
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
上面代码的最后一行将抛出 WebException 并显示以下消息:
The request was aborted: Could not create SSL/TLS secure channel.
上面的错误没有提供太多细节。
感谢帮助。
提前致谢。
编辑:
这是我的整个程序:
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.IO;
namespace TestTwoWaySSL
{
class Program
{
static void Main(string[] args)
{
HttpWebResponse Response = null;
try
{
string URL = "https://11.205.112.49:5311/Ping";
Console.WriteLine("URL: [{0}].", URL);
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(URL);
X509Certificate2 Certificate = new X509Certificate2("F:\cert.pfx", "password");
Request.ClientCertificates.Add(Certificate);
Request.Method = "GET";
Console.WriteLine("Sending request.");
Response = (HttpWebResponse)Request.GetResponse();
Console.WriteLine("Request sent.");
}
catch (WebException webException)
{
Console.WriteLine("Web exception occurred: [{0}].", webException.Message);
Console.WriteLine(webException.StackTrace);
Response = webException.Response as HttpWebResponse;
}
catch (Exception exception)
{
Console.WriteLine("Exception occurred: [{0}].", exception.Message);
Console.WriteLine(exception.StackTrace);
}
Console.WriteLine("Response status code: [{0}].", Response.StatusCode);
Console.WriteLine("Response \"Content-Type\" header value: [{0}].", Response.ContentType);
Console.WriteLine("Response \"Content-Length\" header value: [{0}].", Response.ContentLength);
String ResponseMessageBody = new StreamReader(Response.GetResponseStream()).ReadToEnd();
Console.WriteLine("Response message body: [{0}].", ResponseMessageBody);
}
}
}
当它到达行 Request.GetResponse() 时,抛出 AccessVioationException:
Unhandled Exception: System.AccessViolationException: Attempted to read or write
protected memory. This is often an indication that other memory is corrupt.
at System.Net.UnsafeNclNativeMethods.SafeNetHandles_SECURITY.AcquireCredentialsHandleW(String principal, String moduleName, Int32 usage, Void* logonID, SecureCredential& authData, Void* keyCallback, Void* keyArgument, SSPIHandle& handlePtr, Int64& timeStamp)
at System.Net.SafeFreeCredentials.AcquireCredentialsHandle(SecurDll dll, String package, CredentialUse intent, SecureCredential& authdata, SafeFreeCredentials& outCredential)
at System.Net.SSPISecureChannelType.AcquireCredentialsHandle(String moduleName, CredentialUse usage, SecureCredential& authdata, SafeFreeCredentials& outCredential)
at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface SecModule, String package, CredentialUse intent, SecureCredential scc)
at System.Net.Security.SecureChannel.AcquireCredentialsHandle(CredentialUse credUsage, SecureCredential& secureCredential)
at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint)
at System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output)
at System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count)
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.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
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.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.TlsStream.CallProcessAuthentication(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.ConnectStream.WriteHeaders(Boolean async)
at System.Net.HttpWebRequest.EndSubmitRequest()
at System.Net.HttpWebRequest.SetRequestSubmitDone(ConnectStream submitStream)
at System.Net.Connection.CompleteConnection(Boolean async, HttpWebRequest request)
at System.Net.Connection.CompleteStartConnection(Boolean async, HttpWebRequest httpWebRequest)
at System.Net.Connection.CompleteStartRequest(Boolean onSubmitThread, HttpWebRequest request, TriState needReConnect)
at System.Net.Connection.SubmitRequest(HttpWebRequest request, Boolean forcedsubmit)
at System.Net.ServicePoint.SubmitRequest(HttpWebRequest request, String connName)
at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint)
at System.Net.HttpWebRequest.GetResponse()
at TestTwoWaySSL.Program.Main(String[] args)
问题是您缺少私钥。您只使用了证书。
要么在 loading certificate into X509Certificate2 class
时使用 pkcs#12
X509Certificate2 Certificate = new X509Certificate2("F:\cert.p12", "p12 password");
X509Store store = new X509Store("MY",StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2 certificate = collection.Find(...)[0];
store.Close();
我有一个 WCF 服务应用程序,它应该连接到另一个服务器 X 以检索数据。当服务器 X 配置了单向 SSL 时,WCF 服务应用程序能够毫无问题地连接到它。但是当服务器 X 配置了双向 SSL 时,WCF 服务应用程序将无法连接到它。
WCF 服务应用程序使用自签名证书。该证书在没有私钥的情况下导出到 .cer 文件中,并导入到服务器 X 的信任库中。 WCF 服务应用程序的代码中使用了相同的导出证书:
string URL = "https://11.205.112.49:5311/Ping";
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(URL);
X509Certificate2 Certificate = new X509Certificate2("F:\cert.cer");
Request.ClientCertificates.Add(Certificate);
Request.Method = "GET";
HttpWebResponse Response = (HttpWebResponse)Request.GetResponse();
上面代码的最后一行将抛出 WebException 并显示以下消息:
The request was aborted: Could not create SSL/TLS secure channel.
上面的错误没有提供太多细节。
感谢帮助。
提前致谢。
编辑:
这是我的整个程序:
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.IO;
namespace TestTwoWaySSL
{
class Program
{
static void Main(string[] args)
{
HttpWebResponse Response = null;
try
{
string URL = "https://11.205.112.49:5311/Ping";
Console.WriteLine("URL: [{0}].", URL);
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(URL);
X509Certificate2 Certificate = new X509Certificate2("F:\cert.pfx", "password");
Request.ClientCertificates.Add(Certificate);
Request.Method = "GET";
Console.WriteLine("Sending request.");
Response = (HttpWebResponse)Request.GetResponse();
Console.WriteLine("Request sent.");
}
catch (WebException webException)
{
Console.WriteLine("Web exception occurred: [{0}].", webException.Message);
Console.WriteLine(webException.StackTrace);
Response = webException.Response as HttpWebResponse;
}
catch (Exception exception)
{
Console.WriteLine("Exception occurred: [{0}].", exception.Message);
Console.WriteLine(exception.StackTrace);
}
Console.WriteLine("Response status code: [{0}].", Response.StatusCode);
Console.WriteLine("Response \"Content-Type\" header value: [{0}].", Response.ContentType);
Console.WriteLine("Response \"Content-Length\" header value: [{0}].", Response.ContentLength);
String ResponseMessageBody = new StreamReader(Response.GetResponseStream()).ReadToEnd();
Console.WriteLine("Response message body: [{0}].", ResponseMessageBody);
}
}
}
当它到达行 Request.GetResponse() 时,抛出 AccessVioationException:
Unhandled Exception: System.AccessViolationException: Attempted to read or write
protected memory. This is often an indication that other memory is corrupt.
at System.Net.UnsafeNclNativeMethods.SafeNetHandles_SECURITY.AcquireCredentialsHandleW(String principal, String moduleName, Int32 usage, Void* logonID, SecureCredential& authData, Void* keyCallback, Void* keyArgument, SSPIHandle& handlePtr, Int64& timeStamp)
at System.Net.SafeFreeCredentials.AcquireCredentialsHandle(SecurDll dll, String package, CredentialUse intent, SecureCredential& authdata, SafeFreeCredentials& outCredential)
at System.Net.SSPISecureChannelType.AcquireCredentialsHandle(String moduleName, CredentialUse usage, SecureCredential& authdata, SafeFreeCredentials& outCredential)
at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface SecModule, String package, CredentialUse intent, SecureCredential scc)
at System.Net.Security.SecureChannel.AcquireCredentialsHandle(CredentialUse credUsage, SecureCredential& secureCredential)
at System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint)
at System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output)
at System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count)
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.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
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.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
at System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
at System.Net.TlsStream.CallProcessAuthentication(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
at System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.ConnectStream.WriteHeaders(Boolean async)
at System.Net.HttpWebRequest.EndSubmitRequest()
at System.Net.HttpWebRequest.SetRequestSubmitDone(ConnectStream submitStream)
at System.Net.Connection.CompleteConnection(Boolean async, HttpWebRequest request)
at System.Net.Connection.CompleteStartConnection(Boolean async, HttpWebRequest httpWebRequest)
at System.Net.Connection.CompleteStartRequest(Boolean onSubmitThread, HttpWebRequest request, TriState needReConnect)
at System.Net.Connection.SubmitRequest(HttpWebRequest request, Boolean forcedsubmit)
at System.Net.ServicePoint.SubmitRequest(HttpWebRequest request, String connName)
at System.Net.HttpWebRequest.SubmitRequest(ServicePoint servicePoint)
at System.Net.HttpWebRequest.GetResponse()
at TestTwoWaySSL.Program.Main(String[] args)
问题是您缺少私钥。您只使用了证书。
要么在 loading certificate into X509Certificate2 class
时使用 pkcs#12X509Certificate2 Certificate = new X509Certificate2("F:\cert.p12", "p12 password");
X509Store store = new X509Store("MY",StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2 certificate = collection.Find(...)[0];
store.Close();