Category Archives: Software development

Extracting Zipped Files with SharpZipLib

This article was originally posted as “C#: Extracting Zipped Files with SharpZipLib” at Programmer’s Ranch on 4th October 2014. Minor amendments have been applied in this republished version. The article illustrates how to reference and work with a third-party library. Nowadays it’s simpler to do this using NuGet.

In this article, we’re going to learn how to extract files from a .zip file using a library called SharpZipLib. Additionally, we will also learn how to work with third-party libraries. This is because SharpZipLib is not part of the .NET Framework, and is developed by an independent team.

To get started, we need to create a new Console Application in SharpDevelop (or Visual Studio, if you prefer), and also download SharpZipLib from its website. When you extract the contents of the .zip file you downloaded, you’ll find different versions of ICSharpCode.SharpZipLib.dll for different .NET versions. That’s the library that will allow us to work with .zip files, and we need the one in the net-20 folder (the SharpZipLib download page says that’s the one for .NET 4.0, which this article is based on).

Now, to use ICSharpCode.SharpZipLib.dll, we need to add a reference to it from our project. We’ve done this before in my article “C#: Unit Testing with SharpDevelop and NUnit“. You need to right click on the project and select “Add Reference”:

cssharpziplib-add-reference-1

In the window that comes up, select the tab called “.NET Assembly Browser”, since we want to reference a third party .dll file. Open the ICSharpCode.SharpZipLib.dll file, click the “OK” button in the “Add Reference” dialog, and you’re ready to use SharpZipLib.

cssharpziplib-add-reference-2

In fact, you will now see it listed among the project’s references in the Projects window (on the right in the screenshot below):

cssharpziplib-add-reference-3

Great, now how do we use it?

This is where our old friend, Intellisense, comes in. You might recall how we used it to discover things you can do with strings in one of my earliest articles, “C# Basics: Working with Strings“. This applies equally well here: as you begin to type your using statement to import the functionality you need from the library, Intellisense suggests the namespace for you:

cssharpziplib-intellisense-namespace

Now SharpZipLib has a lot of functionality that allows us to work with .zip files, .tar.gz files and more. In our case we just want to experiment with .zip files, so we’re fine with the following:

using ICSharpCode.SharpZipLib.Zip;

That thing is called a namespace: it contains a set of classes. If you type it into your Main() method and type in a dot (.) after it, you’ll get a list of classes in it:

cssharpziplib-intellisense-zip

A namespace is used to categorise a set of related classes so that they can’t be confused with other classes with the same name. Java’s Vector class (a kind of resizable array) is a typical example. If you create your own Vector class to represent a mathematical vector, then you might run into a naming conflict. However, since the Java Vector is actually in the java.util namespace, then its full name is actually java.util.Vector.

This works the same way in C#. The List class you’ve been using all along is called is actually called System.Collections.Generic.List. We usually don’t want to have to write all that, which is why we put in a using statement at the top with the namespace.

When we’re working with a new namespace, however, typing the full name and using Intellisense allows us to discover what that namespace contains, without the need to look at documentation. In the screenshot above, we can already guess that ZipFile is probably the class we need to work with .zip files.

Intellisense also helps us when working with methods, constructors and properties:

cssharpziplib-intellisense-constructor

I suppose you get the idea by now. Let’s finally actually get something working. To try this out, I’m going to create a zip file with the following structure:

+ test1.txt
+ folder
    + test2.txt
    + test3.txt

I’ve used WinRAR to create the zip file, but you can use anything you like. I named it “zipfile.zip” and put it in C:\ (you might need administrator privileges to put it there… otherwise put it wherever you like). Now, we can easily obtain a list of files and folders in the .zip file with the following code:

public static void Main(string[] args)
{
    using (ZipFile zipFile = new ZipFile(@"C:\\zipfile.zip"))
    {
        foreach (ZipEntry entry in zipFile)
        {
            Console.WriteLine(entry.Name);
        }
    }

    Console.ReadLine();
}

This gives us:

cssharpziplib-output-list

We use the using keyword to close the .zip file once we’re done – something we’ve been doing since my article “C#: Working with Streams“. You realise you need this whenever you see either a Dispose() or a Close() method in Intellisense. We are also using looping over the zipFile itself – you realise you can do a foreach when you see a GetEnumerator() method in Intellisense. Each iteration over the zipFile gives us a ZipEntry instance, which contains information about each item in the .zip file. As you can see in the output above, entries comprise not just files, but also folders.

Since we want to extract files, folders are of no interest for us. We can use the IsFile property to deal only with files:

if (entry.IsFile)
    Console.WriteLine(entry.Name);

In order to extract the files, I’m going to change the code as follows:

        public static void Main(string[] args)
        {
            using (ZipFile zipFile = new ZipFile(@"C:\\zipfile.zip"))
            {
                foreach (ZipEntry entry in zipFile)
                {
                    if (entry.IsFile)
                    {
                        Console.WriteLine("Extracting {0}", entry.Name);
                 
                        Stream stream = zipFile.GetInputStream(entry);
                        using (StreamReader reader = new StreamReader(stream))
                        {
                            String filename = entry.Name;
                            if (filename.Contains("/"))
                                filename = Path.GetFileName(filename);
                             
                            using (StreamWriter writer = File.CreateText(filename))
                            {
                                writer.Write(reader.ReadToEnd());
                            }
                        }
                    }
                }
            }
         
            Console.ReadLine();
        }

Note that I also added the following to work with File and Path:

using System.IO;

Extracting files involves a bit of work with streams. The zipFile’s GetInputStream() method gives you a stream for a particular entry (file in the .zip file), which you can then read with a StreamReader as if you’re reading a normal file.

I added a bit of code to handle cases when files are in folders in the .zip file – I am finding them by looking for the “/” directory separator in the entry name, and then extracting only the filename using Path.GetFileName(). [In practice you might have files with the same name in different folders, so you’d need to actually recreate the folders and put the files in the right folders, but I’m trying to keep things simple here.]

Finally, we read the contents of the entry using reader.ReadToEnd(), and write it to an appropriately named text file. If you run this program and go to your project’s bin\Debug folder in Windows Explorer, you should see the test1.txt, test2.txt and test3.txt files with their proper contents. [Again, the proper way to deal with streams is to read chunks into a buffer and then write the file from it, but I’m using reader.ReadToEnd() for the sake of simplicity.]

Excellent! In this article, we have learned to list and extract files from a .zip file. We also learned why namespaces are important. But most importantly, we have looked at how to reference third party .dlls and discover how to use them based only on hints from Intellisense and our own experience. In fact, the above code was written without consulting any documentation whatsoever, solely by observing the intellisense for SharpZipLib. While it is usually easier to just find an example on the internet (possibly in some documentation), you’ll find that this is a great skill to have when documentation is not readily available.

P2P Chat with Akka .NET using Akka.Remote

In this article, we’re going to develop a Peer-to-Peer (P2P) Chat application. This means that unlike the official Chat example, which has distinct Client and Server roles, each running instance of the application is exactly the same, except for configuration. The Akka.Remoting documentation explains that Akka.Remote is better suited for P2P applications rather than client/server.

In my typical style, I am keeping this example super simple so that we can focus on learning to message remote actors using Akka.Remote. I am still learning to use Akka .NET, so do not consider this article as an example of best practices.

The source code for this article is available at the Gigi Labs BitBucket repository.

NuGet Packages

Aside from the Akka package needed by all Akka .NET applications, we will also need the Akka.Remote package if we want to send messages to remote actors.

Install-Package Akka
Install-Package Akka.Remote

Configuration

If you’re going to use HOCON configuration from your App.config file, you need to declare a configSection for it:

  <configSections>
    <section name="akka" type="Akka.Configuration.Hocon.AkkaConfigurationSection, Akka" />
  </configSections>

You then set up Akka.Remote as follows:

  <akka>
    <hocon>
      <![CDATA[
        
        akka
        {
            actor
            {
                provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
            }

            remote 
            {
                helios.tcp
                {
                    port = 5248
                    hostname = localhost
                }
            }
        }
      
      ]]>
    </hocon>
  </akka>

The provider part is always the same, so you can just copy it. The helios.tcp section specifies the TCP endpoint on which the ActorSystem will listen for incoming connections, in this case localhost:5248.

For this particular example only, I am also going to include some AppSettings that we need in order to differentiate between different running instances of the chat application:

  <appSettings>
    <add key="actorSystemName" value="ChatPeer1" />
    <add key="remoteActorAddress" value="akka.tcp://ChatPeer2@localhost:5249/user/ChatActor" />
  </appSettings>

The actorSystemName setting has two purposes here.

  1. We will use it to display a different console title, so that we can distinguish between different running instances of the same application.
  2. We will actually give a different name to each running ActorSystem.

The remoteActorAddress setting, on the other hand, tells us the location of the remote chat actor. In this way, two running instances of the application will be able to connect and send messages to each other:

akka.remote-p2p-design

Typically you could just have one instance connect to the other, and the second communicates to the first via Sender.Tell() as in the Sending Messages to Remote Actors documentation. I arbitrarily chose not to do this to keep the application instances as symmetrical as possible (which is a typical trait of P2P applications).

Chat Application

Without further ado, here is the full code for the P2P Chat application within a console application’s Main() method:

            string actorSystemName = ConfigurationManager.AppSettings["actorSystemName"];
            Console.Title = actorSystemName;

            try
            {
                using (var actorSystem = ActorSystem.Create(actorSystemName))
                {
                    var localChatActor = actorSystem.ActorOf(Props.Create<ChatActor>(), "ChatActor");

                    string remoteActorAddress = ConfigurationManager.AppSettings["remoteActorAddress"];
                    var remoteChatActor = actorSystem.ActorSelection(remoteActorAddress);

                    if (remoteChatActor != null)
                    {
                        string line = string.Empty;
                        while (line != null)
                        {
                            line = Console.ReadLine();
                            remoteChatActor.Tell(line);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Could not get remote actor ref");
                        Console.ReadLine();
                    }
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex);
            }

From all this code, there are only two parts that are important to note. First, we are creating a local chat actor. This is what the remote actor will connect to in order to talk to the current instance of the application. It does this using the highlighted portion of code. It is simply getting a reference to the remote actor (using the address we specified in configuration) and locating it via an ActorSelection.

The ChatActor doesn’t do anything special. It simply writes whatever message it receives to the console:

    public class ChatActor : TypedActor, IHandle<string>
    {
        public ChatActor()
        {
            
        }

        public void Handle(string message)
        {
            using (var colour = new ScopedConsoleColour(ConsoleColor.White))
                Console.WriteLine(message);
        }
    }

It’s using the ScopedConsoleColour utility class from my Scope Bound Resource Management in C# article just to make received text look different from the text you type in:

    public class ScopedConsoleColour : IDisposable
    {
        private ConsoleColor oldColour;

        public ScopedConsoleColour(ConsoleColor newColour)
        {
            this.oldColour = Console.ForegroundColor;

            Console.ForegroundColor = newColour;
        }

        public void Dispose()
        {
            Console.ForegroundColor = this.oldColour;
        }
    }

Running the Application

We want to run two instances of the same application, but using different configuration. This not only allows us to recognise which is which, but also ensures that each instance can connect to the other at the right endpoint. The applications could run on the same machine or on different machines altogether.

The first instance will use configuration as shown earlier:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="akka" type="Akka.Configuration.Hocon.AkkaConfigurationSection, Akka" />
  </configSections>
    
  <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>

  <appSettings>
    <add key="actorSystemName" value="ChatPeer1" />
    <add key="remoteActorAddress" value="akka.tcp://ChatPeer2@localhost:5249/user/ChatActor" />
  </appSettings>
    
  <akka>
    <hocon>
      <![CDATA[
        
        akka
        {
            actor
            {
                provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
            }

            remote 
            {
                helios.tcp
                {
                    port = 5248
                    hostname = localhost
                }
            }
        }
      
      ]]>
    </hocon>
  </akka>
</configuration>

The second will use opposite configuration:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="akka" type="Akka.Configuration.Hocon.AkkaConfigurationSection, Akka" />
  </configSections>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>

  <appSettings>
    <add key="actorSystemName" value="ChatPeer2" />
    <add key="remoteActorAddress" value="akka.tcp://ChatPeer1@localhost:5248/user/ChatActor" />
  </appSettings>

  <akka>
    <hocon>
      <![CDATA[
        
        akka
        {
            actor
            {
                provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
            }

            remote 
            {
                helios.tcp
                {
                    port = 5249
                    hostname = localhost
                }
            }
        }
      
      ]]>
    </hocon>
  </akka>
</configuration>

When we run the two instances, each with its own configuration, we can actually have them send messages to each other:

akka.remote-chat-demo

Disconnecting

If we close the second instance, you’ll see that this does not go unnoticed by the first instance that is still running:

akka.remote-p2p-disconnect

However, if we run the second instance again, you can see that it recovers, and from then it’s business as usual:

akka.remote-p2p-reconnect

Further Reading

This article was really just a proof of concept to show how Akka.Remote works in practice. You might also want to check out:

  1. Akka.Remote Overview (official documentation)
  2. Sending Messages to Remote Actors (official documentation)
  3. Location Transparency (official documentation)
  4. Chat Example (official examples)

Dependency Injection in Akka .NET

If you’ve read yesterday’s article, “Actor Logging with Akka .NET“, you’ll know that Akka .NET is pretty flexible in terms of the logging frameworks it supports. It uses an adapter so you can pretty much plug in whatever logging framework you prefer.

Akka .NET’s approach to dependency injection is no different. Instead of imposing a particular framework or using its own, Akka .NET lets you plug in a selection of popular third party dependency injection frameworks and use them via a common interface.

The source code for this article is available at the Gigi Labs BitBucket repository.

Example Application

To show how to work with dependency injection (DI), we’ll set up a simple example. No need to get fancy here. All we need is a way to create a parent actor (directly from the ActorSystem) and child actor (from the parent actor). These should have a dependency injected in the constructor.

Here’s the interface for our dependency. I told you, nothing fancy.

    public interface ILazyAss
    {
        void DoNothing();
    }

Here’s the concrete implementation that implements this interface.

    public class SheriffBlake : ILazyAss
    {
        public void DoNothing()
        {
            
        }
    }

Before we start setting up our ActorSystem, we need to install the Akka NuGet package:

Install-Package Akka

Now, we need our actors. We don’t really care what they do, as long as they take the ILazyAss dependency so that we can show later that the DI works. Also, the parent actor creates a child actor – currently not using DI.

    public class ParentActor : ReceiveActor
    {
        public ParentActor(ILazyAss lazyAss)
        {
            Console.WriteLine("Parent Actor created!");

            var childActor = Context.ActorOf(
                Props.Create<ChildActor>(lazyAss), "ChildActor");
        }
    }

    public class ChildActor : ReceiveActor
    {
        public ChildActor(ILazyAss lazyAss)
        {
            Console.WriteLine("Child Actor created!");
        }
    }

We can now set up our ActorSystem:

        static void Main(string[] args)
        {
            using (var actorSystem = ActorSystem.Create("MyActorSystem"))
            {
                var lazyAss = new SheriffBlake();
                var actor = actorSystem.ActorOf(
                    Props.Create<ParentActor>(lazyAss), "ParentActor");

                Console.WriteLine("Press ENTER to exit...");
                Console.ReadLine();
            }
        }

Let us now run the code as is and see that it works:

akkanetdi-nodioutput

Setting up DI with Ninject

Like with logging, DI in Akka .NET involves installing the adapter NuGet package for the framework you want, and then configuring it as needed. I’m going to show how to do this with Ninject, but this is an arbitrary choice. Consult the Akka .NET Dependency Injection documentation for more information about how to set up other dependency injection frameworks. Packages for other frameworks not listed there also exist in NuGet.

akkanetdi-diadapters

So first, install the package you need:

Install-Package Akka.DI.Ninject

Next, we set up our IoC container, configure the dependencies we need to resolve, and set it up to work with the ActorSystem:

        static void Main(string[] args)
        {
            var container = new StandardKernel();
            container.Bind<ILazyAss>().To<SheriffBlake>();

            using (var actorSystem = ActorSystem.Create("MyActorSystem"))
            {
                var resolver = new NinjectDependencyResolver(container, actorSystem);

                var lazyAss = new SheriffBlake();
                var actor = actorSystem.ActorOf(
                    Props.Create<ParentActor>(lazyAss), "ParentActor");

                Console.WriteLine("Press ENTER to exit...");
                Console.ReadLine();
            }
        }

We now need to stop directly creating the dependency, and rely on the DI framework instead.

The catch to do this is that you need this funky DI() extension method, for which you need the following using statement:

using Akka.DI.Core;

This DI() extension method can be used from actor systems as well as actor contexts to create actors. Let’s change our actor system to use this, and get rid of the direct creation of our lazy sheriff:

        static void Main(string[] args)
        {
            var container = new StandardKernel();
            container.Bind<ILazyAss>().To<SheriffBlake>();

            using (var actorSystem = ActorSystem.Create("MyActorSystem"))
            {
                var resolver = new NinjectDependencyResolver(container, actorSystem);

                var actor = actorSystem.ActorOf(
                    actorSystem.DI().Props<ParentActor>(), "ParentActor");

                Console.WriteLine("Press ENTER to exit...");
                Console.ReadLine();
            }
        }

Similarly, we can rewire our ParentActor to create the ChildActor via DI (remember to add the using to get access to the DI() extension method):

    public class ParentActor : ReceiveActor
    {
        public ParentActor(ILazyAss lazyAss)
        {
            Console.WriteLine("Parent Actor created!");

            var childActorProps = Context.DI().Props<ChildActor>();
            var childActor = Context.ActorOf(childActorProps, "ChildActor");
        }
    }

And voilà:

akkanetdi-dioutput

Actor Logging with Akka .NET

In this article, we’re going to see how we can work with logging in Akka .NET. There is a logging adapter which allows one to work with various different logging providers (e.g. NLog), and it is very easy to use from within actors.

The source code for this article is available at the Gigi Labs BitBucket repository.

Example Application

Before we get to the details of how to use logging in Akka .NET, let’s create a very simple application. The first thing we need to do is install the Akka package:

Install-Package Akka

To work with basic Akka components, we need the following using:

using Akka.Actor;

We can now create a simple actor. This actor will just output whatever message (string) it receives:

    public class LoggingActor : ReceiveActor
    {
        public LoggingActor()
        {
            this.Receive<string>(s => Console.WriteLine(s));
        }
    }

Finally, we create our ActorSystem in Main() and send a message to the actor:

        static void Main(string[] args)
        {
            Console.Title = "Akka .NET Logging";

            using (var actorSystem = ActorSystem.Create("MyActorSystem"))
            {
                Console.WriteLine("ActorSystem created!");

                var actor = actorSystem.ActorOf(Props.Create<LoggingActor>(), "loggingActor");

                actor.Tell("Hello!");

                Console.WriteLine("Press ENTER to exit...");
                Console.ReadLine();
            }
        }

If we run this, we get the following output:

akkanetlogging-initialoutput

You can see that some of the output came from the Console.WriteLine()s we have in Main(); while the “Hello!” message came from the actor. But there is also a warning that is not coming from anywhere within our code.

StandardOutLogger

We can adjust our actor’s code to use a logger instead of writing directly to the console. The actor doesn’t care what kind of logger it is; this detail is entirely configurable. By default, it will use the StandardOutLogger which writes to the console. But we can use something else (e.g. NLog or Serilog) and the code would be completely unchanged.

    public class LoggingActor : ReceiveActor
    {
        private readonly ILoggingAdapter logger = Logging.GetLogger(Context);

        public LoggingActor()
        {
            this.Receive<string>(s => logger.Info(s));
        }
    }

If we run this, the “Hello!” message still gets written to the console, but it is now part of a longer formatted log message:

akkanetlogging-standardoutlogger

LogLevel

Just about all logging frameworks have a concept of log level. Typically these consist of at least Debug, Info, Warning and Error (some even have a Fatal level). You tell the logging framework what is the minimum level you’re interested in. So if your minimum level is Warning, the logging framework omits Debug and Info messages.

In Akka .NET, you can configure the minimum log level you’re interested in as part of the HOCON configuration within your App.config as follows:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <configSections>
    <section name="akka" type="Akka.Configuration.Hocon.AkkaConfigurationSection, Akka" />
  </configSections>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>

  <akka>
    <hocon>
      <![CDATA[ akka { loglevel = DEBUG } ]]>
    </hocon>
  </akka>

</configuration>

If we set loglevel to INFO, we get exactly the same as before. But now that we’ve set it to DEBUG, we actually get some additional logging from within Akka .NET:

akkanetlogging-debugoutput

Note: the screenshot actually contradicts what I was saying earlier about the StandardOutLogger. It actually seems to be replacing StandardOutLogger with this DefaultLogger. Presumably DefaultLogger uses StandardOutLogger underneath.

Automatic Logging

Akka .NET provides certain logging mechanisms out of the box. One of these is logging received messages (so we don’t even need to do that in code). You can turn on these mechanisms in the HOCON configuration as follows:

  <akka>
    <hocon>
      <![CDATA[
        akka
        {
          loglevel = DEBUG
          
          actor
          {
            debug
            {
              receive = on      # log any received message
              autoreceive = on  # log automatically received messages, e.g. PoisonPill
              lifecycle = on    # log actor lifecycle changes
              event-stream = on # log subscription changes for Akka.NET event stream
              unhandled = on    # log unhandled messages sent to actors
            }
          }
        }
      ]]>
    </hocon>
  </akka>

Now, to actually log received messages, you also need to make your actor implement the empty ILogReceive interface as per this StackOverflow question:

    public class LoggingActor : ReceiveActor, ILogReceive

If you run the application now, you’ll see that a lot more messages are being logged, including another entry for the “Hello!” message:

akkanetlogging-automaticlogging

Tip: ideally make sure the loglevel HOCON setting and the node under actor in HOCON (in this case debug) are in sync. If you set loglevel to INFO now, all the automatic logging will stop writing.

Integrating NLog

The logging adapter is particularly useful because you can swap out logging frameworks without having to touch the code. We are currently using the StandardOutLogger (or DefaultLogger?), but with some simple configuration, we can use NLog or some other provider instead.

The Akka .NET Logging documentation page shows the currently supported logging frameworks. Typically, you install a NuGet package for the framework you want, and set up its own configuration. I’m going to show you how to do this with NLog, but it’s an arbitrary choice, and the steps are similar for other logging frameworks.

1. Install the relevant NuGet package:

Install-Package Akka.Logger.NLog

2. Add an NLog.config to the project and configure it as you like:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <targets>
    <target name="file" xsi:type="File" fileName="test.log" />
  </targets>
  
  <rules>
    <logger name="*" minlevel="Info" writeTo="file" />
  </rules>
  
</nlog>

3. Right click NLog.config, Properties, then set to Copy always or Copy if newer:

akkanetlogging-copyalways

4. Update your HOCON to use the relevant logger:

  <akka>
    <hocon>
      <![CDATA[
        akka
        {
          loglevel = DEBUG
          loggers = ["Akka.Logger.NLog.NLogLogger, Akka.Logger.NLog"]
          
          actor
          {
            debug
            {
              receive = on      # log any received message
              autoreceive = on  # log automatically received messages, e.g. PoisonPill
              lifecycle = on    # log actor lifecycle changes
              event-stream = on # log subscription changes for Akka.NET event stream
              unhandled = on    # log unhandled messages sent to actors
            }
          }
        }
      ]]>
    </hocon>
  </akka>

Let’s run it now:

akkanetlogging-nlogoutput

You can see that the console output is now limited to what we’re writing in Main(), while the rest has gone into a file called test.log. Since our minlevel is Info, we’re not getting the automatic logging which is configured for the debug log level.

Secure Authentication with BCrypt

Introduction

Implementing authentication (i.e. user login) in a system sounds simple. Just compare username and password with what is stored in the database, right?

Actually, it’s not nearly as simple as it looks to the user logging in. Storing and checking user credentials is a process with different levels of security (and I’m no expert, so there may be more):

  1. Store passwords in plain text. Very bad idea.
  2. Hash the passwords. They won’t be easily readable, but can be cracked by rainbow tables.
  3. Salt and hash the passwords. Protects against rainbow tables as well, but still vulnerable to high-performance brute force attacks.
  4. Use a slow hash algorithm to limit the effectiveness of brute force attacks.

My article “Securing Passwords by Salting and Hashing” covers the first three items. This article will deal with the fourth item, and introduce BCrypt, which gives you all four.

The source code for this article is available at the Gigi Labs BitBucket repository.

Authentication with BCrypt

Before we discuss the merits of using BCrypt, let’s see how to use it.

You first need to include the BCrypt library in your project. You can do this via NuGet:

bcrypt-nuget

The functionality we need to use is all in a class called BCryptHelper, which you get access to by including the following namespace:

using DevOne.Security.Cryptography.BCrypt;

With that, it is very easy to generate a salt, hash a password with it, and validate the password against its salted hashed version:

        static void Main(string[] args)
        {
            Console.Title = "BCryptTest";

            string password = "My$ecureP@$sW0Rd";

            string salt = BCryptHelper.GenerateSalt();
            string hashedPassword = BCryptHelper.HashPassword(password, salt);

            bool valid = BCryptHelper.CheckPassword(password, hashedPassword);

            Console.WriteLine("Salt:            {0}", salt);
            Console.WriteLine("Hashed Password: {0}", hashedPassword);
            Console.WriteLine("Valid:           {0}", valid);

            Console.ReadLine();
        }

Here’s the output of this little program:

bcrypt-auth

The BCrypt hashed password is typically a 60-byte string. As you can see, the salt is actually embedded within the hashed password (this StackOverflow answer explains more about how this works). This means you don’t need to store the salt separately.

Why BCrypt?

The functionality we have seen in the previous section doesn’t really give us anything more than hashing and salting with any other reasonably strong hash function. So why use BCrypt?

In many programming situations, writing code that executes fast is a good thing. Authentication is not one of those. If the algorithms you use to authenticate your users are fast, that means that brute force attacks may attempt large amounts of combinations per second – more so with modern hardware and GPUs.

Algorithms such as PBKDF2 and BCrypt differ from traditional hash algorithms such as MD5 or SHA256 in that they take a work factor as an input. That is, you can decide how fast or slow the algorithm runs. So if, for instance, you set up your algorithm to take 1 second to validate a password, that greatly limits the possibilities of brute force attacks when compared to algorithms that can run several hundreds or thousands of times per second. Read more about why BCrypt is badass at this Security StackExchange answer.

In BCrypt, the GenerateSalt() method takes an optional logRounds parameter that affects the performance of subsequent hash operations. It has a default value of 10 and can be set to a number between 4 and 31. The algorithm will run 2 to the power of logRounds times, making it run exponentially slower. To get an idea of this, I wrote some simple benchmarking code with the help of my trusted ScopedTimer class (from “Scope Bound Resource Management in C#“):

        static void GenerateSaltBenchmarks(string password)
        {
            for (int i = 10; i < 16; i++)
            {
                using (var scopedTimer = new ScopedTimer($"GenerateSalt({i})"))
                {
                    string salt = BCryptHelper.GenerateSalt(i);
                    string hashedPassword = BCryptHelper.HashPassword(password, salt);
                }
            }
        }

Here are the results:

bcrypt-benchmark

Summary

Use BCrypt to securely store and validate your passwords. It’s easy to use, easy to store, and hard to break. Also importantly, you can make it as slow as you like.