14.7 Derive a Symmetric Encryption Key from a Password


Problem

You need to generate a symmetric encryption key from a password so that users can easily remember their keys and don't need to store them.

Solution

Use the class System.Security.Cryptography.PasswordDeriveBytes to create a symmetric encryption key from a string.

Discussion

It's impossible for all but the most exceptional of people to remember the value of a symmetric key, and it's impractical to expect users to enter such lengthy numbers manually. This means that keys must be stored in a secure form that's accessible to applications. Usually this means storing keys on a smart card, floppy disk, or in a database or file. The problem associated with assigning, distributing, accessing, and storing keys is one of the most difficult aspects of implementing any cryptographic solution ”a problem collectively referred to as key management . As soon as you need to record a secret (the key), you have to concern yourself with not only protecting your data, but also protecting the secrets used to protect the data!

One alternative to storing a key is to assign the user a more easily remembered password (or pass phrase) and use a key derivation protocol to create a symmetric key from the password. Then, whenever the user needs to encrypt or decrypt data, the user simply enters the password and the computer generates the correct key. As long as the user enters the same password, the key derivation protocol will generate the same key.

Note  

ImportantDeriving keys from memorable words and phrases significantly reduces the randomness of the keys, which in turn reduces the security provided by any cryptographic function that uses those keys. This is the tradeoff you must make for simplicity. In the worst-case scenario, it's feasible that a hacker could guess a poorly chosen password, saving them the time and effort of cracking your data through cryptanalysis.

The .NET Framework class library includes one symmetric key derivation implementation: PasswordDeriveBytes . The PasswordDeriveBytes class uses a hashing algorithm applied repeatedly to a password to generate a key of the desired length. When configuring a PasswordDeriveBytes object, you can specify which of the .NET hashing algorithms to use as well as the number of repetitions to perform ”the default is SHA-1 applied 100 times. In addition, you should provide something called salt . Salt is random data that the key derivation process uses to make the derived key more resilient to certain forms of cryptographic attack. You don't need to keep the salt value secret; you must store it and use it when deriving the key from the password in the future. Without the correct salt value, you won't be able to derive the correct key and you won't be able to decrypt your encrypted data.

Note  

You can't create asymmetric encryption keys using a key derivation protocol. Asymmetric encryption algorithms rely on specific mathematical relationships between their public and private key components . As such, each asymmetric encryption algorithm requires you to follow a specific process to generate new keys.

The following example demonstrates the use of the PasswordDeriveBytes class to generate a 64-bit symmetric key from a password string. The example requires two command-line arguments. The first is the name of the hashing algorithm to use when generating the key, and the second is the password to use as input to the key derivation process. The supported hashing algorithm names are listed in Table 14.1.

 using System; using System; using System.Security.Cryptography; public class DerivedKeyExample {     public static void Main(string[] args) {                  // Use a cryptographic random number generator to create          // the salt used to seed the derivation algorithm.         byte[] salt = new byte[8];  RandomNumberGenerator.Create().GetBytes(salt);  // Create a PasswordDeriveBytes object to generate the          // key from the password. Supply the source password, which         // is the second command line argument, and the salt.         PasswordDeriveBytes pdb =              new PasswordDeriveBytes(args[1], salt);         // Set the hashing algorithm used to generate the key, the          // algorithm name is specified by the first command line argument.         // The default algorithm used is SHA-1.         pdb.HashName = args[0];         // Set the number of iterations to 200. This controls the number         // of times the hashing algorithm is applied to the password in          // order to generate the key. The default is 100.         pdb.IterationCount = 200;                  // Generate an 8 byte (64 bit) key from the password         // The strength of the key is limited by the length         // of the hash code - 160 bits for SHA-1.         byte[] key = pdb.GetBytes(8);                  // Display the key and salt to the console.         Console.WriteLine("Key  = {0}", BitConverter.ToString(key));         Console.WriteLine("Salt = {0}", BitConverter.ToString(salt));     } } 

Running the command DerivedKeyExample SHA1 S0meVereeStr@ngeP@$$w0rd uses the SHA-1 hashing algorithm to derive an 8-byte (64-bit) key from the string "S0meVereeStr@ngeP@$$w0rd". The output will look similar to this:

 Key  = 53-72-74-5B-A4-88-A4-80 Salt = 70-82-79-F4-3B-F9-DF-D2 

Notice that each time you run the same command, DerivedKeyExample produces a different key; this is the effect of the salt. If you comment out the code that assigns a random value to the salt array (in boldface in the code listing), and then recompile and run DerivedKeyExample, you will find that the example always generates the same key for a given password.




C# Programmer[ap]s Cookbook
C# Programmer[ap]s Cookbook
ISBN: 735619301
EAN: N/A
Year: 2006
Pages: 266

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net