The symmetric cryptography provider works the same way as the hash provider except for the fact that the interface and class involved are different. The ISymmetricCryptoProvider
interface defines the core contract for configurable symmetric cryptographic implementation; this interface is part of the Microsoft.Practices.EnterpriseLibrary.Security.Cryptography
namespace. This interface defines two methods, Encrypt and Decrypt, as shown in the following diagram:
The SymmetricAlgorithmProvider
class inherits the ISymmetricCryptoProvider
interface and provides implementation for algorithms derived from the System.Security.Cryptography.SymmetricAlgorithm
class.
The following diagram shows the members of the SymmetricAlgorithmProvider
class:
CryptographyManager
is an abstract class, which wraps functionality from instances of both IHashProvider
and ISymmetricCryptoProvider
. The application block identifies the configured hash and symmetric cryptography provider and provides both hashing and encryption functionality by exposing the respective methods. It also provides a nifty method that accepts plain text and returns plain text while creating a hash.
The following diagram shows the methods exposed by the CryptographyManager
abstract class:
The CryptographyManagerImpl
class inherits from the abstract class CryptographyManager
; this class provides the real implementation, which identifies both the providers and loads the configured providers. This class loads both the hash and cryptography providers from the configuration and leverages them to perform the respective actions.
The following diagram shows the inheritance hierarchy and methods exposed by the CryptographyManagerImpl
class:
We have already explored creating instances of CryptographyManager in the Creating CryptographyManager and IHashProvider Instances section, so in this section we will focus on creating instances of ISymmetricCryptoProvider
using Unity service locator and using the Unity container directly.
The Cryptographer
static class provides EncryptSymmetric
and DecryptSymmetric
methods to perform encryption and decryption of data. Additionally, it accepts string
as well as byte[]
for both encryption and decryption. As discussed previously, being a static facade the methods can be invoked directly.
Creating instances using Unity service locator has already been explored in the section Creating CryptographyManager and IHashProvider Instances.
We have already learned to create an instance of CryptographyManager
while working with hashing functionality in the section Creating CryptographyManager and IHashProvider Instances; CryptographyManager
also provides methods to perform encryption and decryption of data.
The following is a code snippet to create a deafult ISymmetricCryptoProvider
instance using UnityContainer:
ISymmetricCryptoProvider defaultCryptoProvider = EnterpriseLibraryContainer.Current.GetInstance<ISymmetricCryptoProvider>();
The following is a code snippet to create a ISymmetricCryptoProvider
named instance using UnityContainer:
ISymmetricCryptoProvider cryptoProvider = EnterpriseLibraryContainer.Current.GetInstance<ISymmetricCryptoProvider>("DPAPI Symmetric Crypto Provider");
While learning to leverage the hashing functionality in the section Creating CryptographyManager and IHashProvider Instances we explored creating instances using Unity container directly and the same applies to this section as well.
The following is a code snippet to create a deafult ISymmetricCryptoProvider
instance using UnityContainer:
var container = new UnityContainer(); container.AddNewExtension<EnterpriseLibraryCoreExtension>(); ISymmetricCryptoProvider defaultCryptoProvider = container.Resolve<ISymmetricCryptoProvider>();
The following is a code snippet to create a ISymmetricCryptoProvider
named instance using UnityContainer:
var container = new UnityContainer(); container.AddNewExtension<EnterpriseLibraryCoreExtension>(); ISymmetricCryptoProvider defaultCryptoProvider = container.Resolve<ISymmetricCryptoProvider>("DPAPI Symmetric Crypto Provider");
We have already learned to add Cryptography Settings to the configuration file; click on the plus symbol provided on the top-right corner of the Symmetric Cryptography Providers section, navigate, and click Add Symmetric Cryptography Providers | Add Symmetric Algorithm Provider. This action will display the Symmetric Algorithm selection dialog box. For the purposes of this demonstration, we will select the RijndaelManaged
algorithm implementation, which is part of the System.Security.Cryptography
namespace, and hit the OK button.
The following screenshot shows the menu option Add Symmetric Algorithm Provider:
Once we click on the menu option Add Symmetric Algorithm Provider, the Symmetric algorithm selection dialog box is displayed as shown in the following screenshot:
Selection of the Symmetric Algorithm will result in display of the Cryptographic Key Wizard dialog. Basically, the algorithm requires a key that can be used to encrypt and decrypt data. We can either create a new key, use an existing Data Protection API (DPAPI)-protected key file, or import a password-protected key file. For the purposes of this demonstration, we will opt to Create a new key and click Next.
The following screenshot shows the Cryptographic Key Wizard dialog box:
We are now prompted to either enter the key or generate the key using the Generate button. Click on Generate and a new key will be generated and displayed in the textbox as shown in the following screenshot. Click Next to move to the next step of the wizard.
Once we click Next, we will be prompted to choose the file storage path. We can provide the appropriate path and key filename by clicking the ellipsis "..." button. Click Next to move to the next step of the wizard.
So far we have generated the key and specified the path and filename to store the key. But the key itself is not yet protected and vulnerable; this step prompts us to protect the key using the Data Protection API (DPAPI). We have to select the data protection mode; User mode encrypts the key using the credentials of the currently logged-in user while the Machine mode allows any users on this computer to encrypt or decrypt the key. For the purposes of this demonstration, we will select User mode; click the Finish button to close the wizard.
The following screenshot shows the data protection mode options:
Once the key wizard dialog is closed, we will end up with the Cryptography Settings configuration as shown in the following screenshot:
We are now done with the configuration of the Symmetric Cryptography Provider. We can now leverage the provider to encrypt/decrypt data but before we explore encryption/decryption, we will learn the important task of exporting the generated key in the next section.
We can export the generated key and save it in a file for backup purposes; the key is encrypted with the provided password. Since this file contains the key for encryption, it must be protected and only trusted users must be given access through ACL.
The simplicity of the API makes it very easy to perform encryption operations. Encrypting data requires two/three input based on the approach (Factory vs. Service Locator vs. Unity) taken. For the purposes of this demonstration, we are using the service locator to get an instance of CryptographyManager
and perform encryption using the configured symmetric algorithm provider.
The following code snippet gets an instance of CryptographyManager
and encrypts the given data using the named provider:
CryptographyManager cryptoManager = EnterpriseLibraryContainer.Current.GetInstance<CryptographyManager>(); //Encrypt Data Using Configured Symmetric Cryptography Provider Named 'RijndaelManaged' //Returns encrypted data string encryptedData = cryptoManager.EncryptSymmetric("RijndaelManaged", "Data to be encrypted");
The given code snippet returns the following encrypted data:
5B0oeiIoQNO5A2C/LE+L6Ax7ecPxU4jDQJ8I+j0Z8+VadOaqVcj7HdWMWHyDpfYblqxFgBqNvfijMONAxNYCBQ==
For the purposes of this demonstration we are using the service locator to get an instance of CryptographyManager
and perform decryption using the configured symmetric algorithm. Note that the input for encrypted data is the result of the encryption action performed in the previous section; the same algorithm is used to decrypt the data.
The following code snippet demonstrates data decryption using the DecryptSymmetric
method:
CryptographyManager cryptoManager = EnterpriseLibraryContainer.Current.GetInstance<CryptographyManager>(); string encryptedData = "5B0oeiIoQNO5A2C/LE+L6Ax7ecPxU4jDQJ8I+j0Z8+VadOaqVcj7HdWMWHyDpfYblqxFgBqNvfijMONAxNYCBQ=="; //Decrypt Data Using Configured Symmetric Cryptography Provider Named 'RijndaelManaged' //Returns encrypted data string decryptedData = cryptoManager.DecryptSymmetric("RijndaelManaged", encryptedData);
The given code snippet returns the following decrypted data:
Although the .NET Framework provides implementation of several symmetric cryptography algorithms there might be a scenario in which we will need to use a custom symmetric encryption to meet certain proprietary or statutory requirements. The Cryptography block provides extensibility points that allow us to configure a custom symmetric encryption provider without re-compiling the code. Apart from the assemblies listed in the section Referencing required and optional assemblies, we will have to add an additional reference of System.Configuration.dll
. This assembly is used to indicate the configuration object type specified using the ConfigurationElementType
attribute. We can implement a custom symmetric provider by inheriting the ISymmetricCryptoProvider
interface and providing logic to Encrypt
and Decrypt
data.
Adding the following given namespaces will help in saving IDE real estate and improve readability of the code and so it is recommended to add these namespaces.
System.Collections.Specialized
Microsoft.Practices.EnterpriseLibrary.Common.Configuration
Microsoft.Practices.EnterpriseLibrary.Security.Cryptography
Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Configuration
Although the given code is self explanatory, we will attempt to make a quick walkthrough of the code snippet. We have written a class named CustomEncryptionProvider
, which inherits from the ISymmetricCryptoProvider
interface and provides a stub implementation for demonstration purposes.
The following code snippet provides a skeleton implementation of the custom encryption provider:
[ConfigurationElementType(typeof(CustomSymmetricCryptoProviderData))] public class CustomEncryptionProvider : ISymmetricCryptoProvider { public byte[] Decrypt(byte[] ciphertext) { // Implement Decryption Logic } public byte[] Encrypt(byte[] plaintext) { // Implement Encryption Logic } }
Just in case if you are wondering what the first line of code is all about, the attribute ConfigurationElementType
indicates the configuration object CustomSymmetricCryptoProviderData
used for CustomEncryptionProvider
. We also have to provide a constructor that accepts a parameter of type NameValueCollection
. Implementation of a custom encryption provider is quite straightforward as seen in the above code snippet; we just need to provide our custom encryption/decryption logic in the Encrypt
and Decrypt
methods respectively.
Configuration of a custom symmetric provider takes a slightly different approach. In the Symmetric Cryptography Providers section of Cryptography Settings click on the plus symbol; navigate and click on the menu option Add Symmetric Cryptography Providers | Add Custom Symmetric Crypto Provider.
The following screenshot shows the menu option Add Custom Symmetric Crypto Provider:
This action will display a types browsing dialog box listing the types derived from the ISymmetricCryptoProvider
interface. The following is a screenshot of the custom symmetric cryptography provider selection dialog.
For the purposes of this demonstration, we will select the CustomEncryptionProvider
implementation as shown in the given screenshot. Once we select the provider and click on the OK button, the custom encryption provider is added to the configuration file as shown in the following screenshot. The configuration editor allows us to add custom key/value attributes, which will be passed on to the constructor of CustomEncryptionProvider
.
The following screenshot shows the selected custom Symmetric Cryptography Provider:
After configuring the cryptography provider, we will be able to leverage the custom encryption and decryption functionality without changing or impacting the application code.
3.139.83.151