Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

SSL Communication Between Applications

5.00/5 (4 votes)
4 Oct 2010CPOL4 min read 21.7K  
Step by step procedure of how to create the self signed certificate and how to configure the SSL connection.

Summary

The post shows the step by step procedure of how to create the self signed certificate and how to configure the SSL connection. The example then implements the HTTPS client server communication using Eneter.Messaging.Framework.

Introduction

SSL (Secure Socket Layer) is a standard security protocol to verify the identity of communicating parts and establish the encrypted communication.

Here is how the communication works (if only the server is certified):

  1. The client connects the server and asks for the digital certificate.
  2. The client verifies the received certificate (i.e. if the certificate is issued by a trusted authority, if the domain from the certificate matches the domain sending the certificate, ...)
  3. The client creates a session key, encrypts it with the public key from the received certificate and sends it to the server.
  4. The server decrypts the session key from the client and uses it to encrypt the content for the client.
  5. The client uses the session key to decrypt the content from the server.

Digital Certificate

The digital certificate is like an ID card. It identifies its owner. And same as in the real world, where ID cards are accepted only if they are issued by trusted authorities (If I create my own driver license, it would not probably be accepted by a policeman.), also digital certificates are accepted if they are issued by trusted authorities.

Therefore, it is important to check if the "ID card" can be accepted - i.e. if the digital certificate was issued (digital signed) by a trusted authority. Typically, for the world wide communication, the certificate is issued by a third party mutually trusted authority (e.g. Verisign).

Self Signed Certificate

In case the certificate does not have to be issued (digitally signed) by a trusted third party authority, we can generate our own self signed certificate (e.g. for testing purposes or internal intranet usage, ...).

1. Create Certificate

  1. Execute Visual Studio command prompt with Administrator privileges.
  2. makecert -r -n CN="127.0.0.1" -eku 1.3.6.1.5.5.7.3.1 -ss my -sr localmachine -sky exchange
    (Instead of 127.0.0.1, you can use your IP address or the domain name.
    More information about 'makecert' can be found here.)

2. Configure the certificate to be trusted

  1. Execute from the command prompt: mmc
  2. Choose 'Add/Remove Snap-in...'

  3. Doubleclick 'Certificates'

  4. Choose 'Computer account'

  5. The new certificate should be found under 'Personal Certificates'.

  6. The new certificate is among personal certificates, but it is not trusted. When we double-click the certificate, the following message will be there: "This CA Root certificate is not trusted. To enable trust, install this certificate in the Trusted Root Certification Authorities store."

  7. To resolve this issue, copy and paste the new certificate into 'Trusted Root Certification Authorities'.

  8. The certificate is trusted now.

4. Configure the certificate for a desired IP address and port

In our case, we configure the certificate for all IP addresses and the port 7788.

  1. Copy the 'Thumbprint' from the certificate, paste it to the Notepad and remove spaces between numbers - this thumbprint data will be used in the next step.

  2. Configure the IP address and the port for the certificate. Use your own thumbprint data in the command.

    The command for Windows Vista:

    netsh http add sslcert ipport=0.0.0.0:7788 
    certhash=a357e3f991763516a4119153e137df24f88f18ac 
    appid={00000000-0000-0000-0000-000000000000}

    The command for Windows XP:

    httpcfg set ssl /i 0.0.0.0:7788 /h a357e3f991763516a4119153e137df24f88f18ac

    (Note: You need to download HttpCfg.exe from Microsoft)

HTTPS Client Server Communication

The self signed certificate is now ready, and we can use it for the client server communication.
The following example implements the simple client-server with using Eneter.Messaging.Framework.
(The framework is free and can be downloaded from http://www.eneter.net/. The online help for developers can be found at http://www.eneter.net/OnlineHelp/EneterMessagingFramework/Index.html.)

Server Application

The server is a simple application listening to requests to count two numbers.

Important

  • The server domain must be same as the certificate name. It is 127.0.0.1 in our case. Otherwise the certificate check will fail on the client side and the connection will not be established.
  • The server must be executed with sufficient user rights. Execute it as Administrator for debugging purposes. Otherwise the server will fail to start.
C#
using System;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.HttpMessagingSystem;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;

namespace HttpService
{
    // Message requesting counting of two numbers.
    public class MyRequestMessage
    {
        public int Number1 { get; set; }
        public int Number2 { get; set; }
    };

    // Message returning the counting result.
    public class MyResponseMessage
    {
        public int Result { get; set; }
    };

    class Program
    {
        static void Main(string[] args)
        {
            // Create messaging using Https.
            IMessagingSystemFactory aMessagingFactory = new HttpMessagingSystemFactory();
            IDuplexInputChannel anInputChannel = 
        aMessagingFactory.CreateDuplexInputChannel("https://127.0.0.1:7788");

            // Create the message receiver that receives MyRequestMessage and 
            // responses MyResponseMessage.
            IDuplexTypedMessagesFactory aTypedMessages = 
        new DuplexTypedMessagesFactory(new XmlStringSerializer());
            IDuplexTypedMessageReceiver<MyResponseMessage, MyRequestMessage> 
        aMessageReceiver = aTypedMessages.CreateDuplexTypedMessageReceiver
                    <MyResponseMessage, MyRequestMessage>();
            
            // Subscribe to process incoming messages.
            aMessageReceiver.MessageReceived += MessageReceived;

            // Start listening for messages.
            Console.WriteLine("The server is listening.");
            aMessageReceiver.AttachDuplexInputChannel(anInputChannel);
        }

        // Processes incoming messages.
        static void MessageReceived(object sender, 
        TypedRequestReceivedEventArgs<MyRequestMessage> e)
        {
            if (e.ReceivingError == null)
            {
                // Count incoming numbers.
                MyResponseMessage aResponse = new MyResponseMessage();
                aResponse.Result = e.RequestMessage.Number1 + e.RequestMessage.Number2;

                Console.WriteLine("Result = " + aResponse.Result.ToString());

                // Response the result back to the sender.
                IDuplexTypedMessageReceiver<MyResponseMessage, 
        MyRequestMessage> aReceiver = (IDuplexTypedMessageReceiver
        <MyResponseMessage, MyRequestMessage>)sender;
                aReceiver.SendResponseMessage(e.ResponseReceiverId, aResponse);
            }
        }
    }
}

Client Application

The client is a simple application sending the request to the server to count two numbers.
The whole implementation is here:

C#
using System;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.HttpMessagingSystem;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;

namespace HttpClient
{
    // Message requesting counting of two numbers.
    public class MyRequestMessage
    {
        public int Number1 { get; set; }
        public int Number2 { get; set; }
    };

    // Message returning the counting result.
    public class MyResponseMessage
    {
        public int Result { get; set; }
    };

    class Program
    {
        static void Main(string[] args)
        {
            // Create messaging using Https.
            IMessagingSystemFactory aMessagingFactory = new HttpMessagingSystemFactory();
            IDuplexOutputChannel anOutputChannel = 
        aMessagingFactory.CreateDuplexOutputChannel("https://127.0.0.1:7788");

            // Create the message sender that sends 
            // MyRequestMessage and receive responses MyResponseMessage.
            IDuplexTypedMessagesFactory aTypedMessages = 
        new DuplexTypedMessagesFactory(new XmlStringSerializer());
            IDuplexTypedMessageSender<MyResponseMessage, MyRequestMessage> 
        aMessageSender = aTypedMessages.CreateDuplexTypedMessageSender
                <MyResponseMessage, MyRequestMessage>();
            
            // Subscribe to handle responses.
            aMessageSender.ResponseReceived += ResponseReceived;
            
            // Attach the HTTPS channel to send request messages 
            // and receive response messages.
            aMessageSender.AttachDuplexOutputChannel(anOutputChannel);

            // Very simple loop getting numbers from the user and 
            // sending requests to the server.
            while (true)
            {
                MyRequestMessage aRequest = new MyRequestMessage();

                Console.Write("Number 1: ");
                aRequest.Number1 = int.Parse(Console.ReadLine());

                Console.Write("Number 2: ");
                aRequest.Number2 = int.Parse(Console.ReadLine());

                // Send the request to count inserted numbers.
                aMessageSender.SendRequestMessage(aRequest);
            }
        }

        // Handles received response messages.
        static void ResponseReceived(object sender, 
        TypedResponseReceivedEventArgs<MyResponseMessage> e)
        {
            if (e.ReceivingError == null)
            {
                Console.WriteLine("Result: " + e.ResponseMessage.Result.ToString());
            }
        }
    }
}

I hope you found the article useful. If you would like to have more information about Eneter.Messaging.Framework, you can find it at www.eneter.net.

License

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