24

I'm trying to communicate with a server. This server send me a certificate and a private key in order to execute my request successfully.

To test the server, I use Postman. So I fill the certificate setting in postman, and my request works fine

Postman settings for certificates

Now I want to do the same in C#.

For that I use RestSharp in order to create the request.

Here is my code

 var client = new RestClient(url);

 byte[] certBuffer = UtilsService.GetBytesFromPEM(myCertificate, Models.Enum.PemStringType.Certificate);
 byte[] keyBuffer = UtilsService.GetBytesFromPEM(encryptedPrivateKey, Models.Enum.PemStringType.RsaPrivateKey);

 X509Certificate2 certificate = new X509Certificate2(certBuffer, secret);
 client.ClientCertificates = new X509CertificateCollection() { certificate };
 var request = new RestRequest(Method.POST);
 request.AddHeader("Cache-Control", "no-cache");
 request.AddHeader("Accept", "application/json");
 request.AddHeader("Content-Type", "application/json");
 request.AddParameter("myStuff", ParameterType.RequestBody);
 IRestResponse response = client.Execute(request);

The request doesn't work. I think the problem is from how I load the certificate in RestSharp.

I'm looking for information how to set correctly the certificate in RestSharp.

I'm using RestSharp, but I could be anything else that can work in C#

dpfauwadel
  • 3,866
  • 3
  • 23
  • 40
  • 1
    Don't know if you're using it or not, but Postman has a built in feature where you can export your request for most well known languages. C# happens to be one of them, and it uses the RestSharp library. Just click the code button at the top-ish right corner of the screen and select c#. If you already know about this it may seem obvious, sorry about that! –  Mar 02 '18 at 13:36
  • 1
    Yes, I already generate the code by this way. But it doesn't take into account the certificates... – dpfauwadel Mar 02 '18 at 14:24
  • Gotcha. Sorry, I wish I could, but I don't know how to help you. –  Mar 02 '18 at 15:16

3 Answers3

41

Ok, I got the solution.

First of all, I had to stop using the .crt and the .key for the certificate. I have to get a .pfx. This can be done with openssl command (openssl documentation)

openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt

After creating the certificate, just add it to the request like this

var client = new RestClient(url);

ServicePointManager.Expect100Continue = true;
ServicePointManager.DefaultConnectionLimit = 9999;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3;

var certFile = Path.Combine(certificateFolder, "certificate.pfx");
X509Certificate2 certificate = new X509Certificate2(certFile, onboard.authentication.secret);
client.ClientCertificates = new X509CertificateCollection() { certificate };
client.Proxy = new WebProxy();
var restrequest = new RestRequest(Method.POST);
restrequest.AddHeader("Cache-Control", "no-cache");
restrequest.AddHeader("Accept", "application/json");
restrequest.AddHeader("Content-Type", "application/json");
restrequest.AddParameter("myStuff", ParameterType.RequestBody);
IRestResponse response = client.Execute(restrequest);
Irvin Dominin
  • 30,819
  • 9
  • 77
  • 111
dpfauwadel
  • 3,866
  • 3
  • 23
  • 40
  • 1
    +1 to both Q&A. I spent an hour searching for a simple solution. Finally, something that works. Thanks!! – Gaspa79 Sep 19 '18 at 18:28
  • thank you, thank you, thank you a 1,000 times thank you. Been looking and struggling for hours for this very simple solution – Bob Tate Oct 25 '20 at 13:43
  • 3
    This work for me after I add this line `System.Net.ServicePointManager.ServerCertificateValidationCallback += (s, cert, chain, sslPolicyErrors) => true;` - I hope this might be useful for others. – Arindam Nayak Jun 10 '21 at 13:13
  • Thank you! for those people who get stucked also running the command add this to the end of your command -passout pass:myPassWord – FritsJ Jul 12 '21 at 10:41
  • I was able to use a .p12 file instead of a .pfx. `var certFile = Path.Combine("C:\\Projects\\Certs\\", "CERTFILE_SHA2.p12");` – Cale Sweeney Nov 11 '21 at 19:07
  • @Arindam-Nayak you skip certificate with this line of code :) – Akbar Asghari Dec 04 '21 at 13:05
  • Is the proxy required to use the certificate? Why is that proxy there? Referring to this: `client.Proxy = new WebProxy();` – Cale Sweeney Jan 11 '22 at 16:35
  • I am getting this error - System.Net.ServicePoint: The requested security protocol is not supported. – Tarun Bhatt Dec 11 '22 at 00:43
  • if anyone looking up again this solution: now clientCertificates are passed via options. new RestClientOptions().ClientCertificates = ... br – alexDuty Feb 09 '23 at 16:32
1

This wasn't explicit but I think this is it.

 var options = new RestClientOptions(url)
        {
            ClientCertificates = new System.Security.Cryptography.X509Certificates.X509CertificateCollection() { certificate.Certificate }
           
        };
        var client = new RestClient(options);
Rob
  • 2,363
  • 7
  • 36
  • 54
0

Using RestSharp v107 this did not work for me. I did find a solution as posted here : https://stackoverflow.com/a/73559615/3266995

In Summary - the RestClient constructor uses the Options certificates to configure the HttpClientHandler, but setting the certificate into the Options after the construction of the RestClient did not then go on to add the certificate to the underlying HttpClientHandler object.

DavidCC
  • 315
  • 2
  • 10