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):
- The client connects the server and asks for the digital certificate.
- 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, ...)
- The client creates a session key, encrypts it with the public key from the received certificate and sends it to the server.
- The server decrypts the session key from the client and uses it to encrypt the content for the client.
- 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
- Execute Visual Studio command prompt with Administrator privileges.
- 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
- Execute from the command prompt: mmc
- Choose 'Add/Remove Snap-in...'
- Doubleclick 'Certificates'
- Choose 'Computer account'
- The new certificate should be found under 'Personal Certificates'.
- 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."
- To resolve this issue, copy and paste the new certificate into 'Trusted Root Certification Authorities'.
- 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.
- 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.
- 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.
using System;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.HttpMessagingSystem;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
namespace HttpService
{
public class MyRequestMessage
{
public int Number1 { get; set; }
public int Number2 { get; set; }
};
public class MyResponseMessage
{
public int Result { get; set; }
};
class Program
{
static void Main(string[] args)
{
IMessagingSystemFactory aMessagingFactory = new HttpMessagingSystemFactory();
IDuplexInputChannel anInputChannel =
aMessagingFactory.CreateDuplexInputChannel("https://127.0.0.1:7788");
IDuplexTypedMessagesFactory aTypedMessages =
new DuplexTypedMessagesFactory(new XmlStringSerializer());
IDuplexTypedMessageReceiver<MyResponseMessage, MyRequestMessage>
aMessageReceiver = aTypedMessages.CreateDuplexTypedMessageReceiver
<MyResponseMessage, MyRequestMessage>();
aMessageReceiver.MessageReceived += MessageReceived;
Console.WriteLine("The server is listening.");
aMessageReceiver.AttachDuplexInputChannel(anInputChannel);
}
static void MessageReceived(object sender,
TypedRequestReceivedEventArgs<MyRequestMessage> e)
{
if (e.ReceivingError == null)
{
MyResponseMessage aResponse = new MyResponseMessage();
aResponse.Result = e.RequestMessage.Number1 + e.RequestMessage.Number2;
Console.WriteLine("Result = " + aResponse.Result.ToString());
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:
using System;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.HttpMessagingSystem;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
namespace HttpClient
{
public class MyRequestMessage
{
public int Number1 { get; set; }
public int Number2 { get; set; }
};
public class MyResponseMessage
{
public int Result { get; set; }
};
class Program
{
static void Main(string[] args)
{
IMessagingSystemFactory aMessagingFactory = new HttpMessagingSystemFactory();
IDuplexOutputChannel anOutputChannel =
aMessagingFactory.CreateDuplexOutputChannel("https://127.0.0.1:7788");
IDuplexTypedMessagesFactory aTypedMessages =
new DuplexTypedMessagesFactory(new XmlStringSerializer());
IDuplexTypedMessageSender<MyResponseMessage, MyRequestMessage>
aMessageSender = aTypedMessages.CreateDuplexTypedMessageSender
<MyResponseMessage, MyRequestMessage>();
aMessageSender.ResponseReceived += ResponseReceived;
aMessageSender.AttachDuplexOutputChannel(anOutputChannel);
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());
aMessageSender.SendRequestMessage(aRequest);
}
}
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.
CodeProject