SECURITY

Programming .NET Security : Programming Cryptographic Keys (part 1) - Creating Keys

3/19/2011 4:58:11 PM
1. Creating Keys

In the following sections, we discuss three techniques for creating keys. Only one of these techniques presents the user with data that is easy to memorize. You must be pragmatic when deciding how to create new keys, and select a process that satisfies the security demands of your project and the practical demands of the users.

1.1. Using the algorithm classes

The simplest way to create keys is to use the functionality built into all of the .NET algorithm classes for both symmetric and asymmetric algorithms. The .NET classes creates new keys as they are needed; if you attempt to perform any cryptographic operation and you have not explicitly specified the keys to use, then the .NET classes will create new keys automatically. The following statements demonstrate how to use this functionality to print out the key value for a symmetrical algorithm:

# C#

// create an instance of the symmetric algorithm
SymmetricAlgorithm x_alg = SymmetricAlgorithm.Create("Rijndael");

// set the length of key that we want to create
x_alg.KeySize = 128;

// get the key value, which will cause the implementation
// class to create a new secret key
byte[] x_secret_key = x_alg.Key;

// print out the key
foreach (byte b in x_secret_key) {
Console.Write("{0:X2} ", b);
}

# Visual Basic .NET

' create an instance of the symmetric algorithm
Dim x_alg As SymmetricAlgorithm = SymmetricAlgorithm.Create("Rijndael")

' set the length of key that we want to create
x_alg.KeySize = 128

' get the key value, which will cause the implementation
' class to create a new secret key
Dim x_secret_key As Byte( ) = x_alg.Key

' print out the key
Dim b As Byte
For Each b In x_secret_key
Console.Write("{0:X2} ", b)
Next b


The following statements demonstrate how to create a new key and print out the value for an asymmetric algorithm; unlike most asymmetric functions, obtaining details of the key can be performed through the abstract AsymmetricAlgorithm class :

# C#

// create an instance of the asymmetric algorithm
AsymmetricAlgorithm x_alg = AsymmetricAlgorithm.Create("RSA");

// set the length of key that we want to create
x_alg.KeySize = 1024;

// get the key value, which will cause the implementation
// class to create a new secret key
string x_key_pair = x_alg.ToXmlString(true);

// print out the key
Console.WriteLine(x_key_pair);

# Visual Basic .NET

' create an instance of the asymmetric algorithm
Dim x_alg As AsymmetricAlgorithm = AsymmetricAlgorithm.Create("RSA")

' set the length of key that we want to create
x_alg.KeySize = 1024

' get the key value, which will cause the implementation
' class to create a new secret key
Dim x_key_pair As String = x_alg.ToXmlString(True)

' print out the key
Console.WriteLine(x_key_pair)

The principal benefit of creating keys in this manner is that you do not have to have any prior knowledge about how the key should be created; the algorithm class is responsible for creating keys in accordance with the relevant specification. The principle drawback is that the .NET classes generate keys that users will find difficult to remember.

When using an algorithm class to create a new key, you must be confident that the implementation creates keys securely and there are no flaws in the implementation that might result in key values that are easily guessed.


1.2. Using a random number generator

The second approach to creating keys is to use a random number generator (RNG). The .NET Framework provides support classes for generating random data; Figure 1 illustrates the class hierarchy.

Figure 1. The.NET Framework class hierarchy for random number generators

You cannot generate random data to create a key pair for an asymmetric algorithm. You must rely on the implementation classes to create key pairs or follow the appropriate key generation protocol. Asymmetric algorithms create keys using numbers that are mathematically related and cannot be created from random data.


The class hierarchy for random number generators follows the abstract class/implementation class model that is used for hashing algorithms and symmetrical algorithms. The .NET Framework includes one implementation class, which is a wrapper around the RNG functions of the native Windows Cryptography API. Table 1 details the public members of the abstract RandomNumberGenerator class.

Table 1. Members of the RandomNumberGenerator class
Member Description
Create Creates an instance of a RandomNumberGenerator implementation class by name or creates an instance of the default implementation class if no name is specified
GetBytes Populates a byte array with a sequence of random values
GetNonZeroBytes Populates a byte array with a sequence of random values, none of which will be 0

You must know how many bytes of random data to create to prepare a key for a given algorithm correctly. The following statements demonstrate how to use the random number generator to create a key for a symmetric algorithm:

# C#

// create an instance of the symmetric algorithm
SymmetricAlgorithm x_alg = SymmetricAlgorithm.Create("Rijndael");

// set the length of key that we want to create
x_alg.KeySize = 128;

// we need to create an array of 16 bytes (16 bytes is 128 bits)
byte[] x_key_data = new byte[16];

// create the RNG
RandomNumberGenerator x_rng = RandomNumberGenerator.Create( );

// use the RNG to populate the byte array with random data
x_rng.GetBytes(x_key_data);

// set the key value for the symmetrical algorithm
x_alg.Key = x_key_data;

# Visual Basic .NET

' create an instance of the symmetric algorithm
Dim x_alg As SymmetricAlgorithm = SymmetricAlgorithm.Create("Rijndael")

' set the length of key that we want to create
x_alg.KeySize = 128

' we need to create an array of 16 bytes (16 bytes is 128 bits)
Dim x_key_data(15) As Byte

' create the RNG
Dim x_rng As RandomNumberGenerator = RandomNumberGenerator.Create( )

' use the RNG to populate the byte array with random data
x_rng.GetBytes(x_key_data)

' set the key value for the symmetrical algorithm
x_alg.Key = x_key_data


1.3. Using a key-derivation protocol

The previous two approaches result in values that a user will find difficult to remember. Users tend to prefer key values that have some meaning, but keys made up of proper words do not make ideal cryptographic keys; they are more susceptible to brute force attacks, because not all key values are equally likely when we are restricted to alphanumeric values listed in a dictionary.

A key-derivation protocol is a compromise between the need to create keys that are difficult to guess and the need for users to remember the key values. This kind of protocol processes a password selected by the user to create a cryptographic key. The user remembers the password, and types it in (rather than a sequence of numeric values). The derivation protocol transforms the password into a cryptographic key. The .NET Framework supports one key-derivation protocol, which is based on the PKCS #5/PBKDF1 standard. We summarize the protocol, as follows:

  1. Alice selects a password. The password can be made up of more than one word—for example, "Programming .NET Security" would be acceptable as a password; though the word "password" is used, "pass phrase" is more appropriate.

  2. Alice generates eight bytes of random data, known as the salt. The salt value is not secret, and Alice can safely write it down. The benefit of adding random data to the password is that two users who select the same password will end up with different cryptographic keys.

  3. Alice concatenates her password and the salt data together to form the data block.

  4. Alice selects a hashing algorithm and creates a hash code for the data block.

  5. For a specified number of iterations, Alice uses the hashing algorithm to create a new hash code, using the previous hash code as the input. The first hash code is produced by hashing the data block. The second hash code is produced by hashing the first hash code. The third hash code is created by hashing the second hash code, and so on. It is common to perform 100 iterations.

  6. Alice uses the first n bytes of the final hash code to create a cryptographic key of 8n bits. For example, if Alice selected the SHA-1 hashing algorithm, she will acquire a hash code that is 20 bytes long (because SHA-1 produces 160-bit hash codes). If Alice required a 128-bit key, she will use the first 16 bytes of the hash code value.

Key-derivation protocols are deterministic, meaning that they will always create the same cryptographic key when supplied with specific password and salt values. Keys derived from passwords are suitable for symmetric algorithms, but asymmetric algorithms require you to follow the appropriate key-generation protocol to create new key pairs. Keys that are derived in this way are not as secure as those created from random data, and the password should be chosen so that it is difficult to guess.

Figure 2 illustrates the .NET Framework class hierarchy for derivation protocols. The PasswordDerivedBytes class implements the protocol we described; the members of this class are listed in Table 2.

Figure 2. The .NET Framework class hierarchy for byte derivation schemes

Table 17-2. PasswordDeriveBytes Members
Member Description
Properties  
HashName The name of the hashing algorithm to use; 
IterationCount The number of iterations to perform to create the final hash code
Salt A byte array representing the salt data
Methods  
GetBytes Creates the final hash code and returns a number of bytes, specified as an integer method argument

The following statements demonstrate how to use the PasswordDeriveBytes class to derive a key using "Programming .NET Security" as the password; the password and the salt value are specified in the class constructor:

# C#

// create the random salt value
byte[] x_salt = new byte[8];
RandomNumberGenerator x_rand = RandomNumberGenerator.Create( );
x_rand.GetBytes(x_salt);

// create the derivation protocol class
PasswordDeriveBytes x_pwd
= new PasswordDeriveBytes("Programming .NET Security", x_salt);
// specify the number of iterations
x_pwd.IterationCount = 100;
// specify the hashing algorithm
x_pwd.HashName = "SHA1";

// create the key
byte[] x_key = x_pwd.GetBytes(16);

// write out the salt value
Console.Write("SALT: ");
foreach (byte b in x_salt) {
Console.Write("{0:X2} ", b);
}
Console.WriteLine( );

// write out the key value
Console.Write("KEY: " );
foreach (byte b in x_key) {
Console.Write("{0:X2} ", b);
}
Console.WriteLine( );

# Visual Basic .NET

' create the random salt value
Dim x_salt(7) As Byte
Dim x_rand As RandomNumberGenerator = RandomNumberGenerator.Create( )
x_rand.GetBytes(x_salt)

' create the derivation protocol class
Dim x_pwd As PasswordDeriveBytes _
= New PasswordDeriveBytes("Programming .NET Security", x_salt)

' specify the number of iterations
x_pwd.IterationCount = 100
' specify the hashing algorithm
x_pwd.HashName = "SHA1"

' create the key
Dim x_key( ) As Byte = x_pwd.GetBytes(16)

' write out the salt value
Dim b As Byte
Console.Write("SALT: ")
For Each b In x_salt
Console.Write("{0:X2} ", b)
Next
Console.WriteLine( )

' write out the key value
Console.Write("KEY: ")
For Each b In x_key
Console.Write("{0:X2} ", b)
Next
Console.WriteLine( )

Other  
 
Top 10
Review : Sigma 24mm f/1.4 DG HSM Art
Review : Canon EF11-24mm f/4L USM
Review : Creative Sound Blaster Roar 2
Review : Philips Fidelio M2L
Review : Alienware 17 - Dell's Alienware laptops
Review Smartwatch : Wellograph
Review : Xiaomi Redmi 2
Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
REVIEW
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
VIDEO TUTORIAL
- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
Popular Tags
Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8