An encrypted messaging project in .NET with C# part 3: client proxy with web API

Introduction

In the previous post we finished building the backend part for the first step in the conversation between the sender and the receiver. The sender needs to get a valid one-time public key and a message ID from the receiver. The receiver will communicate with the receiver through a web API based web service.

The Web layer

In this section I’ll refer a lot to this post in the series on the DDD skeleton project. Make sure to get familiar with it as it contains a lot of information that’s relevant to this post. In that post I show you how to add a web API project and transform it so that it only contains the web service relevant parts. We don’t want to deal with views, JS files, images etc. in a web service project. I also go through the basics of how to install and use the IoC called StructureMap in an MVC-based project. It will be responsible for resolving dependencies such as the ones in this constructor:

public AsymmetricCryptographyApplicationService(IAsymmetricCryptographyService cryptographyInfrastructureService
			, IAsymmetricKeyRepositoryFactory asymmetricKeyRepositoryFactory)

Add a new MVC4 web application called Receiver.Web to the solution. Make sure to select the Web API template in the MVC4 Project Template window. Add a reference to all other layers – this is necessary for StructureMap as we’ll see in a bit.

Next get rid of the standard MVC4 web application components. Again, consult the above link to see how it can be done. Install StructureMap from NuGet. Locate the generated IoC.cs file in the DependencyResolution folder. Make sure it looks as follows:

public static IContainer Initialize()
{
	ObjectFactory.Initialize(x =>
		{
			x.Scan(scan =>
			{
				scan.TheCallingAssembly();
				scan.AssemblyContainingType<IAsymmetricCryptographyApplicationService>();
				scan.AssemblyContainingType<IAsymmetricCryptographyService>();
				scan.AssemblyContainingType<IAsymmetricKeyRepository>();
				scan.WithDefaultConventions();
			});
			x.For<IAsymmetricCryptographyService>().Use<RsaCryptographyService>();
			x.For<IAsymmetricKeyRepositoryFactory>().Use<LazySingletonAsymmetricKeyRepositoryFactory>();
                        x.For<ISymmetricEncryptionService>().Use<RijndaelSymmetricCryptographyService>();
		});
	ObjectFactory.AssertConfigurationIsValid();
        return ObjectFactory.Container;
}

Again, consult the above link if you don’t know what this code means. We tell StructureMap to look for concrete implementations of abstractions in the other layers of the application. We also tell it to pick the RSA implementation of the IAsymmetricCryptographyService interface and the InMemoryAsymmetricKeyRepositoryFactory implementation of the IAsymmetricKeyRepositoryFactory interface.

Add the following section to the Register method of WebApiConfig.cs in the App_Start folder to make sure that we respond with JSON. Web API seems to have an issue with serialising XML:

var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;			
config.Formatters.Remove(config.Formatters.XmlFormatter);

In the same method you’ll see that the API calls are routed to api/controller/id by default. Remove the ‘api’ bit as follows:

config.Routes.MapHttpRoute(
	name: "DefaultApi",
	routeTemplate: "{controller}/{id}",
	defaults: new { id = RouteParameter.Optional }
	);	

Add a folder called Helpers to the web layer. Add the following two classes with extension methods:

public static class ExceptionDictionary
{
	public static HttpStatusCode ConvertToHttpStatusCode(this Exception exception)
	{
		Dictionary<Type, HttpStatusCode> dict = GetExceptionDictionary();
		if (dict.ContainsKey(exception.GetType()))
		{
			return dict[exception.GetType()];
		}
		return dict[typeof(Exception)];
	}

	private static Dictionary<Type, HttpStatusCode> GetExceptionDictionary()
	{
		Dictionary<Type, HttpStatusCode> dict = new Dictionary<Type, HttpStatusCode>();
		dict[typeof(ResourceNotFoundException)] = HttpStatusCode.NotFound;
		dict[typeof(Exception)] = HttpStatusCode.InternalServerError;
		return dict;
	}
}	
public static class HttpResponseBuilder
{	
	public static HttpResponseMessage BuildResponse(this HttpRequestMessage requestMessage, ServiceResponseBase baseResponse)
	{
		HttpStatusCode statusCode = HttpStatusCode.OK;
		if (baseResponse.Exception != null)
		{
			statusCode = baseResponse.Exception.ConvertToHttpStatusCode();
			HttpResponseMessage message = new HttpResponseMessage(statusCode);
			message.Content = new StringContent(baseResponse.Exception.Message);
			throw new HttpResponseException(message);
		}
		return requestMessage.CreateResponse<ServiceResponseBase>(statusCode, baseResponse);
	}
}

Set the namespace of both classes to Receiver.Web so that they are available from everywhere in the Web project without having to set using statements.

Add a new Web API controller in the Controllers folder. Name it PublicKeyController and make sure to select the Empty Api controller template in the Add Controller window. You’ll see that the controller derives from ApiController. The public key controller will depend on the IAsymmetricCryptographyApplicationService interface, so insert the following private field and constructor:

private readonly IAsymmetricCryptographyApplicationService _asymmetricCryptoApplicationService;

public PublicKeyController(IAsymmetricCryptographyApplicationService asymmetricCryptoApplicationService)
{
	if (asymmetricCryptoApplicationService == null) throw new ArgumentNullException("IAsymmetricCryptographyApplicationService");
	_asymmetricCryptoApplicationService = asymmetricCryptoApplicationService;
}

The client will call this controller to get a new public key and a message ID. Therefore we need a GET method that returns just these elements. The implementation is very simple:

public HttpResponseMessage Get()
{
	ServiceResponseBase response = _asymmetricCryptoApplicationService.GetAsymmetricPublicKey();
	return Request.BuildResponse(response);
}

We ask the application service to create the necessary elements and build a JSON response out of them. Set a breakpoint within AsymmetricCryptographyApplicationService.GetAsymmetricPublicKey(). Set the start page to PublicKey in properties of the web layer:

Set PublicKey as start page in web properties

Press F5 to start the application. Execution should stop at the breakpoint you set previously. Follow the code execution with F11 and see how the parts are connected. The new asymmetric key pair is generated and saved in the dictionary of the repository. At the end of the process the message ID and the public key should appear in the web browser:

RSA key printed in web browser

Take note of the URL, it will be the web service URL the sender will communicate with in the next step.

Now let’s see how this value can be read by a sender.

The sender

The sender will be a Console application that sends and receives HTTP messages to and from the web service. I won’t care too much about software practices here in order to save time.

Create a new Console application in Visual Studio and call it Sender. Add the following library references:

  • System.Net
  • System.Net.Http

Add a reference to Json.NET – previously known as NewtonSoft – through NuGet. We have contacted the Receiver before and we know that they now employ a standard RSA asymmetric algorithm for their encryption purposes. Synchronisation is vital in encryption scenarios otherwise the two parties will not be able to read each other’s messages.

Add the following service URI to Program.cs:

private static Uri _publicKeyServiceUri = new Uri("http://localhost:7695/PublicKey");

The port will almost certainly differ in your case so please modify it.

We’ll process the Json coming from the Receiver in the following object:

public class PublicKeyResponse
{
	public Guid MessageId { get; set; }
	public RSACryptoServiceProvider RsaPublicKey { get; set; }
}

From this post you’ll know that RSACryptoServiceProvider is the .NET implementation of the RSA asymmetric encryption.

Enter the following method to Program.cs:

private static PublicKeyResponse GetPublicKeyMessageId()
{
	PublicKeyResponse resp = new PublicKeyResponse();
	try
	{
		HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, _publicKeyServiceUri);
		requestMessage.Headers.ExpectContinue = false;
		HttpClient httpClient = new HttpClient();
		httpClient.Timeout = new TimeSpan(0, 10, 0);
		Task<HttpResponseMessage> httpRequest = httpClient.SendAsync(requestMessage,
				HttpCompletionOption.ResponseContentRead, CancellationToken.None);
		HttpResponseMessage httpResponse = httpRequest.Result;
		HttpStatusCode statusCode = httpResponse.StatusCode;
		HttpContent responseContent = httpResponse.Content;
		if (responseContent != null)
		{
			Task<String> stringContentsTask = responseContent.ReadAsStringAsync();
			String stringContents = stringContentsTask.Result.Replace("$", string.Empty);
			XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(stringContents, "root");
			XmlElement root = doc.DocumentElement;
			XmlNode messageIdNode = root.SelectSingleNode("MessageId");
			resp.MessageId = Guid.Parse(doc.DocumentElement.SelectSingleNode("MessageId").InnerText);
					RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider();
			rsaProvider.FromXmlString(doc.DocumentElement.SelectSingleNode("PublicKeyXml").InnerXml);
			resp.RsaPublicKey = rsaProvider;
		}
	}
	catch (Exception ex)
	{
		Console.WriteLine(ex.Message);
	}
	return resp;
}

Let’s see what’s going on here. We want to return a PublicKeyResponse object. We initiate a Http GET request using the HttpClient and HttpRequestMessage objects which are built-in components of the System.Net library. We send the request by calling the SendAsync method. We read the Http status code and the response content. We then extract the string message coming from the service, which is the JSON you saw in the web browser.

We want to transform the JSON into XML to take advantage of the FromXmlString method of the RSACryptoServiceProvider object. However, the JSON response includes an element ‘$id’ which invalidates the XML, the ‘$’ character is illegal. Hence we need to get rid of it. The JSON now looks as follows:

"id": "1",
"MessageId": "157a0890-be7d-4a25-bcf8-78829c99f13a",
"PublicKeyXml": {
"RSAKeyValue": {
"Modulus": "uB6pzihs7A70Su2J33SegPMkMXdWayRoqE57X94eyOPAeiPW+lMhy+pFxHNZ6+1+l35vRzcGZ8xL6AFKFiiriq1Dgu5WSqluBylkkWGTZfA+k7cpAh4CEEy0jg4BvPlxg/f7ufzLhy9iAGKARISKLBbCLIEeBpjqgyXEcW0tzrk=",
"Exponent": "AQAB"
}
},
"Exception": null

The exact values will certainly differ from what you see but the format should be the same.

There’s a very handy method in the Json.NET library which allows to transform a JSON string into an XmlDocument in the System.Xml namespace. This is done by the DeserializeXmlNode method. You’ll notice the “root” parameter. The things is that the current JSON format makes it difficult for the JSON converter to know what the root node is. As you know there’s no valid XML without a root node. Without this parameter you’ll get an exception:

JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName.

After the conversion our XML should look like this:

<root>
	<id>1</id>
	<MessageId>4d38ee45-8c8a-4531-9513-765c5569c942</MessageId>
	<PublicKeyXml>
		<RSAKeyValue>
			<Modulus>kdl1gUhLj6RNk6Ppm5LC6mol1CcIXKft9O34naJLbAOy2720a1HshFfhjkvW4A6ibqhLJCo2N2IGfIBGNDaOeQfyzxvltC6Mvw3Zykxe4Jkmbv7cbzxpnZ20GMW1wCzmfGoqB36movrDqAn1c2ftiznhu0IbDY8GJf3bkB0SwFc=</Modulus>
			<Exponent>AQAB</Exponent>
		</RSAKeyValue>
	</PublicKeyXml>
	<Exception />
</root>

Then it’s only a matter of reading out the relevant nodes from the XML and populate the PublicKeyResponse object.

You can call this method from Main as follows:

PublicKeyResponse publicKeyResponse = GetPublicKeyMessageId();
if (publicKeyResponse.MessageId != null &amp;&amp; publicKeyResponse.RsaPublicKey != null)
{
	Console.Write("Public key request successful. Enter your message: ");
	string message = Console.ReadLine();
}
else
{
	Console.WriteLine("Public key request failed.");
}
Console.ReadKey();

We check if the public key request was successful and then ask the user to enter a message.

Make sure that the web API project is running and then start the Sender app. You can set a breakpoint within the Get method of the PublicKeyController of the Receiver to see the request come in. The Receiver will respond and the Sender will process the Json message. If everything goes well then you should have a populated PublicKeyResponse with a message id and an RSA public key.

So what happens with the message entered by the user? We’ll find out in the next post.

You can view the list of posts on Security and Cryptography here.

An encrypted messaging project in .NET with C# part 2: service and repository

Introduction

In the previous post we started building the foundations of an encrypted messaging project. To be exact we built a couple of objects in the Infrastructure layer to support the creation of new RSA key pairs.

We’ll now look at how the asymmetric key-pair can be stored, located and removed in a repository.

Repository

Insert a new class library called Receiver.Repository to the Receiver solution and add a reference to the Infrastructure layer. Add a new folder called “Cryptography”. The exact way how a key-pair can be stored can vary a lot: in a database, in memory, in a file, on a separate machine, etc. You can read more about key storage here. Therefore it sounds like a good idea to hide the implementation behind an interface. Add the following interface to the folder:

public interface IAsymmetricKeyRepository
{
	void Add(Guid messageId, AsymmetricKeyPairGenerationResult asymmetricKeyPair);
	AsymmetricKeyPairGenerationResult FindBy(Guid messageId);
	void Remove(Guid messageId);
}

We saw the AsymmetricKeyPairGenerationResult object in the previous post. The message ID, as discussed before, will be used to check the validity of the key supplied by the sender. We also need to be able to locate a key-pair by the message ID and remove a message id after it’s been used.

We’ll go with a simple in-memory implementation to make things simple. The repository will be instantiated using the singleton design pattern. Again, as the implementation is hidden behind an interface you can easily change your key storage strategy later on.

Add the following class to the folder:

public class InMemoryAsymmetricKeyRepository : IAsymmetricKeyRepository
{
	private Dictionary<Guid, AsymmetricKeyPairGenerationResult> _asymmetricKeyPairs;

	public InMemoryAsymmetricKeyRepository()
	{
		_asymmetricKeyPairs = new Dictionary<Guid, AsymmetricKeyPairGenerationResult>();
	}

	public void Add(Guid messageId, AsymmetricKeyPairGenerationResult asymmetricKeyPair)
	{
		_asymmetricKeyPairs[messageId] = asymmetricKeyPair;
	}

	public AsymmetricKeyPairGenerationResult FindBy(Guid messageId)
	{
		if (_asymmetricKeyPairs.ContainsKey(messageId))
		{
			return _asymmetricKeyPairs[messageId];
		}
		throw new KeyNotFoundException("Invalid message ID.");
	}

	public void Remove(Guid messageId)
	{
		if (_asymmetricKeyPairs.ContainsKey(messageId))
		{
			_asymmetricKeyPairs.Remove(messageId);
		}
	}

        public static InMemoryAsymmetricKeyRepository Instance
	{
		get
		{
			return Nested.instance;
		}
	}

	private class Nested
	{
		static Nested()
		{
		}
		internal static readonly InMemoryAsymmetricKeyRepository instance = new InMemoryAsymmetricKeyRepository();
	}
}

If you don’t understand what the Nested class and the Instance property mean then make sure to check out the link provided above on the Singleton design pattern.

We store the message ID and its asymmetric key-pair in a Dictionary. I believe it’s easy to follow the implementation: we add, find and remove elements in the dictionary.

We’ll need a couple of extra classes in order to get an instance of the repository. Add the following classes into the Cryptography folder:

public interface IAsymmetricKeyRepositoryFactory
{
	InMemoryAsymmetricKeyRepository Create();
}
public class LazySingletonAsymmetricKeyRepositoryFactory : IAsymmetricKeyRepositoryFactory
{
	public InMemoryAsymmetricKeyRepository Create()
	{
		return InMemoryAsymmetricKeyRepository.Instance;
	}
}

Check out this post to gain a full understanding on the purpose of the abstract factory and its implementation. We want to make sure that only a single instance of the InMemoryAsymmetricKeyRepository object is returned. We don’t want different sets of the _asymmetricKeyPairs dictionary fly around every time we need an InMemoryAsymmetricKeyRepository.

We’re actually done with the repository layer so let’s move on.

Application services

If you’ve read through this series then you’ll know what’s the purpose of the application service layer. In short it’s the thin connecting tissue between the consumer layer – MVC, web service, console and the like – and the backend parts. It should be void of any logic. It co-ordinates the tasks among its dependencies in order to respond to the consumer layer in a meaningful way. Make sure you read at least this post so that you become familiar with things like Request-Response and the ServiceResponseBase object. Those techniques will be reused here.

Add a new C# library called Receiver.ApplicationService to the solution. Add a folder called Interfaces. The first service we implement will need to provide a valid and unused pair of keys and a message ID to the consumer. Insert the following interface into the folder:

public interface IAsymmetricCryptographyApplicationService
{
	GetAsymmetricPublicKeyResponse GetAsymmetricPublicKey();
}

…where GetAsymmetricPublicKeyResponse is a simple wrapper. Add a new folder called Responses and in it add this object:

public class GetAsymmetricPublicKeyResponse : ServiceResponseBase
{
	public Guid MessageId { get; set; }
	public XDocument PublicKeyXml { get; set; }
}

The ServiceResponseBase is located in the Responses folder as well:

public abstract class ServiceResponseBase
{
	public ServiceResponseBase()
	{
		this.Exception = null;
	}

	/// <summary>
	/// Save the exception thrown so that consumers can read it
	/// </summary>
	public Exception Exception { get; set; }
}

Add a new folder called Implementations to the service layer. In it add the following implementation of the above interface:

public class AsymmetricCryptographyApplicationService : IAsymmetricCryptographyApplicationService
{
	private readonly IAsymmetricCryptographyService _cryptographyInfrastructureService;
	private readonly IAsymmetricKeyRepositoryFactory _asymmetricKeyRepositoryFactory;

	public AsymmetricCryptographyApplicationService(IAsymmetricCryptographyService cryptographyInfrastructureService
		, IAsymmetricKeyRepositoryFactory asymmetricKeyRepositoryFactory)
	{
		if (cryptographyInfrastructureService == null) throw new ArgumentNullException("IAsymmetricCryptographyService");
		if (asymmetricKeyRepositoryFactory == null) throw new ArgumentNullException("IAsymmetricKeyRepositoryFactory");
		_cryptographyInfrastructureService = cryptographyInfrastructureService;
		_asymmetricKeyRepositoryFactory = asymmetricKeyRepositoryFactory;
	}

	public GetAsymmetricPublicKeyResponse GetAsymmetricPublicKey()
	{
		GetAsymmetricPublicKeyResponse publicKeyResponse = new GetAsymmetricPublicKeyResponse();
		try
		{
			AsymmetricKeyPairGenerationResult asymmetricKeyPair = _cryptographyInfrastructureService.GenerateAsymmetricKeys();
			Guid messageId = Guid.NewGuid();
			publicKeyResponse.MessageId = messageId;
			publicKeyResponse.PublicKeyXml = asymmetricKeyPair.PublicKeyOnlyXml;
			_asymmetricKeyRepositoryFactory.Create().Add(messageId, asymmetricKeyPair);
		}
		catch (Exception ex)
		{
			publicKeyResponse.Exception = ex;
		}
		return publicKeyResponse;
	}
}

The implementation will need an IAsymmetricCryptographyService and an IAsymmetricKeyRepositoryFactory object to fulfil its job. It doesn’t care which exact implementations are injected through its constructor. We set some guard clauses in the constructor so that the injected dependencies won’t be null.

Take a look at the GetAsymmetricPublicKey() implementation. It first asks the crypto service in the infrastructure layer to generate the asymmetric keys. It then constructs a new GUID which will serve as the message ID, sets the appropriate properties of the GetAsymmetricPublicKeyResponse object and finally asks the repository to save the key pair and the message ID through the Create() method of the repository factory. We save any exceptions that may have been thrown along the way and return the response.

If you followed through the DDD project mentioned above, the next object will look familiar. Add a new folder called Exceptions to the project and insert the following custom Exception:

public class ResourceNotFoundException : Exception
{
	public ResourceNotFoundException(string message)
		: base(message)
	{ }

	public ResourceNotFoundException()
		: base("The requested resource was not found.")
	{ }
}

This will be used in cases where the resource requested by the Sender is not found by the Receiver.

This completes our service layer for the time being. In the next post we’ll start building the web service layer.

You can view the list of posts on Security and Cryptography here.

An encrypted messaging project in .NET with C# part 1: foundations

Introduction

In the past several posts we’ve discussed a number of issues in .NET cryptography. We’ll take now what we’ve learn and will apply it in a model project in .NET. We’ll focus mostly on symmetric and asymmetric encryption which we discussed here, here and here. The goals of the project are as follows:

  • Practice cryptography in a realistic web API project – at least as realistic as can be expected from a blog as opposed to an entire book
  • Show how asymmetric and symmetric encryption could be used in parallel to increase messaging security
  • Show how the public key of the asymmetric key pair can be used only once and refreshed for each new message
  • Be independent of digital certificates

You may be wondering about this last point so let me explain more. You may not always have access to a valid certificate from a CA. Also, a certificate has an expiry date and if you forget to renew it then messaging to and from your server can not be verified. So the goal here is to have secure messaging in place without having to purchase, install and maintain certificates.

Messaging flow

Recall the following from the posts on encryption mechanisms mentioned above:

  • Asymmetric encryption is safe but slow – in practice it is only used to encrypt short strings
  • Symmetric encryption has the problem of sharing public keys, but symmetric algorithms are fast

However, we still want to transfer large texts in a secure and fast way. The solution is to combine the two techniques. Imagine the following conversation between the Sender (S) and the Receiver (R):

S: Hello R, I want to send you a message so I need your asymmetric public key
R: Hello S, OK, here you are, you get two things: my asymmetric public key and a message ID. Use this message ID in your message to me
S: Thanks! I’ll encrypt my message using my symmetric public key, encrypt my symmetric public key with your asymmetric public key and attach the message ID as well. Here you are!
R: Great! I’ll verify if the message ID is still valid. If so, then I’ll decrypt your symmetric public key using my asymmetric private key and decrypt your message using the decrypted symmetric public key. I’ll then remove the asymmetric public key from the list of valid IDs.

I hope you could follow along. The process should be a lot clearer when we look at some code.

The front end of the receiver in this model project will be a Web API based web service. The overall structure of the application will follow that of the model DDD skeleton project we built up here although in a very simplified format. Here we don’t care about domains and domain logic, but we still want to build a layered application with good SOLID design. We could introduce a Domain project as well, but I don’t want to digress too much otherwise we’ll end up discussing stuff that’s not related to the main topic: entity base, value objects etc. In case you’d like to extend this cryptography project to a more Domain Driven Design type of application then check out the provided link – you’ll probably find enough information there to proceed.

We’ll of course test the application with a sender. The sender will be a simple console project, we don’t need anything more complicated.

The receiver

Open Visual Studio 2012/2013 and create a new blank solution called Receiver.

Add a class library called Receiver.Infrastructure to it. Delete Class1.cs and add a folder called Cryptography. If you don’t know the purpose of this layer, then in short the infrastructure layer is used to include classes that encapsulate cross-cutting concerns such as logging, caching, identification. It’s a container of objects and services that do not have any domain-specific roles and can be used in any other projects and layers.

The first function we want to implement in the project is the creation of a one-time asymmetric key pair that the sender can use. If you are familiar with good software engineering practices then you’ll know that it’s a good idea to abstract away dependencies. Here we want to hide the asymmetric key pair generation technique behind an interface. In most cases RSA will be the chosen technique, but there’s nothing stopping you from employing other algorithms such as DSA. Also, unit testing will be easier if you can inject any type of algorithm into the object that has this dependency. You can read more about unit testing and TDD here.

Add the following interface into the folder:

public interface IAsymmetricCryptographyService
{
	AsymmetricKeyPairGenerationResult GenerateAsymmetricKeys();
}

…where AsymmetricKeyPairGenerationResult looks like this:

public class AsymmetricKeyPairGenerationResult
{
	private XDocument _fullKeyPairXml;
	private XDocument _publicKeyOnlyXml;

	public AsymmetricKeyPairGenerationResult(XDocument fullKeyPairXml, XDocument publicKeyOnlyXml)
	{
		if (fullKeyPairXml == null) throw new ArgumentNullException("Full key pair XML");
		if (publicKeyOnlyXml == null) throw new ArgumentNullException("Public key only XML");
		_fullKeyPairXml = fullKeyPairXml;
		_publicKeyOnlyXml = publicKeyOnlyXml;
	}

	public XDocument FullKeyPairXml
	{
		get
		{
			return _fullKeyPairXml;
		}
	}

	public XDocument PublicKeyOnlyXml
	{
		get
		{
			return _publicKeyOnlyXml;
		}
	}
}

The purpose of the AsymmetricKeyPairGenerationResult object is to encapsulate the full asymmetric key pair and its public-key-only part in an object. If you recall from our discussion on asymmetric algorithms then the public key can be sent to anyone who wants to send a message to us. The full XML which includes the private key must stay safe. Therefore it’s reasonable to store them in two different XML objects.

You may be wondering why I chose to store them as XDocuments. I wanted to make sure that the implementing class returns the keys as valid XML so that it’s guaranteed that the sender will be able to extract the public key from it. The XDocument object will throw an error if you try to parse a string that’s not formatted correctly.

We know that RSA is supported in .NET. However, we cannot make the RSACryptoServiceProvider object implement our interface, right? The Adapter pattern is an easy way to bridge this problem. Insert the following implementation of this interface in the same folder:

public class RsaCryptographyService : IAsymmetricCryptographyService
{
	public AsymmetricKeyPairGenerationResult GenerateAsymmetricKeys()
	{
		RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider();
		XDocument publicKeyXml = XDocument.Parse(myRSA.ToXmlString(false));
		XDocument fullKeyXml = XDocument.Parse(myRSA.ToXmlString(true));
		return new AsymmetricKeyPairGenerationResult(fullKeyXml, publicKeyXml);
	}
}

The RsaCryptographyService encapsulates the built-in RSACryptoServiceProvider object. With the RSACryptoServiceProvider object it’s very easy to generate new asymmetric key pair and export them to XML strings. The ‘false’ parameter means that we don’t want to put the private key into the XDocument object. We finally return the key generation result that holds the full key and the public key as XML.

In case you want to test a different asymmetric algorithm then you just create a different implementation of the IAsymmetricCryptographyService interface and encapsulate that algorithm.

That’s it for the Infrastructure layer. In the next post we’ll continue with the Repository layer.

You can view the list of posts on Security and Cryptography here.

Key size and key storage in .NET cryptography

Key size considerations

In the past several blog posts we talked a lot about how keys are used in symmetric and asymmetric cryptography. You’ve seen that they can come in different sizes – 128bit, 256bit etc.

There’s a trade-off between performance and security when it comes to key sizes. The larger the size the harder it is for an attacker to break it by brute force. However, large size keys make the encryption and decryption process slower, so you’ll need to consider just how important your data is. You’ll probably want to protect your bank account information as much as possible. Also, a bank account number is a short string so using asymmetric encryption in that case will not make must difference to the speed. On the other hand the contents of an unpublished book may not require the same degree of security.

If you go for a very small key, say 2 bits, then it will be easy to break as there are not many different values:

00,01,10,11

As you move up the bit size then the amount of different possibilities grows exponentially. A 512-bit key would take an immense amount of time to break by brute force. So for max security always take the highest available key size in .NET, such as a 256-bit key in Rijndael managed AES symmetric encryption. Then you can take up the fight with other developers who may be more concerned with performance. However, with the CPUs that are available today increasing the bit size from 128 to 256 will only decrease the performance by some milliseconds.

In other words if you are working with data that must be secured then make sure to set a high priority on the security implementation of your app. You can always make adjustments to this implementation if you see that your app is not as responsive as you want it to be.

RSA keys are normally a lot larger than those in AES: 1024, 2048 or 4096 bits. These sizes provide an enormous amount of bit combinations. In practice we take either the 2048 or 4096 bit key size.

Key storage

We mentioned key storage here and there throughout the posts on cryptography. Here again you’ll need to consider what type of blocking points you want to give to an attacker. In general never underestimate the tools available to an experienced hacker. What may seem impossible to extract to a normal user will be a piece of cake for a professional.

You may think that hardcoding your keys in your source files, such as…

private string _myKey = "234dfgdsfw4rfdvg";

…will be impossible to read on the server as you only deploy the compiled code, the DLLs, right? Well, there are disassemblers out there, such as ILDASM, that quickly uncover such values. There are many available tools that can do reflection on compiled code so if your keys are important then don’t save them in plain text in your source files.

Also, hard-coded strings can be read by other people in your organisation. Normally your source code is stored in some central storage such as GitHub or SVN so anyone who has access to those accounts can pull the data from it. I’m not saying that you should distrust your co-workers but if the keys are used to encrypt some vital data then again, don’t put them visible in a string.

We saw in the previous post how you can encrypt the appSettings section of the config file. You can then save the keys as app settings entries and encrypt the appSettings section. If you’re concerned that somebody may get access to the config file on the server then this is a good option as they will only get access to jumble of encrypted characters that they cannot read. Here again, other developers will be able to pull out sensitive data programmatically:

string key = ConfigurationManager.AppSettings["RsaKey"];

.NET will take care of the decryption automatically. We’re again talking about distrusting your colleagues, but when it comes to security then you’ll need to take on a “you never know” attitude if you’re the one responsible for writing the security part of the project.

You may even store the key in the Registry instead of the config file, that’s another option.

You can also have a remote service responsible for providing the correct key. In this scenario the key is not physically stored on the deployment server. The attacker who gained access to the server would need to be able to execute code from this server in order to get the key from the service.

With asymmetric encryption we can store the public key on the application server. It won’t do any harm if an attacker could read it as it’s only used for encryption. The private key can be stored on an intranet server that’s protected by the company firewall.

Other considerations

For even more security make sure you refresh your keys periodically. Don’t use the same keys for encryption and decryption for ever because if some hacker is watching this traffic then they will have a better starting point to guess what the keys are.

This point is important also because you may not even be aware that your cryptography has been broken. Some hacker may be happily sniffing your web traffic and extract all the data they need. They will most likely not tell you about it…

In the next post we’ll start looking at a simple cryptography project to see how a sender and a receiver can communicate using encrypted messages with symmetric and asymmetric techniques we’ve seen up to now.

You can view the list of posts on Security and Cryptography here.

How to protect your config file in .NET with cryptography

Introduction

In the past several blog posts we’ve looked at various cryptography techniques in .NET: hashing, symmetric and asymmetric encryption and digital signatures. Yet another application of encryption in .NET is protecting the config file of your project. The goal here is that if an attacker gains access to the file system on the application server then they shouldn’t be able to read any sensitive information from it.

The idea is that certain sensitive sections of the config file are encrypted and stored separate from the app.config or web.config files. These sections are then decrypted by ASP.NET automatically. We don’t need to worry about writing complicated decryption code ourselves. In practice this technique is applied to the app settings and connection settings section of the configuration. We can use encryption keys either at the machine or the user level.

We can take one of two approaches: DPAPI which is built-into Windows or RSA, which we discussed in the posts on asymmetric algorithms and digital signatures.

DPAPI

With DPAPI built into Windows we’ll use machine-specific keys so you don’t need to worry about key storage issues. Key storage is managed by DPAPI in a secure way. This approach is very straightforward to use on a single server as the key is specific to that machine. However, you cannot move that encrypted web.config to another server in a web farm as the other servers will have other keys. The RSA-based solution is better suited for web farms which we’ll look at shortly.

DPAPI demo

We’ll use the aspnet_regiis tool to encrypt and decrypt a file. You’ll need to have a project with either a web.config or app.config file. For this be meaningful insert a couple of app settings to the file, they don’t need to make any real sense:

<appSettings>
        <add key="secretKey" value="key" />
	<add key="rsaKey" value="rsaKey" />
	<add key="thisisgreat" value="true" />
	<add key="codetosavetheworld" value="secret" />
</appSettings>

The aspnet_regiis tool is usually located in one of these folders:

C:\Windows\Microsoft.NET\Framework\v4.0.30319
C:\Windows\Microsoft.NET\Framework64\v4.0.30319

Open a command prompt and navigate to the correct folder. Take note of the folder of your application where the config file is located. Enter the following command to encrypt the app settings section:

aspnet_regiis -pef “appSettings” C:\path-to-folder-with-config-file -prov “DataProtectionConfigurationProvider”

DataProtectionConfigurationProvider is the DPAPI provider so we ask the tool to encrypt the appSettings section of the config file with DPAPI.

If the process succeeded then open the config file and you should see some funny-looking EncryptedData and CipherData nodes:

<appSettings configProtectionProvider="DataProtectionConfigurationProvider">
  <EncryptedData>
   <CipherData>
    <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAARlLCV8A5OE2a9bhixy2JFwQAAAACAAAAAAADZgAAwAAAABAAAACtSLR5AiN84R+VKYn18+aPAAAAAASAAACgAAAAEAAAALygmbBS72xqElqrjz32sVmoAQAAFA+MvV+KYs/MZKMsCvYfapjetPvKgWjm/VNsyFkEaTx8A6z9PigAQdB/H64BOyTh5YVCcijhTrO8D6iU2LnXGwdhZeev4Rskk1AkliD+fLXvxfg7f9dnpjlI16694q60FrpDlIL9LQ9lqSUYgjsJvgZmfI48eXifGQ36HYTWYAWAjm2uQc6OUe2HlDdGr27nvZoVBZXy1Lho6JpiqRjD6VmbyH0TctysLCuzRrKx/8hPpIrrcvSVFcuNtFnbk2UGREt4Urh+TgMH8b5F2BM4jtN4jxblnyGbgwJKBMeheaypk2jctsKIkg6Ly8MhFDjgzJ/YqjV43ucnnt4HV13/TwHK1cvvfxQi5Xbs6vAqu4ZnaTfLdgecQ2JScTYbFoJKrti9quTKev3xOqtjj1vq2VC5mkTiSWxDfrVUH/nIZ3zXE6oGE1gQ9NXFZZ0iZ4casOe6Qq6u8hBLCTWVhdwlGftNAEbSILDdDMQUTCC8xeX2NHIukFRfCC9N6MoCqVFI6bkMj9ovDE//BqVGoLT/0VfmfzmDcXvV/PMJyLcuXnpHDJsPlgPyKxQAAADjr4S4XVr4grgNFiaLrr3waoMx3Q==</CipherValue>
   </CipherData>
  </EncryptedData>
 </appSettings>

Later when you try to extract some settings from the appsettings section in code then the decryption process will be performed for you so you can read values as before.

If you want to edit the app settings section then here’s the decryption command:

aspnet_regiis -pdf “appSettings” C:\path-to-folder-with-config-file

This will enable you to edit the appSettings section as normal.

RSA

If you want to reuse the same encrypted config file on multiple servers in a web farm then RSA is the best choice. The flow is the following from a high level:

  • Generate an RSA key-pair on the first server
  • Set up the local config provider for the customer key pair
  • Use aspnet_regiis to encrypt the sensitive sections in the config file
  • Grant access to the key for the Network Service account
  • Export the key pair for reuse on the other servers of the farm
  • On all other servers we import the key pair and grant Network Service access to it

RSA demo

In the post on asymmetric encryption we discussed how to generate and export RSA key pairs using aspnet_regiis. Make sure that the key-pair is exportable using the -exp flag. Let’s say that the key container is called “MyCustomKeys”:

aspnet_regiis -pc “MyCustomKeys” -exp

We need to set a reference to this container in the config file in a section called configProtectedData within the configuration root node. We also specify that we use RSA to do the file protection:

<configProtectedData>
	<providers>
		<add keyContainerName="MyCustomKeys"
				 useMachineContainer="true"
				 name="CustomProvider"
				 type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
	</providers>
</configProtectedData>

Again use aspnet_regiis to encrypt the appSettings section referring to the config protection provider we named “CustomProvider” in the configProtectedData:

aspnet_regiis -pef “appSettings” c:\path-to-folder-with-config-file -prov “CustomProvider”

You export those keys like this:

aspnet_regiis -px “CustomKeys” “c:\myCustomKeys.xml” -pri

This creates an XML file we’ve seen before.

This is how you import those keys on the other servers:

aspnet_regiis -pi “CustomKeys” “c:\myCustomKeys.xml”

Make sure to copy over the XML file of course.

Decrypting a config file is done the same way as before:

aspnet_regiis -pdf “appSettings” c:\path-to-folder-with-config-file

Just like with DPAPI you don’t need to set any decryption data yourself when you want to read some app settings in the config file, it’s performed for you automatically.

We also mentioned that Network Service will need access to those keys. Guess which tool can be used to achieve that… …aspnet_regiis of course!

The following command will do just that:

aspnet_regiis -pa “MyCustomKeys” “NT Authority\Network Service”

If this fails on one of the web farm machines then it might be that you need to grant access to the ID that the app-pool is running under:

aspnet_regiis -pa “CustomKeys” “IIS APPPOOL\.NET v4.5” -full

So in case decryption fails on the web servers then make sure you try both of these commands. You’ll obviously need to look up the app-pool ID for your website.

Protecting XML

To wrap up this post here comes a little note on XML strings in particular. The config file may not not be the only XML-formatted data the you want to protect. You may work a lot with XML in you code and you may want to protect portions of those strings. You can learn about the System.Security.Cryptography.Xml namespace on MSDN.

You can view the list of posts on Security and Cryptography here.

Introduction to digital signatures in .NET cryptography

Introduction

I’ve devoted the last few posts to cryptography in .NET: hashing, asymmetric and symmetric encryption. Digital signatures are yet another application of cryptography. They provide data integrity and non-repudiation. This latter means that a user cannot claim that he or she wasn’t the one how signed a particular – digital – document. As public keys can be distributed to other users for encryption purposes they are not good candidates for ensuring non-repudiation. So we need to use the sender’s private key with which the contents of a message can be signed. The contents will be hashed. “Signing” means encrypting with the sender’s private key.

Here’s a flow diagram of the process:

Digital signatures flow

In this scenario we’d like to send some information to another person in a secure way. We want to encrypt it so that only that person can see it and we also want to sign that message so that the receiver will know that it came from us.

The message we want to send is shown on the left of the diagram as “plain text”. The next step is the same as what we saw in asymmetric encryption: we encrypt the message with the receiver’s public key. We get the cipher text as the result. We then hash that cipher text so that we know that it won’t be tampered with while it’s transmitted to the receiver. In addition it’s not necessary to sign the entire data content as it can potentially grow very large and asymmetric encryption is rather slow – we don’t want to waste a lot of time just signing large size data.

So instead of signing the actual cipher text we get the hash of it, we encrypt the hash using our own private key. The result is a digital signature and a cipher text. The cipher can only be encrypted by the receiver using their private key. On top of that the hash is signed with our private key. The receiver can decrypt the signature using our public key since – recall from the post on asymmetric encryption – the private and public keys are inverses of each other. The receiver will have access to our public key. If the decryption succeeds then the receiver will know that it must have come from someone who has the correct private key.

This all probably sounds a bit complex at first but I hope the demo will make it clear how it all works.

The creation of the cipher text is not actually required for digital signatures. The main purpose of digital signatures is tamper-proof messaging. In the demo we’ll go for the full encryption cycle – if you don’t require the encryption bit in your code then you can simply ignore it.

Demo

Create a new Console app in Visual Studio. Insert a class called Sender. Add two class level fields to Sender.cs:

private string _myRsaKeys = "...";
private string _receiversPublicKey = "...";

I’ve shown you some techniques in the previous post on how to generate valid RSA keys, I won’t repeat it here. The important thing here is that _myRsaKeys will be an XML string including both my private and public keys, so copy the entire XML contents there. Then generate another set of RSA keys and save the public key portion of it in _receiversPublicKey, but don’t throw away the rest, it will be needed later when we look at the Receiver. Again, refer to the previous post to see how to keep the private and public key portions of an RSA key pair in an XML string variable. This is a simulation of a case where I received the public key of a partner whome I wish to send encrypted messages.

We’ll need RSA ciphers for the sender and receiver so add the following methods to Sender.cs:

private RSACryptoServiceProvider GetSenderCipher()
{
	RSACryptoServiceProvider sender = new RSACryptoServiceProvider();
	sender.FromXmlString(_myRsaKeys);
	return sender;
}

private RSACryptoServiceProvider GetReceiverCipher()
{
	RSACryptoServiceProvider sender = new RSACryptoServiceProvider();
	sender.FromXmlString(_receiversPublicKey);
	return sender;
}

This should look familiar from the previous post. We’ll use our own private key in the GetSenderCipher method for creating the signature – if you get lost you can always refer back to the diagram above. The receiver’s public key will be needed in order to encrypt the plain text and create the cipher text. They will use their private key to do the decryption.

We can compute the hash of the cipher text using the following method:

private byte[] ComputeHashForMessage(byte[] cipherBytes)
{
	SHA1Managed alg = new SHA1Managed();
	byte[] hash = alg.ComputeHash(cipherBytes);
	return hash;
}

This should look familiar from the post on hashing techniques in .NET. We’ll sign this hash instead of the entire data transmitted.

There’s a built in signature provider in .NET represented by the RSAPKCS1SignatureFormatter object which will come handy in the following method:

private byte[] CalculateSignatureBytes(byte[] hashToSign)
{
	RSAPKCS1SignatureFormatter signatureFormatter = new RSAPKCS1SignatureFormatter(GetSenderCipher());
	signatureFormatter.SetHashAlgorithm("SHA1");
	byte[] signature = signatureFormatter.CreateSignature(hashToSign);
	return signature;
}

The RSAPKCS1SignatureFormatter object then accepts an RSA provider to sign with which in this case will be our private key. We specify SHA1 as the hash algorithm for the signature. This is the signature that the receiver will verify using our public key.

The methods can be connected in the following public method:

public DigitalSignatureResult BuildSignedMessage(string message)
{
	byte[] messageBytes = Encoding.UTF8.GetBytes(message);
	byte[] cipherBytes = GetReceiverCipher().Encrypt(messageBytes, false);
	byte[] cipherHash = ComputeHashForMessage(cipherBytes);
	byte[] signatureHash = CalculateSignatureBytes(cipherHash);

	string cipher = Convert.ToBase64String(cipherBytes);
	string signature = Convert.ToBase64String(signatureHash);
	return new DigitalSignatureResult() { CipherText = cipher, SignatureText = signature };
}

…where DigitalSignatureResult is a simple DTO:

public class DigitalSignatureResult
{
	public string CipherText { get; set; }
	public string SignatureText { get; set; }
}

The steps in the BuildSignedMessage correspond to the flow diagram: we encrypt the message, compute a hash of it and finally sign it.

Let’s test from Program.cs if it looks OK up to this point:

static void Main(string[] args)
{
	Sender sender = new Sender();
	DigitalSignatureResult res = sender.BuildSignedMessage("Hello digital sig!");
	Console.WriteLine(res.CipherText);
	Console.WriteLine(res.SignatureText);

	Console.ReadKey();
}

Run the programme and if everything went well then you should see two sets of character-jungles in the console window.

Now let’s see what the receiver looks like. Add a new class called Receiver. Insert the following class level private fields:

private string _myRsaKeys = "...";
private string _senderPublicKey = "...";

Here the values will be the inverses of the _myRsaKeys and _receiversPublicKey fields of Sender.cs. Receiver._myRsaKeys will be the full XML version of Sender._receiversPublicKey. Conversely Receiver._senderPublicKey will be the reduced public-key-only version of Sender._myRsaKeys. The sender’s public key will be used to verify their signature.

To make this clearer I have the following values in Receiver.cs:

private string _myRsaKeys = "<RSAKeyValue><Modulus>vU3Yfu1Z4nFknj9daoDmh+I0CzR+aLnTjUSejQyNJ0IgMb59x4mVe17C6U+bl4Cry7gXAk3LEmmE/BRxjlF8HKlXixoBWak1dpmr89Ye7iaD2UWwl5Dmn07Q9s27NGdywy0BsD1vDcFSgno3LUbVznkw/0hypbnOPxWKlBCao2c=</Modulus><Exponent>AQAB</Exponent><P>6veL+pbUjOr0PAiFcvBRwNlTz/+8T1iLHqkCggRPDSsTg25ybSqDa98mP5NQj9LHSYCECjOGZkiN4NoxgPPDxw==</P><Q>zj/l0Z36A/iD2IrVQzrEsvp31cmU6f9VCyPIGiM0FSEXbj23JuPNUPCzSo5oAAiSZfs/hR9uuAx1xQFAfTzjYQ==</Q><DP>dsW7VGh5+OGro80K6BbivIEfBL1ZCyLO8Ciuw9o5u4ZSztU9skETPawHQYvN5WW+p0D3fdCd14ZFcavZ6j1OcQ==</DP><DQ>YSQBRzgjsEkVOCEzjsWYLUAAvwWBiLCEyolgzsaz2hvK4FZa9AspAa1MlJn768Ady8CJS1bhm/fqZA5R5GqQIQ==</DQ><InverseQ>zEGFnyMtfxSYHwRv8nZ4xVcFctnU2pYmmXXYv8NV5FvhZi8Z1f1GE3tmS8qDyIuDTrXjmII2cffLMjPOVmLKoQ==</InverseQ><D>Ii97qDg+oijuDbHNsd0DRIix81AQf+MG9BzvMPOSTgOgAruuxSjwaK4NLsrkgzCGVayx4wWfZXzOuiMK+rN2YPr6IPeut3O14uuwLH7brxkit+MnhclsCtKpdT2iuUGOnbEhWccepCO7YLyyczhT9GE0rEtbEK6S7wvVKab/osE=</D></RSAKeyValue>";
		

private string _senderPublicKey = "<RSAKeyValue><Modulus>rW0Prd+S+Z6Wv0gEakgSp/v8Pu4xJ6OjaVCHKTIcf/C5nZvE77454lii3Ne6odV+76oaM2Pn3I9kKehK7CtqklI7rc1+05WRE3u8O5tC5v2ECjEDPMULAcZVTjXSyZtSAOiqk+6nEcJGRED65aGXwFgZuxEY8y4FbUma3I311aM=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

…and in Sender.cs:

private string _myRsaKeys = "<RSAKeyValue><Modulus>rW0Prd+S+Z6Wv0gEakgSp/v8Pu4xJ6OjaVCHKTIcf/C5nZvE77454lii3Ne6odV+76oaM2Pn3I9kKehK7CtqklI7rc1+05WRE3u8O5tC5v2ECjEDPMULAcZVTjXSyZtSAOiqk+6nEcJGRED65aGXwFgZuxEY8y4FbUma3I311aM=</Modulus><Exponent>AQAB</Exponent><P>5TYzDyoQBT4C8eqyuWlfNbg0XfnJAUHzonOiz/5az86E9y8V3oxDH3B3GMECDzvcLRJnp5x/G1Lectu1p3ckDw==</P><Q>wbHOTIh7l/p9FszFj/uMdvLlITyABeOZVJEPJhw6fkMSqiRqnx4F2dtqRcGUDBhpWbG6kbTXi9ijMVL8u+iRLQ==</Q><DP>h0KOqvo1bgKEFmJbiZKm/rpvHK3UcguLTGhUwczlpg/G419D1oqK6biib1cmcfrvGSHtTTnKwEMMxlblQafK/Q==</DP><DQ>u80hQFVouF+Xn16mA0eb1s0FWmdlndAin7sSHBpsoHV6CFvMwUCD3cp/TOk3GU8l/mBzi8jy4NYIzM8w2yTQdQ==</DQ><InverseQ>1rYDocFlo3EEs28Miieqa/fE8uzESz6YWONuZPoKHWO/1m9Tf0K01+TtPqDBFRhFBaTNKBJ2lyCGGRIEA41CYg==</InverseQ><D>dZvsciGYbqfZ20ZfmCPgYwNEAPlPZG5Yt2bhAlL1eN4rQnMMjvkWECXD7Lhv3KgIOUfGFOu/pZeoebMKfDbFQe6uA9f4jSYiC3yI0lyGiZQ+SpyJPRKetSSSqiOcK/vnnn2+03RgOVnyU3T52hRXVsb3oXtT5xacWm4IeGABB2E=</D></RSAKeyValue>";
		

private string _receiversPublicKey = "<RSAKeyValue><Modulus>vU3Yfu1Z4nFknj9daoDmh+I0CzR+aLnTjUSejQyNJ0IgMb59x4mVe17C6U+bl4Cry7gXAk3LEmmE/BRxjlF8HKlXixoBWak1dpmr89Ye7iaD2UWwl5Dmn07Q9s27NGdywy0BsD1vDcFSgno3LUbVznkw/0hypbnOPxWKlBCao2c=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

We’ll need to set up sender and receiver RSA providers in the Receiver class as well:

private RSACryptoServiceProvider GetSenderCipher()
{
	RSACryptoServiceProvider sender = new RSACryptoServiceProvider();
	sender.FromXmlString(_senderPublicKey);
	return sender;
}

private RSACryptoServiceProvider GetReceiverCipher()
{
	RSACryptoServiceProvider sender = new RSACryptoServiceProvider();
	sender.FromXmlString(_myRsaKeys);
	return sender;
}

We’ll also need the same hash computation method that was employed on the Sender’s side.

private byte[] ComputeHashForMessage(byte[] cipherBytes)
{
	SHA1Managed alg = new SHA1Managed();
	byte[] hash = alg.ComputeHash(cipherBytes);
	return hash;
}

I realise that this is a lot of duplication but imagine that the Sender and Receiver are different applications with no possibility to have a shared project. It’s important they they set up details such as “SHA1” in the ComputeHashForMessage methods for consistency. If one specifies SHA1 and the other one SHA256 then the process will fail of course so the two sides must agree on a common platform. Usually the person who needs to send a message to someone else will need to comply with what the receiver has set up on their side.

The RSAPKCS1SignatureDeformatter object has a VerifySignature method that is very useful in our case:

private void VerifySignature(byte[] computedHash, byte[] signatureBytes)
{
	RSACryptoServiceProvider senderCipher = GetSenderCipher();
	RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(senderCipher);
	deformatter.SetHashAlgorithm("SHA1");
	if (!deformatter.VerifySignature(computedHash, signatureBytes))
	{
		throw new ApplicationException("Signature did not match from sender");
	}
}

We’ll need to pass in the computed hash of the cipher text received from the sender and the signature bytes so that we can verify the authenticity of the message. If this method returns true then the receiver will know that the message must have originated from someone with the correct private key. Otherwise there’s reason to suspect that the message has been tampered with. In fact we need to recompute that hash of the cipher the same way the sender computed the hash. You can see that in the following public method in Receiver.cs:

public string ExtractMessage(DigitalSignatureResult signatureResult)
{
	byte[] cipherTextBytes = Convert.FromBase64String(signatureResult.CipherText);
	byte[] signatureBytes = Convert.FromBase64String(signatureResult.SignatureText);
	byte[] recomputedHash = ComputeHashForMessage(cipherTextBytes);
	VerifySignature(recomputedHash, signatureBytes);
	byte[] plainTextBytes = GetReceiverCipher().Decrypt(cipherTextBytes, false);
	return Encoding.UTF8.GetString(plainTextBytes);
}

This is the inverse of the BuildSignedMessage of Sender.cs. We send in the DigitalSignatureResult object that resulted from the encryption process on the sender’s side. The cipher and signature are converted back to byte arrays. Then the hash is recomputed and the signature is verified. If we get this far then we know that the message is authentic and we can decrypt the message.

The ExtractMessage can be called in Program.cs as follows:

static void Main(string[] args)
{
	Sender sender = new Sender();
	DigitalSignatureResult res = sender.BuildSignedMessage("Hello digital sig!");
	Console.WriteLine(res.CipherText);
	Console.WriteLine(res.SignatureText);

	String decryptedText = new Receiver().ExtractMessage(res);
	Console.WriteLine(decryptedText);

	Console.ReadKey();
}

Run the application and you should see that the signature is correct and the message is correctly decrypted by the receiver.

Digital certificates

We’ll wrap up this post on a short intro into digital certificates. Certificates are another, more advanced way to make sure that a message is coming from the person who claims to be the sender of the message. They are often used in conjunction with web traffic. If you see https:// in the URL then you know that some certificate is involved. In that case it’s not plain TCP that’s used for data transmission but SSL – Secure Sockets Layer – and TLS – Transport Layer Security.

A digital certificate is basically a public key assigned to a particular entity, like what a registration number is to a car. The number plate can be used to verify the owner of the car. The driver presents an ID card and if the data on the ID card matches what the police registry says about the owner of the car then the “certificate” is accepted. Otherwise the driver may have stolen the car or the number plate.

The format that a digital certificate follows is usually an X509 format. It contains an issuer, a validity period, the public key and the issuer’s signature. The digital signature helps us validate the public key of the sender. This process requires a certain level of trust in the issuer of the certificate. There are trusted issuers, so called Certificate Authorities (CAs), that the browsers have on their trusted issuers’ list.

It is the CA that signs the public key. They basically tell you like “we attest that the public key in this certificate comes from the owner of the public key”. The browser will have a list of those approved CAs and their public keys so they can validate signatures attached to these certificates.

So when the owner of the car presents an ID then it cannot just be any type of ID, it must have been issued by some authority. The authority attests through the ID that the person is really the one the ID claims them to be. This ties in well with claims-based security.

TLS and SSL are responsible to do the encryption between web browsers and web servers to make sure that the messages are not tampered with. You can use self-signed certificates for testing but if you use it in production then the web browser will warn you that the certificate didn’t come from one of the trusted CAs.

In other cases you may see that the browser warns that the certificate comes from a trusted CA, so the certificate is itself correct, but the domain name within the certificate is different from the domain name I’m visiting. It may be a sign that someone stole someone else’s certificate.

You can view the list of posts on Security and Cryptography here.

Introduction to asymmetric encryption in .NET cryptography

Introduction

In the previous two blog posts we looked at symmetric encryption in .NET. Recall that it’s called “symmetric” as both the receiver and the sender must have access to the same public key. Asymmetric encryption differs in that it involves two complementary keys: a public key and a private key. Asymmetric algorithms are also called Public Key Cryptography.

These algorithms are up to 100-1000 times slower than symmetric ones. They are therefore often used to encrypt small size data such as a symmetric key.

We can graphically show the data flow as follows:

Asymmetric algorithm flow

If I want to send some secret data to a particular receiver then I’ll need their public key. Then I’ll do the encryption with that public key which creates the cipher text. When the receiver gets the cipher text they will decrypt it using their private key. So these keys come in pairs in a sense that you encrypt with one and decrypt with the other.

In .NET asymmetric algorithms are represented by the AsymmetricAlgorithm abstract base class. There are a few implementations readily available:

The most common is RSA. DSA and EXDiffieHellman are only used in conjunction with digital signatures.

The public and private keys are inverses of each other: a message encrypted with the public key can be decrypted with the private key. Similarly, the same message encrypted with the private key and be decrypted by the public key.

Demo

Open Visual Studio and create a new Console application. Insert a new class called AsymmetricAlgoService. RSA is represented by the RSACryptoServiceProvider object so we’ll need to create it first for the encryption part. Insert the following method:

private RSACryptoServiceProvider CreateCipherForEncryption()
{
	RSACryptoServiceProvider cipher = new RSACryptoServiceProvider();			
	cipher.FromXmlString(_rsaKeyForEncryption);
	return cipher;
}

…where _rsaKeyForEncryption is a private string field with some XML that we’ll look at in a second.

There are several ways to generate and store the RSA keys. There’s a FromXmlString method which populates the appropriate properties of the RSACryptoServiceProvider object based on an XML string. The XML string is populated from a previously exported set of RSA keys. You can also do this using the CspParameters object as follows:

CspParameters cspParams = new CspParameters();
cspParams.KeyContainerName = "RsaKeys";
cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
RSACryptoServiceProvider crypto = new RSACryptoServiceProvider(cspParams);

This will use an existing RSA protected key container called RsaKeys. If the container doesn’t exist then it auto-generates one. The public-private key pair will be stored in Windows key storage, i.e. on the machine level, hence the selected flag value.

You can use the aspnet_regiis tool to generate and export RSA keys. This tool is usually located in one of these folders:

C:\Windows\Microsoft.NET\Framework\v4.0.30319
C:\Windows\Microsoft.NET\Framework64\v4.0.30319

Open a Command prompt and navigate to the correct folder. Insert the following command:

aspnet_regiis -pc “MyKeys” -exp

You can specify a different key container name if you want of course. If everything went well then you should see “Creating RSA Key container… Succeeded!” in the command window. The -exp flag means that the key pair can be exported. In order to export the contents of the key container to an xml file you can use the following command:

aspnet_regiis -px “MyKeys” c:\temp\mykeys.xml -pri

The -pri flag indicates that we want to export the private key as well. We’ll only need it in our code, that’s not something you want to redistribute.

Check the contents of the XML file. It will have the following elements: modulus, exponent, p, q, dp, dq, inverseq and d. Copy the modulus and exponent elements to the _rsaKeyForEncryption private field mentioned above, so the field should have the following format:

private const string _rsaKeyForEncryption = @"<RSAKeyValue>
	<Modulus>blahblah</Modulus>
	<Exponent>blahblah</Exponent>
</RSAKeyValue>";

This is the XML that you can distribute to the programmes and partners that need to send encrypted data to your application(s). You can already now create a second private field and assign the full XML to it:

private const string _rsaKeyForDecryption = @"<RSAKeyValue>
	<Modulus>blah</Modulus>
	<Exponent>blah</Exponent>
	<P>blah</P>
	<Q>blah</Q>
	<DP>blah</DP>
	<DQ>blah</DQ>
	<InverseQ>blah</InverseQ>	
        <D>blah</D>
</RSAKeyValue>";

This is only one way to create and export a valid RSA key pair. You can achieve this programmatically as well:

public void ProgrammaticRsaKeys()
{
	RSACryptoServiceProvider myRSA = new RSACryptoServiceProvider();
	RSAParameters publicKey = myRSA.ExportParameters(false);
	string xml = myRSA.ToXmlString(true);
}

This creates a new instance of an RSA algorithm and exports its auto-generated public key to an RSAParameters object. The ‘false’ parameter sent to ExportParameters method says please don’t want to export the private key. Which is fine as the private key should stay by you only. The ToXmlString(true) shows the xml output including the private key. If you set that to false then the XML will only show the Modulus and Exponent elements.

The most interesting sections in the extended version of the XML string are D, Modulus and Exponent. D denotes the private key. Exponent is the short part of the public key whereas Modulus is the long part. You won’t need to access the other elements in the XML string.

There’s also a distinction between user-level and machine-level keys. A currently logged-on user can access the machine-level keys and those user-level ones that they have generated for themselves. When a different user logs onto the same computer then they won’t have access to the user-level keys assigned to other users. However, they will still have access to the machine-level keys. Inspect the CspProviderFlags enumeration mentioned above. You’ll see that it includes an option for user-level key storage. You can read more about this distinction on MSDN here.

We can encrypt any string input as follows:

public string GetCipherText(string plainText)
{
	RSACryptoServiceProvider cipher = CreateCipherForEncryption();
	byte[] data = Encoding.UTF8.GetBytes(plainText);
	byte[] cipherText = cipher.Encrypt(data, false);
	return Convert.ToBase64String(cipherText);
}

For decryption we’ll need a cipher that reads the full XML string:

private RSACryptoServiceProvider CreateCipherForDecryption()
{
	RSACryptoServiceProvider cipher = new RSACryptoServiceProvider();
	cipher.FromXmlString(_rsaKeyForDecryption);
	return cipher;
}

The decryption method is the inverse of the one performing the encryption part:

public string DecryptCipherText(string cipherText)
{
	RSACryptoServiceProvider cipher = CreateCipherForDecryption();
	byte[] original = cipher.Decrypt(Convert.FromBase64String(cipherText), false);
	return Encoding.UTF8.GetString(original);
}

You can call these methods from Program.cs as follows:

AsymmetricAlgoService asymmService = new AsymmetricAlgoService();
string cipherText = asymmService.GetCipherText("Hello");
Console.WriteLine(cipherText);
string original = asymmService.DecryptCipherText(cipherText);
Console.WriteLine(original);

Run the code and you should see that the translates the string back to its original value. Just for verification purposes modify the CreateCipherForDecryption() method so that the encryption XML is used instead i.e. without the private key:

cipher.FromXmlString(_rsaKeyForEncryption);

Decryption still succeeds but a cryptographic exception will be thrown within the Decryption method saying that the key does not exist.

Considerations

In practice you wouldn’t use RSA to encrypt and decrypt arbitrarily long strings. You can encrypt your string using a symmetric algorithm, like AES discussed here then encrypt the AES secret public key using the RSA public key. The other party will be able to decrypt the secret AES key using the RSA private key. Then using the key they’ll be able to decrypt your string. We will build a model application which shows how to do this in a later post.

Often a web site needs sensitive information, such as a bank account number. Normally such data should be encrypted in some way. We could take a symmetric algorithm but if you are familiar with that approach then you know why it’s not a good idea – the secret key needs to be shared between the encryption and decryption.

Instead we need to look into what asymmetric encryption has to offer. As we saw before we need to start by generating an RSA key pair and store the public key on the web server. We can share the public key with anyone who needs to send encrypted data to us. We then would need to make sure that the private key is stored safely for the decryption so that no attacker has access to it. The private key could be stored on an internal web server behind a firewall. That web server could be dedicated to data decryption. The public key would then be stored on an “open” web server which hosts your web site. That server could do the encryption and in the absence of the private key would have no possibility to decrypt even the message that it encrypted itself.

Due to the slow speed of asymmetric encryption this approach works well only with small amounts of data – use RSA directly to encrypt and decrypt that small string. As we hinted at at the end of the previous post RSA would rather be used to encrypt a symmetric key and encrypt the actual data using a symmetric algorithm. The symmetric key should be generated on the fly – it is propagated once to the requesting party and never reused. This is a better solution for encrypting and decrypting large amounts of data as symmetric algorithms are a lot faster. Asymmetric algorithms in this case provide a good way around the key-storage problem. Mixing these strategies will provide the advantages of each: speed, safe key storage, maximum message security.

However, you still need to be careful. If you want to send encrypted data to someone then you must be sure that you are encrypting using the correct public key. E.g. if the public key is printed on a blog for everyone to see then an attacker may take over that site and put his/her own public key there instead. In that case you may be sending the secret data to the attacker where they can decrypt it using their private key.

You can view the list of posts on Security and Cryptography here.

Symmetric algorithms in .NET cryptography part 2

In the previous post we started looking at symmetric encryption algorithms in .NET. We also saw an example on how the encrypt and decrypt a string value. We’ll wrap up the discussion with a couple of related topics.

Generating secret keys

You cannot just use any key in the encryption process, it must have a valid format with the specified bit size – usually either 128 or 256 bits. You can generate random bytes using the following function:

public void GenerateRandomBytes(byte[] buffer)
{
	RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
	rng.GetBytes(buffer);
}

We’ve seen the RNGCryptoServiceProvider object in the previous post. It helps generate cryptographically random numbers.

You can call this function as follows:

public string GetValidEncryptionKey(int bitSize)
{
	byte[] key = new byte[bitSize / 8];
	GenerateRandomBytes(key);
	return BitConverter.ToString(key).Replace("-", string.Empty);
}

You send in the bit size which must be converted to bytes, i.e. divided by 8. We generate the random bytes and convert them to a string. The BitConverter class puts a dash in between each hex value which we need to get rid of, hence the call to the Replace function.

This function can be invoked like this:

string validKey = symmDemo.GetValidEncryptionKey(128);

Importance of CBC and padding ISO10126

Run the application we’ve been working on a couple of times and you’ll see that the cipher text is always different even for the same string being encrypted. This is because we get a unique initialisation vector for each encryption and because we’re in CBC mode. Now locate the CreateCipher method and modify the padding and mode values as follows:

cipher.Padding = PaddingMode.Zeros;
cipher.Mode = CipherMode.ECB;

Run the application again with the same string to be encrypted. You should see that the cipher text is always the same. We saw in this post how it can be dangerous to show the same cipher text for string values of limited variability. Hence always use ISO10126 and CBC to add more randomness to the encryption process.

CryptoStream

You can integrate encryption and decryption with .NET streams using the CryptoStream object. Say you want to chain together different crypto transforms and save the output in a file. Let’s look at how this can be done:

public void ChainStreamOperations(string plainText)
{
	byte[] plaintextBytes = Encoding.UTF8.GetBytes(plainText);
	RijndaelManaged cipher = CreateCipher();
	using (FileStream cipherFile = new FileStream(_fileName, FileMode.Create, FileAccess.Write))
	{
		ICryptoTransform base64CryptoTransform = new ToBase64Transform();
		ICryptoTransform cipherTransform = cipher.CreateEncryptor();
		using (CryptoStream firstCryptoStream = new CryptoStream(cipherFile, base64CryptoTransform, CryptoStreamMode.Write))
		{
			using (CryptoStream secondCryptoStream = new CryptoStream(firstCryptoStream, cipherTransform, CryptoStreamMode.Write))
			{
				secondCryptoStream.Write(plaintextBytes, 0, plaintextBytes.Length);
			}
		}
	}
}

…where _fileName is a local variable such as this:

private string _fileName = @"c:\temp\result.txt";

We first create a file stream in a normal .NET way. The purpose of the base 64 crypto transform is that in this case I want to encode the result of the encryption in this way. Then we get the Rijndael crypto transform object as we saw before. You see in the using statements that we create a series of streams. The final goal is to write out the result to a file. Then we have a CryptoStream that ties together the file stream and the base 64 crypto transform. Then on top of that we run the encryption itself. So when we call secondCryptoStream.Write with the plain text it’s going to use the CryptoStream, perform the encryption, perform the base 64 encoding and finally the result is written out to the file. So it’s very straightforward to do a number of encryptions for different plain text values. The chained streams will perform the same steps on all of them.

If you are used to using streams in .NET then this might be a natural way to encrypt a string and put the result in a file.

You can view the list of posts on Security and Cryptography here.

Symmetric encryption algorithms in .NET cryptography part 1

Introduction

Symmetric encryption and decryption are probably what most people understand under “cryptography”. A symmetric algorithm is one where the encryption and decryption key is the same and is shared among the parties involved in the encryption/decryption process.

Ideally only a small group of reliable people should have access to this key. Attackers typically use brute force to find the key in an attempt to decipher an encrypted message rather than defeating the algorithm itself. The key can vary in size so the attacker will need to know this first. Once they know this then they will try combinations of possible key characters.

A clear disadvantage with this approach is that distributing and storing keys in a safe and reliable manner is difficult. On the other hand symmetric algorithms are fast.

Here’s the graphical representation of the algorithm at work:

Symmetric algorithm flow

We start with the plain text to be encrypted. The encryption algorithm runs using the common secret key. The plain text becomes cyphertext which is decrypted using the same secret key and algorithm.

A common algorithm is called AES – Advanced Encryption Standard. This has been a US government standard since 2001 when it replaced DES – Data Encryption Standard.

AES uses the so-called Rijndael algorithm with 128 bit block sizes. You can read about the details of the algorithm here. If you need to work with external partners that use disparate systems then AES is a good choice as it’s widely supported in different encryption libraries in Java, Ruby, .NET, Objective C, etc.

In .NET all symmetric algorithms derive from the SymmetricAlgorithm abstract class. AES with Rijndael is not the only implementation available, here are some others:

  • Triple DES: applies DES encryption 3 times
  • DES: used to be the standard but there were successful approaches to break the key due to its small key size of 56 bits. It is not recommended to use this algorithm in new systems – use it only if you have to support backward-compatibility or legacy systems
  • RC2: this was another competitor to replace DES

There are other symmetric algorithms out there, such as Mars, RC6, Serpent, TwoFish, but there’s no .NET implementation of them at the time of writing this post. Make sure to pick AES/Rijndael as your first choice if you need to select a symmetric algorithm in your project.

In .NET

The .NET implementations if symmetric algorithm are called block ciphers. This only means that the encryption process takes the provided plain text and breaks it up into fixed size blocks, such as 128 mentioned above. The algorithm is performed on each individual block.

It is of course difficult to guarantee that the plain text will fit into those exact block boundaries – this is where padding enters the scene. Padding is data added to fill the last block to the correct size where if it doesn’t fit the given bit size. We need to fill up this last block as the algorithm requires fix sized blocks.

Padding data can be a bunch of zeros. Another approach is called PKCS7. This one says that if there are e.g. 8 bits remaining to fill the block we’ll use that number for each one of those spots. Yet another way to fill the missing spots is called ISO10126, which fills that block with random data. This is also the recommended approach as it provides more randomness in the process which is always a good way to put extra layers of protection on your encryption mechanism.

Mode is also a factor in these algorithms. The most common one is called ECB which means that each block of the plain text will be encrypted independently of all the others. The recommended approach here is CBC – this means that a block will not only be encrypted but that a given block will be used as input to encrypt the subsequent block. So CBC adds some more randomness to the process which is always good.

In case you go with CBC then another term you’ll need to be familiar with is the IV – Initialization Vector. The IV determines what kind of random data you’re going to use for the first block simply because there’s no block before the first block to be used as input. The IV is just some random data that will be used as input in the encryption of the first block. The IV doesn’t need to be some secret string – it must be redistributed along with the cipher text to the receiver of our message. The only rule is not to reuse the IV to keep the randomness that comes with it.

Demo

Now it’s time see some code after all the theory. Create a Console application in Visual Studio. We first want to set up the Rijndael encryption mechanism with its properties. Consider the following code:

private RijndaelManaged CreateCipher()
{
	RijndaelManaged cipher = new RijndaelManaged();
	cipher.KeySize = 256;
	cipher.BlockSize = 128;
	cipher.Padding = PaddingMode.ISO10126;
	cipher.Mode = CipherMode.CBC;
	byte[] key = HexToByteArray("B374A26A71490437AA024E4FADD5B497FDFF1A8EA6FF12F6FB65AF2720B59CCF");
	cipher.Key = key;
	return cipher;
}

We instantiate a RijndaelManaged class which I guess you know what it might represent. We then set its key and block size. As mentioned above padding is set to ISO10126 and mode to CBC. The encryption key must be a valid AES key that you can find plenty of on the Internet. Note that you can set a lower key size, e.g 128, but make sure that the AES key is a valid 128 bit array in that case. Here I set the block size to 128 to be fully AES compliant, but generally the higher the key and block size the more secure the message. I’ve put the key as plain text into the code but it can be stored in the web.config file, in the database, it’s up to you. However, this key must remain secret, so storage is not a trivial issue.

The HexToByteArray method may look familiar from the previous post on hashing:

public byte[] HexToByteArray(string hexString)
{
	if (0 != (hexString.Length % 2))
	{
		throw new ApplicationException("Hex string must be multiple of 2 in length");
	}

	int byteCount = hexString.Length / 2;
	byte[] byteValues = new byte[byteCount];
	for (int i = 0; i < byteCount; i++)
	{
		byteValues[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
	}
	return byteValues;
}

In the below method we perform the actual encryption:

public void Encrypt(string plainText)
{
	RijndaelManaged rijndael = CreateCipher();
	Console.WriteLine(Convert.ToBase64String(rijndael.IV));
	ICryptoTransform cryptoTransform = rijndael.CreateEncryptor();
	byte[] plain = Encoding.UTF8.GetBytes(plainText);
	byte[] cipherText = cryptoTransform.TransformFinalBlock(plain, 0, plain.Length);
	Console.WriteLine(Convert.ToBase64String(cipherText));
}

We let the IV and the cipher text be printed on the Console window. The IV is randomly generated by .NET, you don’t need to set it yourself. We get hold of the encryptor using the CreateEncryptor method as it is implemented by the RijndaelManaged object. It implements the ICryptoTransform interface. We use this object to transform the plain text bytes to the AES-encrypted cipher text.

Run the application and inspect the IV and cipher text values. Save those values in class properties:

public string IV { get; set; }
public string CipherText { get; set; }

You can save these in the Encrypt method:

CipherText = Convert.ToBase64String(cipherText);
IV = Convert.ToBase64String(rijndael.IV);

The Decrypt method is the exact reverse of Encrypt():

public void Decrypt(string iv, string cipherText)
{
	RijndaelManaged cipher = CreateCipher();
	cipher.IV = Convert.FromBase64String(iv);
	ICryptoTransform cryptTransform = cipher.CreateDecryptor();
	byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
	byte[] plainText = cryptTransform.TransformFinalBlock(cipherTextBytes, 0, cipherTextBytes.Length);

	Console.WriteLine(Encoding.UTF8.GetString(plainText));
}

We’ll need the cipher text and the IV we saved in the Encrypt method. This time we construct a Decryptor and decrypt the cipher text using the provided key and IV. It’s important to set up the Rijndael managed object the same way as during the encryption process – key and block size, same mode etc. – otherwise the decryption will fail.

Test the entire cycle with some text, such as “Hello Crypto” and you’ll see that it’s correctly encrypted and decrypted.

You can view the list of posts on Security and Cryptography here.

Hashing algorithms and their practical usage in .NET Part 2

In the previous post we looked at hashing in general and its usage in hashing query strings. In this post we’ll look at some other areas of applicability.

Passwords

Storing passwords in clear text is obviously not a good idea. If an attacker gets hold of your user data then it should not be easy for them to retrieve user names and passwords. It’s a well-established practice to store passwords in a hashed format as they cannot be deciphered. When your user logs onto your site the provided password is hashed using the same algorithm that was employed when the same user signed up with your site. The hashed values, i.e. not the plain text passwords will be compared upon log-in. Not even you as the database owner will be able to read the password selected by the user.

However, you must still be careful to protect the hashed passwords. As we mentioned in the previous post there are not too many hashing algorithms available. So if an attacker has access to the hashed passwords then they can simply get a list of the most common passwords – ‘secret’, ‘password’, ‘passw0rd’, etc. – from the internet, iterate through the available hashing algorithms and compare them to the hashed values in your user data store. They can even write a small piece of software that loops through an online dictionary and hashes those words. This is called a “dictionary attack”. It’s only a matter of time before they find a match. Therefore it may not be a blocking point that an attacker cannot reverse a hashed password.

Hashing passwords can be done in the same way as hashing a query string which we looked at previously. Here comes a reminder showing how to hash a plain text value using the SHA1 algorithm:

byte[] textBytes = Encoding.UTF8.GetBytes("myPassword123");
SHA1 hashAlgorithm = new SHA1Managed();
byte[] hash = hashAlgorithm.ComputeHash(textBytes);
string hashedString = BitConverter.ToString(data);

Salted passwords

So you see that storing hashed values like that may not be secure enough for the purposes of your application. An extra level of security comes in the form of salted passwords which means adding some unique random data to each password. This unique data is called ‘salt’. So we take the password and the salt and hash their joint value. This increases the work required from the attacker to perform a dictionary attack against all passwords. They would need to compute salt values as well.

Again, keep in mind that if you don’t protect your user data store then the attacker will gain access to the salt values as well and again it will be a matter of time before they find a match. It may take longer of course but they can concentrate on some specific valuable accounts, like the Administrator, instead of spending time trying to find the password of a ‘normal’ user.

This is how you can generate a salt:

private static string GenerateSalt(int byteCount)
{
	RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
	byte[] salt = new byte[byteCount];
	rng.GetBytes(salt);
	return Convert.ToBase64String(salt);
}

You’ll need cryptographically strong salt values. One of the available strong random number generators in .NET is the RNGCryptoServiceProvider class. Here we’re telling it that we need a ‘byteCount’-length of random salt. The salt is then saved along with the computed hash in the database.

The extended ComputeHash method accepts this salt:

public static string ComputeHash(string password, string salt)
{
	SHA512Managed hashAlg = new SHA512Managed();
	byte[] hash = hashAlg.ComputeHash(Encoding.UTF8.GetBytes(password + salt));
	return Convert.ToBase64String(hash);
}

So when the user logs in then you must first find the user in the database for the given username. If the user exists, then you have to retrieve the salt generated at the sign-up phase. Finally take the password provided in the login form, compute the hash using the ComputeHash method which accepts the salt and compare the hashed values.

We can add an extra layer or security by providing entropy – a term we mentioned in the previous post. We can extend the ComputeHash method as follows:

public static string ComputeHash(string password, string salt, string entropy)
{
	SHA512Managed hashAlg = new SHA512Managed();
	byte[] hash = hashAlg.ComputeHash(Encoding.UTF8.GetBytes(password + salt + entropy));
	return Convert.ToBase64String(hash);
}

The entropy can be a constant that is common to all users, e.g. another cryptographically strong salt that is not stored in the user database. We can take a random value such as ‘xl1k5ss5NTE=’. The updated ComputeHash function can be called as follows:

string salt = GenerateSalt(8);
Console.WriteLine("Salt: " + salt);
string password = "secret";
string constant = "xl1k5ss5NTE=";
string hashedPassword = ComputeHash(password, salt, constant);

Console.WriteLine(hashedPassword);
Console.ReadKey();

Alternatively you can use a Keyed Hash Algorithm which we also discussed in the previous post.

Examples from .NET

The .NET framework uses hashing in a couple of places, here are some examples:

  • ViewState in ASP.NET web forms is hashed using the MAC address of the server so that an attacker cannot tamper with this value between the server and the client. This feature is turned on by default.
  • ASP.NET Membership: if you have worked with the built-in Membership features of ASP.NET then you’ll know that both the username and password are hashed and that a salt is saved along with the hashed password in the ASP.NET membership tables
  • Minification and boundling: if you don’t know what these terms mean then start here. Hashing in this case is used to differentiate between the versions of the bundled files, such as JS and CSS so that the browser ‘knows’ that there’s a new version to be collected from the server and not use the cached one

We’ll start looking at symmetric encryption in the next post.

You can view the list of posts on Security and Cryptography here.

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

ARCHIVED: Bite-size insight on Cyber Security for the not too technical.