2 Way Encrypted Communication Register - Sunday, September 05, 2010
Ad Minimize

Encrypt your C# and VB.Net DLL files to protect your code from decompilers, competitors, hackers, and viruses.

Assembly Lockbox... The anti-Decompiler.

ALBBoxMediumTransparent.gif

2 Way Encrypted Communication with a web service from a Windows smart client Minimize

 Sample application showing the use of asymmetric encryption with symmetric encryption.

Introduction

With all of the many thousands of issues to be considered with even a modest application it can feel like stepping into quicksand when you set yourself onto the task of encrypting your application's remote communications. You know it needs to be done because by definition "remote" communications are less secure than an application that never reaches beyond a single PC. Never the less it is burdensome.
 
This article is going to cover how a Windows programmer can make a smart client application that calls a web service on a remote application server and receive information back in a secure manner. This method also takes into account various issues that are not directly about communication, yet are related to the problem from a security point of view. i.e. How to get encrypted communications without hard coding the decrypt key in your client code where it is vulnerable to being obtained by the wrong person and without requiring (or letting) a user to memorize the password that is used to decrypt the communications.
 

Background

The world of encryption and cryptography is huge and complex. For software developers that are not mathematics scientists it is probably better to not bother trying to figure out how the encryption algorithms work. There is plenty of work to be done just using the tools given to us by the mathematicians. With the advancement of software tools over the years this domain has been made ever simpler to perform with less and less code (for all the general purposes uses anyway) . However the "architecture" of how these tools are meant to be used and assembled remains blurry.
 
My attempt here is to just spell out in laymen terms what is necessary and how to plug it all together and why you would build it this way. In other words, what is the bare minimum you got to do to take full advantage of these technologies and what you will get out of it.
 

"Seeing" what is going on

 
 
 
Without any encryption "sensitive" information is wide open for anyone to snoop if they are listening in on the communications between your client and server.
 
 
 
 
 
 With Symmetric (shared password) encryption your "sensitive" information now cannot be understood by snoopers. Symmetric is good because it protects your secrets and it happens to be "fast" as in it does not make the processor in your PC work too hard. The down side is that your password is located all over the place. All it takes is one stolen laptop and a good hacker to get their hands on the password... and now if they snoop on your communications they can decrypt them just like you can.
 
 
 
 
 
Asymmetric aka Public Key encryption uses mathematic magic to auto generate two passwords for you. These passwords are completely different yet they are mathematically related. There is no known way to take the public password and "figure out" with it what the private password is. So you can give out the public password all you want and if a hacker gets their hands on it they will not be able to snoop on your communications because only the private password can decrypt the message. That is the secret... the public password only encrypts and the private password only decrypts.

 

 

 * In reality there is more to it than this (isn't there always?). In fact the private key can encrypt messages that only the public key can decrypt, but then again whats the point in doing that when the public password is no safer than a shared password? Well there is a point. It is not so much about hiding the secrets as it is about knowing that a message came from who you think it did. When a message is encrypted with the private password it will only decrypt into its valid form when using the public password if the private password that goes with the public password is what did the encrypting. This is called signing a message. Basically you are saying that this message will only decrypt with that public password if it was sent by the ONE person that has the private password. If you were using symmetric (shared password) encryption then if someone had stolen the password from one of its many users then they could encrypt a message and send it to you and you wouldn't know that it had come from the hacker instead of your "trusted" friend...  an interesting extra value, but not one we will be using in this article.

  

Even if you now see what the differences are between symmetric and asymmetric encryption you may be wondering how do you send secure information from the server to the client using asymmetric encryption? After all you have to choose to either use asymmetric or symmetric encryption right? Wrong. To get secure two way communications you combine the two and this is how...

  • On the client generate a GUID
  • Encrypt the GUID with the asymmetric public password
  • Call a web method asking for sensitive data and as part of the call send the encrypted GUID
  • Use the asymmetric private password to decrypt the GUID
  • Encrypt the sensitive data to be sent back with the GUID as the key using symmetric encryption
  • Send the encrypted sensitive data back to the client
  • On the client decrypt the sensitive data with the GUID as the key using symmetric encryption

     

  • Generate a GUID

  • Encrypt the GUID with the asymmetric public password

  • Call a web method asking for sensitive data and as part of the call send the encrypted GUID

  • Use the private password to decrypt the GUID

  • Encrypt the sensitive data response with the GUID using symmetric encryption

  • Send the encrypted sensitive data back to the client

  • On the client decrypt the sensitive data with the GUID as the key using symmetric encryption

 

So what do you get out of all this? You get two way secured communications with encryption AND without slowing the whole process down by using asymmetric encryption for all data transfers. Professional programmers have to deal with a convergence of problems at any one point in their software. There are always trade offs between these various problems. Here we chose to lose a little speed of execution by using asymmetric encryption to protect the GUID because the GUID is acting as a temporary symmetric password. In return we got a more secure system because we no longer have "universal keys" floating around on the clients waiting to be stolen. If the server stores the GUID in some kind of cache or session then it can reuse that GUID over and over without using any more asymmetric encryption... but then you have to define what a "session" is and how long it lasts. If you are using IIS ASP.NET then you can use its session system. If you are using a stateless web service model or are not using IIS then you will either have to use asymmetric encryption for each call or you must setup your own session system. There are several other extras you can add in, but the system shown here gives you a good middle ground that will work in many situations. This way there is only one password that really needs to stay secure and that is on the server, yet you also get two way communications. In addition no human being is involved i.e. no one has to remember a password nor does any human have access to a password that can be "given" to someone else less trustworthy.

Down into the code

Now lets take a look at a sample application that shows the use of asymmetric encryption. Later we will build a sample application that calls a web service that takes advantage of asymmetric and symmetric encryption together. For now, however, we will just build a simple application for testing. The code and project files for this sample can be downloaded from a link at the top of this article. Below there is also a link to a video showing this application being built.

 Watch this video to see a sample application being built that uses asymmetric encryption.

 

If you watch the video you will see that there are basically two operations that are going on. First we have a button that when clicked generates a public and private keys (passwords) that are then set into textboxes so you can see them. There are various options as always, however here I used the method that returns the keys in XML format. The second button when clicked takes a "secret message" that you type into one textbox and encrypts it with the public key. Next it takes the encrypted string and outputs it into a textbox so you can see what it looks like. Finally it decrypts the string with the private key and puts the decrypted string in another textbox so you can see that the string is readable after the decrypt.

Now lets break down the code and talk about each section:

 

        private void btnGenerate_Click(object sender, EventArgs e)
        {
            //Setup crypto
            CspParameters cspParams = new CspParameters();
            cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
            RSACryptoServiceProvider crypto = new RSACryptoServiceProvider(cspParams);

            //Get public key
            txtPublicKey.Text = crypto.ToXmlString(false);
            //Get private key
            txtPrivateKey.Text = crypto.ToXmlString(true);
        }

 What we see here is a button click event. In the first section of code we are setting up the cryptography objects that will be doing the real work for us. The first object is a CspParameters class. CSP stands for (cryptographic service provider ). The CspParameters class allows you to tell the cryptographic provider object how to perform various tasks. In this case we are using the CspParameters object to tell the system to store the private key in a secret location in an encrypted form in the default "key store" for that machine (PC). You would use this option if you do not manually keep the private key safe in whatever manner you happen to choose. If you only intend on using the key once there is no point in adding this step. Here is what Microsofts documentation says about the CspParameters class:

The CspParameters class represents parameters that you can pass to managed cryptography classes that internally use Microsoft Cryptographic Service Providers (CSPs) from the unmanaged Microsoft Cryptography API (CAPI). Classes with names ending in "CryptoServiceProvider" are managed code wrappers for the corresponding CSP.

and here is what Microsoft documentation says about key stores:

Asymmetric private keys should never be stored verbatim or in plain text on the local computer. If you need to store a private key, you should use a key container. For more information on key containers, see the CryptoAPI section in the Platform SDK documentation at http://msdn.microsoft.com.

The last part of the setup section is creating the cryptographic provider object itself. Here we call the variable holding this object "crypto".

The last two lines of code simply generate private and public keys and then puts them into the textboxes so you can see them.

And now for the actual encryption process itself:

 

        private void btnEncryptDecrypt_Click(object sender, EventArgs e)
        {
            //Setup
            RSACryptoServiceProvider crypto = new RSACryptoServiceProvider();
            //Use the Public Key to do the encryption
            crypto.FromXmlString(txtPublicKey.Text);

            //Encrypt
            byte[] stringEncryptedAsByteArray = crypto.Encrypt(System.Text.Encoding.UTF8.GetBytes(txtSecretTextBefore.Text), false);

            //Show result
            txtEncryptedText.Text = Convert.ToBase64String(stringEncryptedAsByteArray);



            //Decrypt
            crypto = new RSACryptoServiceProvider();
            crypto.FromXmlString(txtPrivateKey.Text);
            byte[] stringDecryptedAsByteArray = crypto.Decrypt(Convert.FromBase64String(txtEncryptedText.Text), false);

            //Show result
            txtSecretTextAfter.Text = System.Text.Encoding.UTF8.GetString(stringDecryptedAsByteArray);
        }

Here we start off setting up the cryptographic provider again. We skip the CspParameters because we really dont need it in this sample. Next we take the public key and pass it to the crypto object using the FromXMLString method that tells the object to expect the key to be in XML format. Because the crypto object's Encrypt method requries a byte array to be passed in we use this code System.Text.Encoding.UTF8.GetBytes to convert the string to a byte array using UTF8 character "sizes" or formatting. Next we take the encrypted byte array that the Encrypt method returns and we turn it back into a string using Base64 conversion. I use the Base64 formatting because it tends to travel around to all the different locations I might try sending it like a xml web service without causing any incompatibility problems. Once the encrypted byte array is in text format we put it into the textbox txtEncryptedText so you can see what your "secret text" looks like after being encrypted.

Now that the encryption is done we will next decrypt the string and show what is inside. We first recreate the crypto object to be sure to clear out any settings that was made to it originally. Then we give the crypto object the private key in XML format. Next we convert FROM a Base64 string back into a UTF8 byte array and pass this byte array to the Decrypt method on the crypto object. This returns to us another byte array which contains the decrypted message. The last step is to convert the byte array back into the original formated string and put that string into the textbox txtSecretTextAfter so you can see that indeed the "secret text" survived through all of this encryption and formatting.

 

 Smart Client + Web Service == two way encrypted communications

 

 Watch this video to see a smart client application being built along with a web service that it calls.

 

 

Copyright (c) 2010 GeraldGibson.Net - DotNetNuke