Click here to Skip to main content
13,550,950 members
Click here to Skip to main content
Add your own
alternative version


10 bookmarked
Posted 21 Apr 2011
Licenced CPOL

SSL Peer Verification

, 21 Apr 2011
Rate this:
Please Sign up or sign in to vote.
Verifying the Server Certificate on the client side using a CA file


When calling a Web Service using HTTPS and SSL, Host Verification and Peer Verification are to be handled for security. This article shows and explains how Peer Verification can be done successfully when calling a Web Service via HTTPS that is secured by SSL.

Using the Code

Mostly Web Services are hosted on HTTPS and are secured by SSL so others can't use it. Many times when we surf an HTTPS site, we get a certificate dialog asking us to trust the provider. This is the Server Certificate that is sent by the web server. We accept the certificate and proceed ahead. In desktop applications, when we perform a similar task like accessing a Web Service which uses HTTPS and SSL, we can't receive any dialog to trust the certificate and there comes the problem.

This can be easily achieved by creating our own CertificatePolicy class that implements the ICertificatePolicy interface. For instance, such a class could be written as:

public class MyPolicy : ICertificatePolicy {

    public MyPolicy() {

    public bool CheckValidationResult(ServicePoint srvPoint, 
                X509Certificate certificate, 
                WebRequest request, int certificateProblem)
        // Perform operations to verify
        // the certificate and return true or false 
        return true;

And can set:

ServerCertificateValidationonCallback = MyPolicy();

The above code can also be written using a delegate of System.Net.ServicePointManager.ServerCertificateValidationonCallback.

ServicePointManager.ServerCertificateValidationCallback = {
     (Object sender, X509Certificate certificate, X509Chain chain, 
             SslPolicyErrors sslPolicyErrors) {
         return true;

The above code accepts the Server Certificate (the dialog that pops up on the browser to trust the provider). It implicitly returns true, that means it accepts any server certificate and proceeds ahead accessing the Web Service.

This is so simple and easy. But if SSL is specially meant for security and cryptography and can be bypassed so easily, then what sense does SSL make? Nothing, right?

When our client verifies this server certificate against any certificate file, i.e., without verifying the verify certificate to verify the server certificate, the client can't access any Web Service from the provider. This is like providing a password or authenticating password. Without actually authenticating, a Web Service that gives and takes data should be easy to fake. Thus we need to verify the Server Certificate using a "Right" version of the verification certificate*. Verification Certificate is just a CA file that compares the server certificates data. If both match, it returns true and lets us access Web Services, else it returns false and doesn't let us access a Web Service and its confidential data.

Note *: The certificate used to verify is not the same as Client Certificate, both are different and so are their roles. A Client Certificate is passed to the server if the server needs a Client Certificate. It can be set using the request.ClientCertificates property.

Now comes the point: how do we verify that the server certificate is correct or the server certificate matches the verify certificate? Fake users can change the Server Certificate or the certificate used to verify, so we got to take care on both sides.

Here is the code that helps you to accept the server certificate and also verify the certificate against a CA file.

Remember: Acceptance of Server Certificate code should be set only once in the whole application life cycle. And it will be called automatically whenever a request is made. So for ease of coding, we will separate the SSL Certificate part with the request part.

Here is the code to set and handle the SSL Certificate part:

// Certificate to verify 
private X509Certificate2 verifyCert = null;   

private void setSSLCertificate() {
     veriftCert = new X509Certificate2("ca_verify.crt");
     ServicePointManager.ServerCertificateValidationCallback += new 

public bool customCertificateValidation(Object sender, 
       X509Certificate certificate, X509Chain chain, 
       SslPolicyErrors sslPolicyErrors) 
      switch(sslPolicyErrors) {
           case RemoteCertificateChainErrors:
           case RemoteCertificateNameMismatch:
           case RemoteCertificateNotAvailable:
      // With this we have accepted the server certificate
      // Now, VERIFY the certificate against verifyCert
      // If details of both the certificates matches, then returns true, else false 
      return verifyCert.Verify();   

That's it. This is how Peer Verification is handled and should be taken care of without any hard coding or comparing in code.

Now whenever any request is performed, first customCertificateValidation() will be called and if that returns true, then the request will be able to proceed, else a WebException will be caught.

private void SendPost(String post_data) {

     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
       <a href=""></a>);
     request.KeepAlive = true;
     request.ContentType = "application/x-www-form-urlencoded";
     request.Method = "POST";
     byte[] postBytes = Encoding.ASCII.GetBytes(psot_data);
     Stream requestStream = null;

     try {
           // Send
           request.ContentLength = postBytes.Length;
           requestStream = request.GetRequestStream();
           requestStream.Write(postBytes, 0, postBytes.Length);
     } catch (WebException we) {

     // If our customCertificateValidation returns false, here it will be caught. 
     // You can check the status of WebException we.Status,
     // mostly it returns TrustFailure and handle them
     } catch(Exception e) {
          // Handle other normal request errors
     } finally {
          if (requestStream != null)

Don't forget to call setSSLCertificate() at the start of the application or whenever appropriate before calling any Web Service.

That's all for SSL Peer Verification. I am sure this will definitely help more developers who actually cross-check SSL verification and not just accept the server certificate blindly.

Let me know how it works.

Points of Interest

I wanted to perform SSL Peer Verification. I Googled and asked questions in forums a lot, but could only find how to accept a Server Certificate, not how to verify it, which is most important when you are accessing a Web Service that implements SSL security. Finally, when I figured out the solution, I thought about sharing it with all to make others' work a bit easier.


This is my first article on CodeProject. If I have made any mistakes, kindly let me know of it; any tips for improvements are appreciated.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

All Time Programming
Software Developer (Senior)
India India
I am a Freelance Software Developer and a Consultant. I provide service in Desktop, Client-Server, Database, Web and Mobile application developments. I like working on challenging projects and implementing new technologies and platforms.
I had started my career in IT development from DBase, COBOL, C and reached today to Java, C#, .NET, Android, BlackBerry (RIM), Windows Mobile, etc.

You may also be interested in...

Comments and Discussions

BugcustomCertificateValidation method does not validate certificate received from a server Pin
Alex V22-Dec-17 9:17
memberAlex V22-Dec-17 9:17 
GeneralMy vote of 4 Pin
cyrildex25-Apr-14 4:02
membercyrildex25-Apr-14 4:02 
GeneralMy vote of 5 Pin
Member 43208447-May-12 9:51
memberMember 43208447-May-12 9:51 
QuestionCan it detect Fiddler? Pin
Nimea5-Mar-12 10:49
memberNimea5-Mar-12 10:49 
AnswerRe: Can it detect Fiddler? Pin
All Time Programming7-Mar-12 2:51
memberAll Time Programming7-Mar-12 2:51 
QuestionDUAL authentication with web service (non SOAP) Pin
Sreenath Varma7-Feb-12 10:39
memberSreenath Varma7-Feb-12 10:39 
Your article gave me some idea on this. I am trying to do the similar thing but not able to achieve it. It will be great if you could help out here.

I am writing a web service in which will call another host's web services over SSL. I have both the server & client certificates (.cer) with me. The host guys are saying to use DUAL authentication (using both certificates). The web service call is not SOAP, it is through HTTP posts. Here is the function I have written which uses client & server (as in your sample) certificates. Which gives an error "The underlying connection was closed: The connection was closed unexpectedly on a send" and if I uncomment the line SecurityProtocolType.Ssl3, it gives another error "The request was aborted: Could not create SSL/TLS secure channel"..

private XmlDocument PostXMLTransaction(string url, XmlDocument xReqDoc)
     log.Debug("Inside Method");
     //Declare XMLResponse document
     XmlDocument XMLResponse = null;

     //Declare an HTTP-specific implementation of the WebRequest class.
     HttpWebRequest objHttpWebRequest;

     //Declare an HTTP-specific implementation of the WebResponse class
     HttpWebResponse objHttpWebResponse = null;

     //Declare a generic view of a sequence of bytes
     Stream objRequestStream = null;
     Stream objResponseStream = null;

     //Declare XMLReader
     XmlTextReader objXMLReader;

         //---------- Start HttpRequest

         //Creates an HttpWebRequest for the specified URL.
         log.Debug("Creates an HttpWebRequest for the specified URL.");
         log.DebugFormat("URL: - {0}", url);
         objHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);

         //Set HttpWebRequest properties
         log.Debug("Set HttpWebRequest properties");
         byte[] bytes;
         bytes = System.Text.Encoding.ASCII.GetBytes(xReqDoc.InnerXml);

         //validate server cert
         //System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();
         TrustAllCertificatePolicy policy = new TrustAllCertificatePolicy();
         policy.CheckValidationResult(objHttpWebRequest.ServicePoint, objHttpWebRequest.ServicePoint.Certificate, objHttpWebRequest, 0);

         //System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
         //ServicePointManager.Expect100Continue = false;
         //ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
         //objHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);

         //Add certificate from file
         //X509Certificate cer = X509Certificate.CreateFromCertFile("D://WARBA//warbabankCa.cer");

         //add certificate from store
         X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
         X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindBySerialNumber, "78e78f2f5441d68a42c39dc681bdaace", true);
         log.DebugFormat("Cert Count = {0}", col.Count.ToString());

         objHttpWebRequest.Method = "POST";
         objHttpWebRequest.ContentLength = bytes.Length;
         objHttpWebRequest.ContentType = "text/xml; encoding='utf-8'";
         objHttpWebRequest.KeepAlive = false;

         //Get Stream object
         log.Debug("Get Stream object ");
         objRequestStream = objHttpWebRequest.GetRequestStream();

         //Writes a sequence of bytes to the current stream
         log.Debug("Writes a sequence of bytes to the current stream");
         objRequestStream.Write(bytes, 0, bytes.Length);

         //Close stream
         log.Debug("Close stream");

         //---------- End HttpRequest

         //Sends the HttpWebRequest, and waits for a response.
         log.Debug("Sends the HttpWebRequest, and waits for a response.");
         objHttpWebResponse = (HttpWebResponse)objHttpWebRequest.GetResponse();

         //---------- Start HttpResponse
         if (objHttpWebResponse.StatusCode == HttpStatusCode.OK)
             log.Debug("Start HttpResponse");
             //Get response stream
             objResponseStream = objHttpWebResponse.GetResponseStream();

             //Load response stream into XMLReader
             log.Debug("Load response stream into XMLReader");
             objXMLReader = new XmlTextReader(objResponseStream);

             //Declare XMLDocument
             XmlDocument xmldoc = new XmlDocument();

             //Set XMLResponse object returned from XMLReader
             XMLResponse = xmldoc;

             //Close XMLReader

         //Close HttpWebResponse
         log.Debug("Close HttpWebResponse");
     catch (WebException we)
         //TODO: Add custom exception handling
     catch (Exception ex)
         //throw new Exception(ex.Message);
         //Close connections
         if (objRequestStream != null)
         if (objRequestStream != null)
         if (objHttpWebResponse != null)

         //Release objects
         objXMLReader = null;
         objRequestStream = null;
         objResponseStream = null;
         objHttpWebResponse = null;
         objHttpWebRequest = null;

     return XMLResponse;

GeneralMy vote of 5 Pin
Member 43208446-Jan-12 9:16
memberMember 43208446-Jan-12 9:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.180515.1 | Last Updated 21 Apr 2011
Article Copyright 2011 by All Time Programming
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid