I am trying to connect to a WCF service with c# (SOAP Service). I am using a SLL/TLS version 1.2 certificate. The certificate has the extension .p12. The certificate is correct as when I make the request in the web browser everything flows correctly. It is also installed in MMC. The problem is in the client, which makes the connection but at the last moment the connection is closed, skipping the exception in the title. I have observed the traffic with Wireshark and both the connection to the server and the decryption of the key are done correctly. Could someone help me with this error? I leave you the code and the content of the App.config and the output of the error together with the one of the stack. Thanks in advance
PD: Using RestSharp, it connects the client perfectly, and I get all the xml from the query, but it is more tedious. Because I have to be sending headers, bodies, etc.. for each query. With WCF is more comfortable and I would like to use it.
static void Main(string[] args)
{
// Set TLS version 1.2
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Certificate file path and password
string certFilePath = @"MyPath\MyCertificate.p12";
SecureString certPassword = GetSecureString("MyPassword");
// Upload the certificate from the file
X509Certificate2 cert = new X509Certificate2(
certFilePath,
certPassword,
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
Console.WriteLine(cert);
// Deciphering the key
try
{
RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)cert.PrivateKey;
rsa.PersistKeyInCsp = false;
RSAParameters rsaParams = rsa.ExportParameters(true);
// Obtain the SHA-256 summary of the certificate
SHA256Managed sha256 = new SHA256Managed();
byte[] certHash = sha256.ComputeHash(cert.RawData);
string certHashString = Convert.ToBase64String(certHash);
Console.WriteLine("Private key successfully decrypted.");
Console.WriteLine("SHA-256 summary of the certificate: " + certHashString);
}
catch (Exception ex)
{
Console.WriteLine("Error decrypting the private key: " + ex.ToString());
}
Console.ReadLine();
// We make the inquiry through WCF
try
{
// Create a WCF client instance
QueryServiceClient clienteQuery = new QueryServiceClient();
// Configuring the certificate in the WCF client
//clienteQuery.ClientCredentials.ClientCertificate.Certificate = cert;
clienteQuery.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindByThumbprint,
cert.Thumbprint
);
// Using WCF client methods
var accessProfiles = clienteQuery.getAccessProfiles();
foreach (var profile in accessProfiles)
{
Console.WriteLine("Access profile: " + profile);
}
Console.ReadLine();
// Close the client after use
//clienteQuery.Close();
}
catch (Exception ex)
{
// Handle any exception
Console.WriteLine("Exception: " + ex.ToString());
Console.ReadLine();
}
}
// Method for SecureString
private static SecureString GetSecureString(string password)
{
SecureString secureString = new SecureString();
foreach (char c in password)
{
secureString.AppendChar(c);
}
return secureString;
}
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03fkg89kg890a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="WorkServicePortBinding">
<security mode="Transport" />
</binding>
<binding name="WorkServicePortBinding1" />
<binding name="QueryServicePortBinding">
<security mode="Transport" />
</binding>
<binding name="QueryServicePortBinding1" />
<binding name="ImportServicePortBinding">
<security mode="Transport" />
</binding>
<binding name="ImportServicePortBinding1" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://mywebAPI.com:8989/work/v2/"
binding="basicHttpBinding" bindingConfiguration="WorkServicePortBinding"
contract="WorkServices.WorkService" name="WorkServicePort" />
<endpoint address="https://mywebAPI.com:8989/query/v2/"
binding="basicHttpBinding" bindingConfiguration="QueryServicePortBinding"
contract="QueryServices.QueryService" name="QueryServicePort" />
<endpoint address="https://mywebAPI.com:8989/import/v2/"
binding="basicHttpBinding" bindingConfiguration="ImportServicePortBinding"
contract="ImportServices.ImportService" name="ImportServicePort" />
</client>
</system.serviceModel>
</configuration>
Exception: System.ServiceModel.Security.SecurityNegotiationException: Failed to establish a secure channel for SSL/TLS with the authority. 'mywebAPI.com:8989'. ---> System.Net.WebException: Anulada la solicitud: No se puede crear un canal seguro SSL/TLS.
en System.Net.HttpWebRequest.GetResponse()
en System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
--- End of internal exception stack tracking ---
Server stack trace:
en System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException, HttpWebRequest request, HttpAbortReason abortReason)
en System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
en System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
en System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
en System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
en System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
en System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
I was trying to query a service to receive data. I did what I show in the code but the connection closes without fetching the data.
I think the reason might be that the client can't find the corresponding certificate. You can try adding the following to your configuration file:
findValue:Certificate name
x509FindType:Type
StoreLocation:Storage location
Storename:Storage Name