A C# Encryption provider for Azure Websites

Azure.Security, my second OSS project has been released!

1. What is Azure.Security?

Azure.Security is an Azure specific piece of software designed to provide cryptographic services to an application deployed to Azure Websites platform. One of the issues that you may come across when using this platform is data encryption and key management. Luckily, Azure Websites are happy to run code from the System.Security namespace, but there is no easy way to securily manage private key(s). And that's where this project comes to fill in the gap. Azure.Security uses a number of Azure features in order to provide cryptographic services while ensuring that the keys remain secure at all times. Azure.Security creates an easy-to-use off-the-self solution that wrapps nicely the complexity of manually setting up a cryptography provider in your project by leveraging SSL certificates, tables and blob storage. All you need to do to start using it is to either download the NuGet package or grab the source code on GitHub and use the guide below to set it up.

2. Getting Started

There are a couple of things you need before getting down to encrypting/decrypting data. First you have to get your self an SSL certificate. However, I assume that if you are serious about security, you already use SSL in your web app anyway. If you don't already have an SSL in place, you can:

  • get a free one (GoDaddy offers a free SSL with every domain registration)
  • buy one from a third-party supplier
  • create your own, self signed certificate

Whichever the case, you need to ensure that the SSL certificate comes with a private key!

Any of the above options is acceptable since the certificate will only be used to encrypt/decrypt your private key anyway (double encryption, I like it!). You also need a Storage Account in Azure. Again, if you are running an Azure Website, then it's highly likely that you already have one. If not, use the Azure Portal to create one because you will need it further down for the configuration.

Go on, I'll wait...

Back? Good. So, now that we have met all the prerequisites, lets go and install Azure.Security. Within your solution run the following:

Or you can use the Nuget Package Manager to achieve the same result :)

This will add the Azure.Security.dll, the Azure.Storage NuGet package and a couple of properties in your web.config. The first two are self-explanatory. The web.config properties are important as they define important parameters for the EncryptionHelper class. The properties in question are:

  • StorageConnectionString: the url to your storage account e.g. DefaultEndpointsProtocol=https;AccountName=asecdemo;AccountKey=serhqxm77ogB4TGs6zJE7yDHenn9jiWJFI98mHnLfr4Tl63VWwFFBK4U3I6PB6be8QWvR+EGbgdEAbH1Ygo51mw==
  • CertificateValue: the private key password for your SSL Certificate e.g. "thisisaverylongandsecuritystringusedasmysslprivatekey123456789"
  • CertificateTable: the table that will store your encrypted AES keys e.g. "encryptionkeytable"
  • CertificateName: the name of your certificate file e.g "mycertificate.pfx"

Note: You can find the connection string to your storage account on the Azure Portal by going to StorageAccount --> Settings --> Keys. There, you can access your primary and secondary keys and the url to your storage account.

You have two choices when it comes to setting the values for the web.config parameters and they both come with their own pros and cons:

  1. Add the parameter values directly in the web.config: Pros: easy to manage and find. Cons: in case of unauthorized access, there is nothing stopping the perpatrators from accessing the sensitive information.
  2. Add the parameter values in the Azure portal. As long as the parameter names match, Azure will happily replace values in the web.config with the ones defined in the portal. Pros: you can leave the web.config values empty and rely on Azure to do the hard work for you. This adds another layer of security since the sensitive information is not held anywhere in the local files. Cons: you need to set the parameters in the Azure portal.

Instructions on how to set this up below:

  1. Log on to the Azure Portal
  2. Go to Websites and select your website
  3. Go to the Configuration tab
  4. Scroll down to the App Settings section
  5. Set the values as per the image below:

NOTE: You don't have to use option 2, but I highly recommend it as it definitely improves the security of your system.

Place your .pfx certificate within your web project either in the App_Data folder or any other location you feel comfortable with. The EncryptionHelper needs the path to the certificate so make sure that you can easily retrieve it in code, hence the reason I suggested the App_Data folder.

At the end of all this, your solution should look like this:

And your web.config like this:

3. Using Azure.Security to secure data###

With the hard part behind us, we can now encrypt/decrypt sensitive information. The EncryptionHelper is the wrapper that we will use for all operations and it implements a simple interface:

Void CreateNewCryptoKeyIfNotExists()
Byte[] EncryptBytes(byte[] bytesToEncrypt)
Byte[] DecryptBytes(byte[] bytesToDecrypt)
String EncryptAndBase64(string valueToEncrypt)
String DecryptFromBase64(string valueToDecrypt)

In your Application_Start(), instantiate the EncryptionHelper and call the CreateNewCryptoKeyIfNotExists() as per the example below:

protected void Application_Start()
{
 	//other code omitted
 
 	var certificatePath = Server.MapPath("~/App_Data");
 	var encryptionHelper = new EncryptionHelper(certificatePath);
 	encryptionHelper.CreateNewCryptoKeyIfNotExists();
}

This will only run once and will create the private key that will be used for encrypting & decrypting the data. Then in your code you can instantiate the EncryptionHelper and call either the encrypt/decrypt methods as you need them. A short example is provided below:

// Create the encryption installer
var certificatePath = Server.MapPath("~/App_Data");
var encryptionHelper = new EncryptionHelper(certificatePath);
// Encrypt
var encryptedString = encryptionHelper.EncryptAndBase64("test string");
// Decrypt
var decryptedString = encryptionHelper.DecryptFromBase64(encryptedString);

Important notice: DO NOT use the EncryptionHelper to secure user passwords! Passwords should be one-way hashed and not encrypted. If you need an implementation example of password hashing you can have a look at BCrypt or PBKDF2.

4. Overall Benefits

This security solution will scale with your website as it grows horizontally and vertically. Also, since this is an OSS project, you can fork it to better meet your needs.

Happy coding...

Find me on twitter: @christosmatskas