August 8, 2020
Hot Topics:

Cryptographic Solutions for .NET Developers: Hashing and Encryption

  • By Jani Järvinen
  • Send Email »
  • More Articles »

Cryptography is an important part of many applications. Even if your application doesn't process credit card data or military information, it is likely that your application will need to store secrets such as usernames or passwords.

Cryptography allows you to store and transmit sensitive data in such a way that outsiders cannot read the data. Assume that you would need to send a password from a client application to a server over the Internet. Without cryptography, you would need to send the password in plaintext; in other words, fully readable. If somebody would listen to the network traffic, he or she could easily steal your password.

Luckily, mathematics and cryptography help you make the job of the malicious listener much more difficult. With the process known as encryption, you could convert the password into non-intelligible data known as ciphertext, and make it very hard to convert it back to the plaintext version.

Another tool is hashing. Hashing is way to calculate a fixed-length "fingerprint," the hash, of some input data in such a way that no two inputs produce the same output (hash value). This means that each time the input changes, the hash changes as well. Also, the hash is always of fixed length, and is not related to the input length.

There are different ways to encrypt and hash data. Different algorithms are needed because there are diverse needs for encryption and hashing. Sometimes you want to be as secure as possible, but sometimes you want to trade a little security with encryption speed or simplicity, for example. The names of these algorithms are often short acronyms. For example, some of the most common algorithms are named RC2, RSA, AES, and SHA.

.NET Support for Encryption and Hashing

The .NET Framework contains extensive support for cryptographic needs, and in this article you will learn basic encryption and hashing along with C# code examples. Before firing up Visual Studio, you should first understand some of the most common needs for cryptography.

One common need is to store or send information in encrypted format to keep your data out of prying eyes. For example, you might want to transmit accounting information from one machine to another, or store sensitive sales data in a database. Encryption would help here.

Secondly, you might need to store a password in your applications. This need can be twofold: You could either have the need to access other systems, or you might need to verify that a user's password is correct while he logs in to your application. In these cases, you could use both encryption and hashing.

Most classes in the .NET Framework related to cryptography can be found from the System.Security.Cryptography namespace. From this namespace, you can find classes that implement many common cryptography algorithms, such as AES, RSA, SHA, and MD5. All the implementation classes inherit from certain abstract base classes, such as SymmetricAlgorithm, AsymmetricAlgorithm, and HashAlgorithm.

To use these implementation classes, you first need to be able to select the correct algorithm for your needs. For example, to use password-based encryption, select symmetric encryption algorithms such as AES or RC2. Or, if you prefer asymmetric algorithms needing both public and private keys, select RSA, the only option in the basic class library. For hashing purposes, you could select MD5 or SHA, for instance.

Because many parts of the .NET Framework work with streams, it is not surprising to find that the cryptographic classes also can utilize streams. Speaking of streams, there's a special class called CryptoStream, which is very central to using cryptography in .NET. You will become familiar with this class when you look at the example application in the next section.

Example of Encryption with RC2

I've written two sample applications using .NET cryptography that work as a pair: RC2Encrypt and RC2Decrypt. These applications are simple console applications that take a filename and a password as input, and then encrypt or decrypt the given file with the RC2 algorithm. RC2 is the name of one of those encryption algorithms that .NET supports. You can download both these sample applications.

Console application parameter handling aside, the most interesting method in the encrypting application is the EncryptFile method, shown here:

using System.IO;
using System.Security.Cryptography;

private static void EncryptFile(string filename, string password)
   // parameter checks
   bool ok = CheckParameters(filename, ref password);
   if (!ok) return;
   // start encrypting the file
   RC2 rc2 = RC2.Create();
   byte[] initvector = new byte[8] { 83, 123, 28,
                                     95, 70, 231, 117, 156 };
   byte[] key = System.Text.Encoding.ASCII.GetBytes(password);
   string outputFilename = Path.ChangeExtension(filename, "rc2enc");
   ICryptoTransform transform = rc2.CreateEncryptor(key, initvector);
   FileStream input = null;
   FileStream output = null;
   CryptoStream crypto = null;
      input = new FileStream(filename, FileMode.Open);
      output = new FileStream(outputFilename, FileMode.Create);
      crypto = new CryptoStream(output, transform,
      // encrypt file data
      CopyStream(input, crypto);
      if (crypto != null) crypto.Close();
      if (output != null) output.Close();
      if (input  != null) input.Close();
   Console.WriteLine("File encrypted.");

The EncryptFile method takes a filename (with an optional path) and a password as parameters, creates classes to help in the encryption process, and then copies the input stream (the source file) to the output stream (the output file). Walk through the code.

After initial parameter checks (such as that the file exists), two byte arrays are created: one for the so-called key, and another for the initialization vector (or iv for short). These two-byte sequences are very important in the cryptography process: Unless the combination of both the key and the initialization vector are exactly the same when encrypting and decrypting, the decryption of the previously encrypted data won't work and you might get a CryptographicException with the message "Bad data." Thus, it is important to keep both known when you attempt decryption.

Now, take a look at the code inside the try block in the listing. Here, two file streams are initialized, one for the input file (plaintext) and another for the to-be-created ciphertext file; in other words, the encrypted file. Thirdly, an instance of the CryptoStream class is created.

The CryptoStream is a special stream class that needs a stream object, a transformation, and a mode that tells whether the given stream should be read or written. Of these parameters, the transformation requires the most thought. Simply put, it is the encryption algorithm that you want to use to encrypt the data. This parameter is needed because CryptoStream can be used with many different algorithms, not just one.

Page 1 of 3

This article was originally published on July 27, 2007

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date