Developing with the Cryptography Application Block


The previous sections described the technologies used in the Cryptography Application Block and how it has been designed to subscribe to cryptography best practices. You also saw that, even though it is rarely wise to do so, custom symmetric and hashing algorithms can be created and used by the Cryptography Application Block. This section details how to configure and develop an application to take advantage of the Cryptography Application Block.

Adding the Cryptography Application Block

The first step to using the Cryptography Application Block is to add it to the configuration sections in an application. The easiest and least errorprone way to accomplish this is to add a new Cryptography Application Block in the Enterprise Library Configuration Tool.

In the Configuration Tool, rightclick on the application node and select New > Cryptography Application Block. This generates a Cryptography Application Block subtree with further subtrees for HashProviders and SymmetricProviders. It also creates a configuration node named securityCryptographyConfiguration in the Configuration Application Block. Figure 8.6 depicts the resulting hierarchy.

Figure 8.6. Hierarchy of the Cryptography Application Block


Encrypting/Decrypting Data

At least one SymmetricProvider must be configured to use the Cryptography Application Block to encrypt and decrypt data. To add a SymmetricProvider, rightclick on the Symmetric Providers node and select one of the providers: Custom Symmetric Cryptography Provider, DPAPI SymmetricCryptographyProvider, or SymmetricAlgorithmProvider. The option to create a custom symmetric provider is for enterprises that have applications that may need to do something other than leverage the underlying symmetric algorithm or DPAPI to encrypt and decrypt data. I have not seen this used anywhere, so I will focus on how to configure the DPAPI Symmetric Cryptography and SymmetricAlgorithmProviders that come with Enterprise Library.

The DpapiSymmetricCryptographyProvider

When you add a DpapiSymmetricCryptographyProvider to an application's configuration data, the Enterprise Library Configuration Tool displays the Data Protection Configuration dialog. This eases the process for configuring the DpapiSymmetricCryptographyProvider. This dialog lets you select the DPAPI mode as either user or machine. If you select machine mode, the dialog automatically adds the entropy to be used for its calls to CryptProtectData and CryptUnprotectData.

Figure 8.7 shows how to use the Data Protection Configuration dialog to set the DPAPI mode to machine mode and generate an entropy value. This value for the entropy is editable, so you can change it when it is created or at a later date by selecting the DataProtectionMode property for the DpapiSymmetricCryptographyProvider. However, if any data is encrypted before this setting is modified, it will not be able to be decrypted. So, unless there is a really good reason for modifying this value, it is probably better to accept the entropy that is automatically generated.

Figure 8.7. Configuring a DpapiSymmetricCryptographyProvider


SymmetricAlgorithmProvider Configuration

The Enterprise Library Configuration Tool also makes it easy to configure an application to use with one of the .NET Framework's symmetric algorithms (or one that derives from System.Security.Cryptography.SymmetricAlgorithm). A wizard guides you through the process of selecting a symmetric algorithm and corresponding key. When you select one of the SymmetricAlgorithmProviders that exists, the Enterprise Library Configuration Tool displays the Type Selector dialog. This dialog displays a list of all classes that it knows derive from the SymmetricAlgorithm class.

If you are not sure which algorithm to choose, the RijndaelManaged algorithm is usually a pretty good choice because it possesses the greatest key length of all the available providers. It is also the Advanced Encryption Standard accepted by the United States Federal Government in 2001 (the previous standard was DES). Figure 8.8 shows how to use the Type Selector dialog to select a SymmetricAlgorithmProvider.

Figure 8.8. Selecting the RijndaelManaged SymmetricAlgorithmProvider


Next you create an encryption key for the algorithm provider to use. The dialog lets a key either be imported or automatically generated by leveraging the helper methods in the CryptographyUtility class for generating cryptographically strong keys. Figure 8.9 shows the Key Creation dialog that is used to accomplish this.

Figure 8.9. Adding a Key for the SymmetricAlgorithmProvider


After the key has been created, it is hidden in the Enterprise Library Configuration Tool for security reasons. That is, it cannot be edited with the tool. To modify the key with the tool, a new instance of the algorithm provider has to be created to use in place of the existing one. Alternatively, the key can be exported to a file that can be password protected. Figure 8.10 shows that by clicking on the Key property in the Configuration Tool, the encryption key can be exported.

Figure 8.10. Key Modification Options


This is not to say that the key value cannot be modified at all or to imply that it is extremely secured. It can be modified, and it is not secured. The key value is stored in cleartext in the StorageProvider's data store. For example, if the XMLFileStorageProvider is used to store the configuration settings for the Cryptography Application Block, the key can generally be located in the securityCryptographyConfiguration.config file.

To encrypt this key value, encryption needs to be enabled in the Configuration Application Block. This need for encryption in the Configuration Application Block is the reason why many of the cryptography methods that are used by the Cryptography Application Block actually reside in the Common namespace. A circular dependency would occur if the Configuration Application Block depended on the Cryptography Application Block for cryptographic functions, while the Cryptography Application Block depended on the Configuration Application Block to get its configuration data.

To enable the encryption of configuration data, a Key Algorithm StorageProvider needs to be added to the Configuration Application Block. Enterprise Library ships with a FileKeyAlgorithmStorageProvider that lets you specify a single algorithm and key (i.e., a master key) for encrypting all configuration data. You add this key by rightclicking on the Encryption Settings configuration node in the Configuration Application Block and selecting a new FileKeyAlgorithmStorageProvider. Then, as depicted in Figure 8.11, a wizard will guide you through the process of either loading an existing keyalgorithm pair or creating a new one.

Figure 8.11. Creating a New FileKeyAlgorithmStorageProvider in the Configuration Application Block


If creating a new master key, the wizard next prompts you with the same Type Selector dialog that is used to select a Symmetric Algorithm in the Cryptography Application Block. After you select the algorithm provider, the wizard prompts you to select a file to use for saving this keyalgorithm pair and provides the opportunity to protect the file using DPAPI. Figure 8.12 shows this dialog. If you choose to load the master key from an existing file instead of creating a new one, the wizard skips over the Type Selector dialog and goes right to the step shown in Figure 8-12. The master key is stored in the file that is created or selected in cleartext.

Figure 8.12. Saving the Master Key


This may make you wonder whether the problem has not really been solved but just moved to a different file. From one perspective, the problem has just been moved because the master key exists as cleartext. However, because this single key file can now be used to encrypt all of the configuration data for an application, DPAPI can be used to help protect it. This is the first step toward better key management. Key management is the most challenging part of cryptography. Howard and LeBlanc devote a great deal of time to this subject.[5]

[5] Writing Secure Code, Second Edition, pp. 272281.

Combining DPAPI (described earlier in this chapter) with ACLs could protect the single master key, while all other keys and data remain protected using the symmetric algorithm used when the FileKeyAlgorithmStorageProvider was configured. If the part of the application that uses the master key must be distributed to multiple machines, then straight ACLs might have to do. Another option available in Windows 2000 and later is the Encrypted File System (EFS), which encrypts and provides tamper detection for files.

Once the master key has been created, all configuration data for all blocks can be encrypted very easily. To encrypt the configuration data for a block, the Encrypt property for that application block's configuration settings needs to be set to true. Figure 8.13 shows how to switch the Encrypt flag to true for the Cryptography Application Block.

After the configuration data for the application block has been set to encrypted, the data is no longer stored in cleartext. For example, encrypting the settings shown in Figure 8.13 turns the cleartext shown in Listing 8.4 into the output shown in Listing 8.5.

Figure 8.13. Turning Encryption On for an Application Block


Because this is a setting in the configuration for an application block and not dependent in any way on the use of the Cryptography Application Block, configuration data for any application block can be encrypted. That is, the capability to encrypt the configuration data is not isolated to cryptographic keys; it can and should be used for any configuration data for any application block.

The EncryptSymmetric Method

Once a symmetric algorithm has been configured for an application, encrypting data becomes simple. You can use the Cryptographer's static EncryptSymmetric method to encrypt data by passing in the name of the SymmetricAlgorithmProvider and either a base64encoded string or byte array to encrypt. In the first instance, the EncryptSymmetric method returns a base64encoded string that represents the ciphertext; in the second instance it returns an array of bytes that represent the ciphertext. Listing 8.6

Listing 8.4. Custom Symmetric Algorithm

[View full width]

<?xml version="utf-8"?> <securityCryptographyConfiguration>   <xmlSerializerSection type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography. Configuration.CryptographySettings, Microsoft.Practices.EnterpriseLibrary.Secu:     <enterpriseLibrary.securityCryptographySettings xmlns:xsd="http://www.w3.org/2001 /XMLSchema" xmlns:sxi="http://www.w3.2001/XMLSchema-instance" xmlns="http://www       <hashProviders />       <symmetricCryptoProviders$gt;         <symmetricCryptoProvider xsi:type="DpapiSymmetricCryptoProviderData" name="DPAPI  Symmetric Cryptography Provider">           <dpapiSettings mode="Machine" entropy="YM04qnQbcGR6OuD4kW2zKg==" />          </symmetricCryptoProvider>          <symmetricCryptoProvider xsi:type="SymmetricAlgorithmProviderData"  name="RigndaelManaged" algorithmType="System.Security.Cryptography.RijndaeManaged, mscorlib,        </symmetricCryptoProviders>      </enterpriseLibrary.securityCryptographySettings>        </xmlSerializerSection>  </securityCryptographyConfiguration>

shows how to use the RinjdaelManaged provider that was configured in the previous section to encrypt a string of data that represents a Social Security Number. The remaining examples in this chapter (Listings 8.6 to 8.13) used the String Resource Tool[6]

[6] As mentioned earlier, the String Resource Tool can be found in the Downloads section of the Enterprise Library workspace at http://practices.gotdotnet.com/projects/entlib. to create a class called SR that creates properties that represent the values of the strings used in an application.

Listing 8.6. Encrypting Data with the EncryptSymmetric Method and a String

[C#] string cipherText = Cryptographer.EncryptSymmetric      (SR.RinjdaelManaged, "123-45-6789"); [Visual Basic] Dim cipherText As String = Cryptographer.EncryptSymmetric _     (SR.RinjdaelManaged, "123-45-6789")

Alternatively, as Listing 8.7 shows, the same result can be achieved by using the method that accepts a byte array.

Listing 8.7. Encrypting Data with the EncryptSymmetric Method and a Byte Array

[C#] byte[] valueToEncrypt = new byte[]     {49, 0, 50, 0, 51, 0, 45, 0, 52, 0, 53, 0, 45, 0, 54, 0, 55,      0, 56, 0, 57, 0} byte[] cipherContents = Cryptographer.EncryptSymmetric(SR.RinjdaelManaged, valueToEncrypt); Array.Clear(valueToEncrypt, 0, valueToEncrypt.Length); [Visual Basic] Dim valueToEncrypt As Byte() = New Byte() _     {49, 0, 50, 0, 51, 0, 45, 0, 52, 0, 53, 0, 45, 0, 54, 0, 55, _      0, 56, 0, 57, 0} Dim cipherContents As Byte() = _     Cryptographer.EncryptSymmetric(SR.RinjdaelManaged, valueToEncrypt) Array.Clear(valueToEncrypt, 0, valueToEncrypt.Length)

Even though using a byte array is more secure than using strings, the byte array should still be cleared as soon as possible because having unencrypted data in memory can be a security risk.

The DecryptSymmetric Method

Decrypting data that has been encrypted with a configured symmetric provider is also straightforward. The static DecryptSymmetric method is overloaded to match its counterpart, the EncryptSymmetric method. Listing 8.8 provides a sample that decrypts the base64encoded cipherText string that was encrypted in Listings 8.6 and 8.7.

Listing 8.8. Decrypting data with DecryptSymmetric and a base64encoded string

[C#] string cleartext =     Cryptographer.DecryptSymmetric(SR.RinjdaelManaged, cipherText); [Visual Basic] Dim cleartext As String = _     Cryptographer.DecryptSymmetric(SR.RinjdaelManaged, cipherText)

And just as a byte array can be used to encrypt the data, it can also be used to decrypt it, as shown in Listing 8.9.

Listing 8.9. Decrypting data with DecryptSymmetric and a byte array

[C#] byte[] decryptedContents = Cryptographer.DecryptSymmetric      (SR.RinjdaelManaged, cipherContents); [Visual Basic] Dim decryptedContents As Byte() = Cryptographer.DecryptSymmetric _     (SR.RinjdaelManaged, cipherContents)

It is important to use the same provider to encrypt and decrypt the data. Notice that the same RinjdaelManaged provider was used to both encrypt and decrypt the data in Listings 8.6 through 8.9.

Creating and Comparing Hashes

It is better to hash secret data, like passwords, than it is to encrypt them using a symmetric key. Using a symmetric key to encrypt and store password data runs the risk of every password being compromised if the key is compromised. However, if the password is hashed, and only the hash is stored, the actual passwords themselves do not become compromised. When a user enters a password, the password gets hashed in the same manner as the hash that is stored and the two are compared. If the hashes match, the password has been entered correctly.

Hash Provider Configuration

At least one hash provider must be configured for an application for it to use the Cryptography Application Block to create and compare hashes. To add a hash provider, rightclick on the Hash Providers folder and select Custom Hash Provider or HashAlgorithm Provider. There is no menu item for configuring a KeyedHashAlgorithmProvider. Instead, the block will automatically determine whether further configuration for a KeyedHashAlgorithmProvider needs to occur based on whether the hash algorithm that is selected is a keyed hash algorithm. Figure 8.14 demonstrates how to add a nonkeyed hash algorithm like SHA1Managed to the Cryptography Application Block.

Figure 8.14. Adding the SHA1Managed HashAlgorithmProvider


Since this hash algorithm is not keyed, this is all you need to do to configure it. You can change the name or disable salting; however, it is not necessary.

If you select the keyed hashing algorithm instead of the nonkeyed hashing algorithm, an additional dialog will display that lets you enter a key. This is the same Key Creation dialog that was shown in Figure 8.9 for configuring a symmetric key. This key is configured in exactly the same way as the symmetric keys. For details on how to encrypt the configuration information for this key and further protect the master key, see the earlier section SymmetricAlgorithmProvider Configuration.

After the hashing algorithm has been created, you can set whether the algorithm should be salted or not. By default, the Cryptography Application Block enables salting for all hashing algorithms in an effort to reduce the risk of a dictionary attack. You can disable salting for a hashing algorithm by changing the SaltEnabled value to false. Figure 8.15 shows how to change the SaltEnabled value in the Enterprise Library Configuration Tool.

Figure 8.15. Changing the SaltEnabled Value for a Hash Provider


The CreateHash Method

After a hash algorithm provider has been configured, creating hashes is pretty trivial. You can use the Cryptographer's static CreateHash method to create a hash by passing in the name of the hash provider and either a base64encoded string or byte array to encrypt. In the first instance, the CreateHash method returns a base64encoded string that represents the hash; in the second instance it returns an array of bytes that represent the hash. Listing 8.10 shows how to use the HMACSHA1 provider that was configured in Figure 8.15 to create a hash for a password. As in the examples for encrypting and decrypting data in Listings 8.6 through 8.9, the String Resource Tool is used to create a class called with properties that represent the values of the strings used in an application.

Listing 8.10. Creating a Hash from a String

[C#] string hashText =     Cryptographer.CreateHash(SR.HMACSHA1, "p@ssw0rd"); [Visual Basic] Dim hashText As String = _     Cryptographer.CreateHash(SR.HMACSHA1, "p@ssw0rd")

Alternatively, Listing 8.11 shows that the same hash can be created by using the overload that accepts a byte array.

Listing 8.11. Creating a Hash from a Byte Array

[C#] byte[]valueToHash = new byte[]     {112, 0, 115, 0, 115, 0, 119, 0, 48, 0, 114, 0, 100, 0} byte[] generatedHash = Cryptographer.CreateHash      (SR.HMACSHA1, valueToHash); Array.Clear(valueToHash, 0, valueToHash.Length); [Visual Basic] Dim valueToHash As Byte() = New Byte() _     {112, 0, 115, 0, 115, 0, 119, 0, 48, 0, 114, 0, 100, 0} Dim generatedHash As Byte() = Cryptographer.CreateHash _      (SR.HMACSHA1, valueToHash) Array.Clear(valueToHash, 0, valueToHash.Length)

By only storing this hash and not the actual password, the password can only be verified; it cannot be decrypted.

The CompareHash Method

Creating a hash is only one half of the puzzle. The ability to create hashes is of little use if the hash cannot be used to verify that the proper data had been received and that the data has not been modified in transit. You can use the Cryptographer's static CompareHash method to compare the received data against the hash that was created with the CreateHash method. As mentioned earlier in this chapter, many people assume that if the results of two CreateHash methods with the same byte array are equal, then the hashes are equal. However, this is not always true if salt is used. The CompareHash method takes the salt into account when comparing the hashes.

The CompareHash method is overloaded to accept three strings or to accept a string and two byte arrays. The data types must match between the received data and the original hash; therefore, if the original hash is stored as a string, then the first overload must be used; if it is stored as a byte array, then the second overload must be used. If the received data is not of the same data type as the stored hash, then one of them must be converted. Both overloads return a Boolean value that indicates whether the hashes are equal or not.

Listing 8.12 shows how to use the HMACSHA1 provider to compare the received data against the hash that was created in Listing 8.10.

Listing 8.12. Comparing Hashes Using Strings

[C#] bool bValid =     Cryptographer.CompareHash(SR.HMACSHA1,"p@ssw0rd",hashText); [Visual Basic] Dim bValid As Boolean = _     Cryptographer.CompareHash(SR.HMACSHA1,"p@ssw0rd",hashText)

Alternatively, the comparison could be done using byte arrays, as shown in Listing 8.13.

Listing 8.13. Comparing Hashes Using Byte Arrays

[C#] byte[] stringToCompare = new byte[]     {112, 0, 115, 0, 115, 0, 119, 0, 48, 0, 114, 0, 100, 0} bool bValid =     Cryptographer.CompareHash(SR.HMACSHA1, stringToCompare, hashText); [Visual Basic] Dim stringToCompare As Byte() = New Byte() _     {112, 0, 115, 0, 115, 0, 119, 0, 48, 0, 114, 0, 100, 0} Dim bValid As Boolean = _     Cryptographer.CompareHash(SR.HMACSHA1, stringToCompare, hashText)




Fenster Effective Use of Microsoft Enterprise Library(c) Building Blocks for Creating Enterprise Applications and Services 2006
Effective Use of Microsoft Enterprise Library: Building Blocks for Creating Enterprise Applications and Services
ISBN: 0321334213
EAN: 2147483647
Year: 2004
Pages: 103
Authors: Len Fenster

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