Calling a REST web service over SSL

marc_s

I'm struggling to connect to a REST web service that's working only over HTTPS / SSL from my .NET application.

I received the certificate and private key to use as two separate files - a certificate.pem file which contains the certificate, and the webservice.key file which contains the private key. Those are both text files with BASE64 encoded binary data contained in them.

The provider also sent me a PDF showing how to call that web service using CURL and those two files, and that works just fine:

curl.exe -k -v "https://(URL)" --cert certificate.pem --key webservice.key

I need to use the -k option since there seems to be a self-signed certificate somewhere in the hierarchy of certs. Without this option, the call fails.

In order to call this web service from a .NET application (a console app for now), I used OpenSSL (on Windows) to combine these two files into a *.pfx file using this command:

openssl pkcs12 -export -out webservice.pfx -in certificate.pem -inkey webservice.key 

This seems to have worked, too - no errors were reported, the file was created and is about 3K in size and it's a totally binary file.

Now, I tried to call that web service from my .NET code something like this:

try
{
    // use the SSL protocol (instead of TLS)
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

    // ignore any certificate complaints
    ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { return true; };

    // create HTTP web request with proper content type
    HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
    request.ContentType = "application/xml;charset=UTF8";

    // grab the PFX as a X.509 certificate from disk
    string certFileName = Path.Combine(certPath, "webservice.pfx");

    // load the X.509 certificate and add to the web request
    X509Certificate cert = new X509Certificate(certFileName, "(top-secret password)");
    request.ClientCertificates.Add(cert);
    request.PreAuthenticate = true;

    // call the web service and get response
    WebResponse response = request.GetResponse();

    Stream responseStream = response.GetResponseStream();
}
catch (Exception exc)
{
    // log and print out error
}

However, I can try whatever I like (fiddling around with various settings, on the ServicePointManager and the HttpWebRequest, but I just keep getting these errors:

WebException: The underlying connection was closed: An unexpected error occurred on a send.

IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

SocketException: An existing connection was forcibly closed by the remote host

and no response - even though communicating with the service with CURL has worked just fine.....

What am I missing?? I'm a bit puzzled and mystified by all those certificates, private keys, service point manager options and so on - just waaaaay too many knob and switches to turn, set or turn off - what are the RIGHT settings here??

Update:

If I use

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

then the error just simply is:

WebException: The request was aborted: Could not create SSL/TLS secure channel.

S O L U T I O N :

In the end, with looking at the output from curl and a lot of help from @Alexandru and @JurajMajer, I was able to get this to work with this code:

try
{
    // use the TLS protocol 
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

    // create HTTP web request with proper content type
    HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
    request.ContentType = "application/xml;charset=UTF8";

    // grab the PFX as a X.509 certificate from disk
    string certFileName = Path.Combine(certPath, "webservice.pfx");

    // load the X.509 certificate and add to the web request
    X509Certificate2 cert = new X509Certificate2(certFileName, "(top-secret password)");
    request.ClientCertificates.Add(cert);
    request.PreAuthenticate = true;

    // call the web service and get response
    WebResponse response = request.GetResponse();

    Stream responseStream = response.GetResponseStream();

    string xmlContents = new StreamReader(responseStream).ReadToEnd();
}
catch (Exception exc)
{
    // log and print out error
}
Alexandru

You've used the X509Certificate(String, String) constructor with a PKCS#12 certificate, but that constructor only works for PKCS#7 certificates, as MSDN says it...

Initializes a new instance of the X509Certificate class using the name of a PKCS7 signed file and a password to access the certificate.

PKCS#7 does not include the private (key) part of a certificate/private-key pair, which you will need. This means you will need to use your PKCS#12 certificate given the nature of your certificate.

You may want to try the X509Certificate2(String, String) constructor with your existing PKCS#12 certificate, as this constructor is used with PKCS#12 (PFX) files that contain the certificate's private key, as MSDN says...

This constructor creates a new X509Certificate2 object using a certificate file name and a password needed to access the certificate. It is used with PKCS12 (PFX) files that contain the certificate's private key. Calling this constructor with the correct password decrypts the private key and saves it to a key container.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Calling web service with ssl certificates

From Dev

Calling liferay portlet as web service with REST API

From Dev

SSL error calling Perl web service via https using LWP

From Dev

Rest web service not found when calling from client

From Dev

Calling REST web service when user type in textbox

From Dev

REST API in Python over SSL

From Dev

Azure Web App calling on-prem service with Self-Signed SSL Cert

From Dev

Calling a Rest Service from a servlet

From Dev

Calling web service to web service; Architecture View

From Dev

Calling a SOAP service using REST service

From Dev

Calling a SOAP service using REST service

From Dev

login in REST web service

From Dev

Rest Web Service with scala

From Dev

POST method calling from service Angular 6 to the REST using web api in asp.net mvc

From Dev

Calling a web service using nodejs

From Dev

Calling a web service SOAP in java

From Dev

calling https web service methods

From Dev

standalone ssl web service in java

From Dev

SSL Certificate for Web Service in the Cloud

From Dev

HTTP Basic Authentication Over SSL for REST API

From Dev

SSL certification on C# service over TCP

From Dev

Calling a REST service inside another REST service (Apache Camel)

From Dev

Calling a REST service keeps failing (with RESTSharp)

From Dev

Mule : Calling a Rest service on mule context startup

From Dev

Calling my evil REST service from AngularJs

From Dev

Calling REST service method from AJAX

From Dev

Calling a REST service keeps failing (with RESTSharp)

From Dev

Calling a Rest WCF Service via HttpClient

From Dev

WCF Rest Service - worked great ... Until SSL