Click here to Skip to main content
15,891,136 members
Articles / Programming Languages / C#
Article

Deriving Encryption Keys From Passwords

Rate me:
Please Sign up or sign in to vote.
2.50/5 (6 votes)
25 Jul 2005CPOL1 min read 37.1K   14   3
Show how to generate and store your keys for cryptography in safe mode

Introduction

This article shows you how you can derive secure and strong keys for encryption in symmetric algorithms.

I assume you have knowledge on cryptography. You can read a good introductory article on encryption here.

Deriving a Key from a Password

Suppose you want to encrypt sensitive information of users of your application. You don't want anybody to be able to decrypt this data. So you decide to encrypt using Rijndael, a good symmetric algorithm. But Rijndael needs at least a 128 bit key. You also want to store this key in a secure environment.

I have written a complementary class to the EncDec described in this article.

This class generates Keys and IV, derives them from passwords, and stores them in a secure manner.

Here is the full implementation:

C#
using System.Security.Cryptography;
public sealed class GenKeys
{
   /// <summary>
   /// Derive a key suitable for use in symmetric algorithms.
   /// </summary>
   /// <param name="password">a password in plain text, perhaps an easy
   /// to remember one
   /// </param>
   /// <param name="size">The size in BITS of the key</param>
   /// <returns>A key for use in encryption</returns>
   public static byte[] DeriveKeyFromPassword(string password, int size)
   {
      return DeriveKey(password, GenSalt(8), size/8);
   }

   /// <summary>
   /// Generate an IV (Initialization Vector) for use in Rijndael crypto
   /// algorithm
   /// </summary>
   /// <param name="size">size in bits of the vector</param>
   /// <returns>a new array o bytes with a random generated IV</returns>
   public byte[] GenIV(int size)
   {
      return GenSalt(size/8);
   }

    /// <summary>
    /// Generate a salt array, this is a vector of bytes used for the
    /// generation of strong keys.
    /// This method is used internally by DeriveKeyFromPassword()
    /// </summary>
    /// <param name="size">Size in bytes (watch out)</param>
    /// <returns>an array of random bytes of size bytes</returns>
    private static byte[] GenSalt(int size)
    {
      /// Use a cryptographic random number generator
      RandomNumberGenerator rng = RandomNumberGenerator.Create();
      // create the result array and fill it with non-zero bytes
      byte[] result = new byte[size];
      rng.GetNonZeroBytes (result);
      return result;
    }

    /// <summary>
    /// Derive a key form a password. This internally used by DeriveKeyFromPassword
    /// This is an advanced implementation, when you know how to generate
    /// a salt array
    /// </summary>
    /// <param name="password">A password, perhaps human readable and
    /// easy to remember </param>
    /// <param name="salt">A salt array used to generate a password</param>
    /// <param name="size">the size in bytes of the key</param>
    /// <returns>a key of size bytes</returns>
    private static byte[] DeriveKey(string password, byte[] salt, int size)
    {
        PasswordDeriveBytes pder = new PasswordDeriveBytes(password, salt);
        pder.IterationCount = 100;
        pder.HashName = "SHA1";
        return pder.GetBytes (size);
     }
}

Now you can use this class with EncDec in this way:

C#
byte[] iv = GenKeys.GenIV(128);
byte[] key = GenKeys.DeriveKeyFromPassword("my own private password", 128);
byte[] data = {......};
EncDec.Encrypt(data, key, iv) 

EncDec has methods that use PasswordDerivedBytes class, but in the implementation, the salt is hard coded. Using GenKeys class, you can generate and store the keys outside your program.

One trick is to use an automatic generated password, for example the MAC address of your Ethernet card and use it for deriving a password, then generate the IV deriving from another automatically generated, like the CPU ID, size of your executable, the primary Key of a record in a table, etc.

The Search of a Secure Key Storage

I will start writing in my blog about this topic, and I will investigate ways to store the generated keys in a safe manner.

I will update this article when my investigations give acceptable results.

See you soon.

Visit my blog here.

History

  • 25th July, 2005: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Chile Chile
Eduardo Diaz
personal blog

Comments and Discussions

 
QuestionThe search of a secure key storage Pin
Hal_HDLCS11-Nov-05 10:19
Hal_HDLCS11-Nov-05 10:19 
QuestionIs it Thread Safe? Pin
sunny_abdullah27-Aug-05 0:45
sunny_abdullah27-Aug-05 0:45 
AnswerRe: Is it Thread Safe? Pin
ediazc27-Aug-05 7:40
ediazc27-Aug-05 7:40 
As far I know this class is thread safe.
I have no tested, but if you read the code, nothing suggest is not thread safe. Off course its depends on .net Libraries, we have to test.

Eduardo Diaz



Dark Side Programming"

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.