Encryption and Decryption in C#

I have been looking at encrypting and decrypting data as part of a project that I’m doing at work. As is quite common there’s a ton of stuff on the internet but the devil as always is in the details. What appears to work for one person won’t necessary work for another.

I don’t want to talk too much about how encryption and decryption works, partly because I’m not an expert so there are a few things I’m bound to get wrong. Also it is a separate topic in itself. There are however two fundamental things that you need to be aware of: these are the Public Key and the Private Key. The Public Key as its name suggests can be shared with the public, the private key should be kept private. The other thing to be aware of from a coding point of view is that there are a number of different ways to do this. I tried quite a few of them but not all. The reason for this is trying to keep the details used to encrypt safe.

The private key can be used to decrypt messages and the public key can be used to encrypt messages. I think that when passing encrypted data between two parties, Alice and Bob, then both will need to have the same private key to decrypt. When reading articles about cryptography it’s very common to read about Alice and Bob.

The purpose of this article is make some notes about the code that works for me, and explain some of the areas which tripped me up and caused me some problems.

The code at the bottom of this article is the working version I got to this morning. There are a things to note. First, I’m using two X509Certificates, an CER file and a PFX file. You could just use the PFX file, since this contains both the private and public key, the CER file doesn’t contain the private key. If you had a scenario where Bob needed to send encrypted messages to Alice then he would just need the CER. Alice could keep her private key and decrypt messages she receives from Bob.If Bob wanted to read encrypted messages from Alice then he would also need the private key.

The most common exception I got was ‘the key does not exist’. There can be a number of reasons why this happens but all the solutions I saw online didn’t help me. It wasn’t until I added a third parameter in the X509Certificate import: the X509KeyStorageFlags.Exportable parameter when things started working. And I only found out I really needed this through trial and error and getting this exception ‘key not valid for use in specified state’. And I only started getting that error when I tried using the ImportParameters method of the RSACryptoServiceProvider. There were also a number of problems with the

These links on StackOverflow helped me and contain information that I found useful

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.IO;

namespace EncryptionAndDecryption {
  class Program {
    static void Main(string[] args) {

      string textToEncrypt = “The quick red fox jumps over the lazy brown dog”;

      string encryptedText = Crypto.Encrypt(textToEncrypt);
      string decryptedText = Crypto.Decrypt(encryptedText);

      Console.ReadLine();
    }
  }

  static public class Crypto {

    public static X509Certificate2 GetPublicKey() {
      return new X509Certificate2(@”c:\TestCertificates\testCertificate.cer”,
                                                           “”,
                                                         X509KeyStorageFlags.Exportable);
    }

    public static X509Certificate2 GetPrivateKey() {
      return new X509Certificate2(@”c:\TestCertificates\testPFX.pfx”,
                                                          “password”,
                                                         X509KeyStorageFlags.Exportable);
    }

    public static string Encrypt(string textToEncrypt) {
      ASCIIEncoding byteConverter = new ASCIIEncoding();
      byte[] encodedBytes = byteConverter.GetBytes(textToEncrypt);
      X509Certificate2 cert = GetPublicKey();

      byte[] encryptedBytes;

      RSACryptoServiceProvider rsa = cert.PublicKey.Key as RSACryptoServiceProvider;
      encryptedBytes = rsa.Encrypt(encodedBytes, false);

      return Convert.ToBase64String(encryptedBytes);
    }

    public static string Decrypt(string encryptedText) {
       byte[] encryptedBytes = Convert.FromBase64String(encryptedText);
       X509Certificate2 cert = GetPrivateKey();
       RSACryptoServiceProvider rsa = cert.PrivateKey as RSACryptoServiceProvider;

       byte[] decryptedBytes;
       decryptedBytes = rsa.Decrypt(encryptedBytes, false);

       ASCIIEncoding byteConverter = new ASCIIEncoding();
       return byteConverter.GetString(decryptedBytes);
    }

   } //End of class Crypto
}

Advertisements

Use the new keyword if hiding was intended

A couple of months ago at work we put some new web services into production. All seemed to go well and everything seemed nice and fast but we noticed that some of these services were using a lot of CPU and memory. We had used JMeter to load test these services quite extensively so I was fairly convinced that there wasn’t really a memory leak but, of course, one can never be too certain.

Now, in these web services we know that one of the methods was used pretty extensively so to begin with I focussed my efforts on it to see if there was anything that might explain this curious behaviour.

It turns out that there was a memory leak and it wasn’t in the depths of the code but right at the top. I’ve got an ASMX and its code behind starts like this:

public class CustomWeb: System.Web.Services.WebService {
    private CustomService customService;
    private SitesListService sitesListService;
    public CustomWeb() {
         customService= new CustomService();
        sitesListService = new SitesListService();
    }
    public void Dispose() {
        customService= null;
        sitesListService = null;
        base.Dispose();
    }

I’ve removed most of the code but you can see a fairly plain constructor and a dispose method. Pretty basic stuff. This compiles perfectly well but there was a warning displayed regarding the Dispose method. This says.

CustomWeb.Dispose() hides inherited member ‘System.ComponentModel.MarshallByValueComponent.Dispose() Use the new keyword if hiding was intended.

Initially I read this quite literally. I didn’t want my Dispose method to be hidden in fact I wanted it to be called to mark the objects created in the constructor to be null to free up memory. As this web method inherits from the WebService I thought that perhaps its Dispose method needed to be over ridden but doing that caused an error to be shown.

I’ve never used the new keyword in a method signature before and doing so to hide a method didn’t really make sense. However, that apparently is what I should be doing. This was the cause of my memory leak. My Dispose method should be written like this:

public new void Dispose() {
    customService = null;
    sitesListService = null;
    base.Dispose();
}

It would seem that the previous way without using the new keyword prevented the base.Dispose method from being called so therefore every request to the web service was resulting in CPU usage and memory usage being much higher than expected. At a guess there might have been less damage caused by not having a custom Dispose method at all, that way the base method would be called and the resources freed. The new objects created in the constructor would have eventually been picked up by the garbage collector.

However, I’m glad we made this mistake since it illustrates a couple of things. Firstly, don’t ignore the warnings. Yes, your code might have built but it’s worth checking the warnings. The clues in the name after all. Secondly, now I know a little bit more about web services. It’s odd to think that these three letters ‘new’ have resulted in memory for my web services running at a consistent level, whereas previously they used to climb to about 1GB in size before then dropping, and the CPU usage now being 3 – 9% (depending on load) as opposed to 35% – 60%. That’s quite something.