The cryptography, before the arrival of .NET, was meant to use the Unmanaged Win32 APIs which was very obscure way to encrypt or decrypt the data. .NET provides a set of classes (and actually a complete namespace) for the subject. Now you have a number of classes using different pre defined algorithms which can help you to secure your data using cryptography. In .NET, there are three types of cryptography defined under the tree of Cryptography namespace. Those are
HashAlgorithm. All these three classes (and also types of cryptography in .NET) are abstract classes. We are going to discuss
SymmetricAlgorithm in this article. The rest will be discussed in coming articles.
NOTE: Although most of the encryption classes are implemented in the managed code many classes uses the CryptoAPI library. You can predict them if you see the
CryptoServiceProvider in the class name like
Basics of SymmetricAlgorithms
Symmetric Algorithms works using a user defined secret key (or password). It means, whenever you are going to implement and Symmetric Algorithm to encrypt/decrypt your data, you must have to define a password or secret key which will be used to encrypt or decrypt your data. Following are the characteristics of Symmetric based encryption.
- The strength of the encryption depends on the secured key (password). If you provide the larger key, it will be harder to hack that code. Since it will take more time to the hackers to find out the key.
- It is based on a simple mathematical operation. So it works faster. Hence, it is the best choice if you are working with a large amount of data.
- One drawback of this type of algorithm is that the secret key should be known to both parties (that who is encrypting and that who needs that information/data to decrypt.)
- Symmetric based encryption can be broken by the hackers using brute force. But if you defines a good key, then it may take a long time (or even impossible) to hack.
- Since the secret key is user defined, which normally, as the nature of the users, exists in the dictionary. So a hacker can decode/decrypt your information using brute force and dictionary. But larger key can protect the data for a long time since it takes long time to be cracked.
Beside the Secret Key or password, there is one thing more which involves in the encryption or decryption process of Symmetric algorithm. That is Initialization Vector (IV). IV is used to initialize the encoding (encryption/decryption). We have a property in all Symmetric algorithm classes named
Mode. This is where IV is used. If we set the Mode property to CipherMode.CBC (Cipher Block Chaining), then using this mode, each block of the data is processed by taking values from the previous block. Means if the system is processing third block of data, then it will use some information from the second block (which has been processed). And it will take values from first block when it was processing second block. But since there is no block before the first block, so it will use IV to process first block. This technique makes sure that no two same blocks generates equal output and hence data becomes more secure. While if you use Mode = CipherMode.ECB (Electronic Codebook Mode), then it do not use chaining (using previously processed block information to process next block). This mode is helpful if you want to process large messages since it takes less resources and time. It also let's you to process from the mid of data, if some data is corrupted.
So, up to here we saw that there are two important things involved in the Symmetric encryptions. Those are, Key (Secret Key or password) and Initialization Vector (IV). Now let's take a look on some algorithms which supports Symmetric encryption
Symmetric Algorithms and SymmertricAlgorithm Class
The following are the Symmetric algorithms and their classes with some information of Key.
||Algo Class (Abstract)
||Valid Key Size (bit)
||Default Key Size (Bit)
||Default Implementation Class
||128, 192, 256
It should be noted here that all these algorithm classes are derived from Abstract class named SymmetricAlgorithm. And you can see that each class supports different Key Sizes. In the same way, these also supports for different IV size. As I told earlier that all these classes are abstract, so we can not directly create any instance of any of these classes. But the SymmetricAlgorithm Class (which is also an abstract class) expose a shared method named create which can be used to create a concrete instance of the class without worrying about that how it is implemented. Means, you can use it in this way
Dim mRC2 As RC2 = RC2.Create()
This will return you the instance of the default implementation of RC2 without worrying about that how to implement the RC2 class (which is an abstract class). This technique is useful if you need a generic code since it is possible that Microsoft may update the changes in implementation of RC2 class later. In that case, you code will pick these changes automatically and will work fine. Or maybe, RC2 class code is written as Managed code in future and hence your code will accept that. In the same way, you can use the following statement as well.
Dim mCrypto as RC2 = SymmetricAlgorithm.Create("RC2")
This will also return you the RC2 object (default implementation). In this case you are using overloaded create function which takes the algorithm name as parameter and returns the object of that algorithm. This create method is used from
SymmetricAlgorithm class and as I said earlier all other classes which uses Symmetric Algorithm inherits the
SymmetricAlgorithm class, hence, you will find this Create method in all classes defined above. It means that if you use
RC2.Create("DES") then it will also work and will return the object of DES. But it doesn't seem good to get DES object using RC2 class.
The above mechanism is more useful then it seems. We can define our own class using our own algorithm and use that in the same way. But for that, we have to made a little changes in the machine.config file. I am not going to describe that here. You can consult the Wrox Book on Cryptography (mentioned in Bibliography section of this article) for more reference.
Now let's take a look at some properties and methods of the
- BlockSize: The size of the block(data) which will be processed at a time. A long data will be broken into chunks of data (blocks) to process and if the data is less than the block size, then it will be padded (filled using some default value).
- Key: The secret value which will be used to process the data. This key is provided using a byte array.
- KeySize: Total Size of the Key (in bits).
- IV: Initialization Vector for data processing (discussed above). Provided as an array of byte.
- LegalBlockSizes: Returns the BlockSize Enumeration which tells you legal values for block size including max value, min value and Skip value. Skip value means that how much value should be added to last legal value to get next value. Like if min value is 32 and Skipvalue is 16, it means next legal values will be 48, 64 and so on.
- Mode: Gets or sets the Mode for the operation. Discussed above. Value is one of the CipherMode enumeration.
- Padding: Gets or Sets the padding (how empty area of the block should be filled) Value is one of the PaddingMode enumiration value
- LegalKeySizes: Same as LegalBlockSizes, but deals with KeySize.
- Create: Discuessed above, used to create the default algo implementation class.
- CreateEncryptor: Returns the ICryptoTransform Object which can be used to encrypt data manually. will be discussed shortly.
- CreateDecryptor: Returns the ICryptoTransform Object which can be used to decrypt data manually. will be discussed shortly.
- GenerateKey and GenerateIV: If the Key and IV is found null during the encryption or decryption process, then these methods are used to Generate the default key and IV.
- ValidKeySize: Checks either the given key is valid for this algo or not.
- Clear: Clears all the resources and removes memory information like key and IV.
Now before writing a code, let's discuss two more things which will be usefull for us to understand the code.
CreateEncryptor and CreateDecryptor
CreateEncryptor and CreateDecryptor methods of SymmetricAlgorithm class returns the object of ICryptoTransform. ICryptoTransform is an interface which is implemented by the class which wants to process data block wise. This processing may be encryption, decryption, hashing, base 64 encoding/decoding etc. The basic purpose of this Interface is to perform Blockwize processing of data. You can use its instance directly, but in most cases, for convenience, we pass it to another class named CryptoStream. Let's see an example that how to use it.
Dim mCrypt as DES = SymmetricAlgorithm.Create("DES")
Dim mTransform as ICryptoTransform = mCrypt.CreateEncryptor()
CreateDecryptor are overloaded functions. If you do not pass anything to it, then default Key and IV (using GenerateKey and GenerateIV methods of SymmetricAlgoruthm class) will be used to get Key and IV. In other case, you can pass IV and Key to CreateEncryptor and CreateDecryptor object. So that the encryption or decryption should be made using our defined key and IV.
CryptoStream class is used to read or write the data and also encrypt or decrypt that while reading or writing. It simly wraps the ordinary Stream class. It uses the buffered access taking all worries from you to manage buffer, block sizes, padding etc. You can get it's instance using the following code.
Dim mCrypt as DES = SymmetricAlgorithm.Create("DES")
Dim mTransform as ICryptoTransform = mCrypt.CreateEncryptor()
Dim mStream as New CryptoStream(fileStream, mTransform, CryptoStreamMode.Read)
fileStream is the stream of any ordinay file (or may be
MemoryStream) which is responsible for reading data from the disk (file) or memory. Now use this
mStream object with StreamReader/StreamWriter object to Read/Write data. When you will read/write that, then you will have encrypted/decrypted information depending on the ICryptoTransform object (either it was created using CreateEncryptor or CreateDecryptor).
Writing the Sample Code.
Now we have enough information about SymmetricAlgorithm. Finally, let's move to a little block of code which will encrypt and then decrypt the data. I am assuming that you have a form with one textbox named txtData and a command button. Write this code on the command button's click event. This code will encrypt text inside the textbox, show you in the messagebox, write to textbox, decrypt that, show in the messagebox and then write back to textbox.
Dim mCryptProv as SymmetricAlgorithm
Dim mMemStr as MemoryStream
SymmetricAlgorithm Like DES mCryptProv = SymmetricAlgorithm.Create("Rijndael")
mMemStr = New MemoryStream()
Dim mTransform As ICryptoTransform = mCryptProv.CreateEncryptor()
Dim mCSWriter As New CryptoStream(mMemStr, mTransform, CryptoStreamMode.Write)
Dim mSWriter As New StreamWriter(mCSWriter)
One thing you may have notice here that we didn't used IV and Key anywhere in the code. Actually, the .NET Framework will generate it for us since we are not specifying it for ease of code. But the sample included with this article uses the Key and IV defined by the user. Now the data after encryption has been written to the memory using MemoryStream object. Now let's get that data from the Memory.
Dim mBytes(mMemStr.Length - 1) As Byte
mMemStr.Position = 0 mMemStr.Read(mBytes, 0, mMemStr.Length)
Dim mEnc As New Text.UTF8Encoding()
Dim mEncData As String = mEnc.GetString(mBytes)
MsgBox("Encrypted Data is : " & vbCrLf & mEncData)
Me.txtData.Text = mEncData
Converting from Byte to string involves Encoding. I am using UTF8Encoding here. Finally, Let's us decrypt that data and then show againt in the messagebox and TextBox as well.
mMemStr.Position = 0
mTransform = mCryptProv.CreateDecryptor()
Dim mCSReader As New CryptoStream(mMemStr, mTransform, CryptoStreamMode.Read)
Dim mStrREader As New StreamReader(mCSReader)
Dim mDecData As String = mStrREader.ReadToEnd()
MsgBox("Decrypted Data is : " & vbCrLf & mDecData)
Me.txtData.Text = mDecData
That's all the work. To decrypt that data, we used the same memory stream. We first moved the position to start so that we can read from the start of the stream. Then we created the ICryptoTransform Object using CreateDecryptor method of SymmetricAlgorithm object. We reused the object which was created for encrypting data in above section of this code. You can create a new object (with new variable). Then we needed a StreamReader which will read data from the memory for us. While reading that it will also decrypt that data since we passed CryptoStream object during the creation of StreamReader object.
Closing this article, I would like to say that .NET provides us a very managed way to secure our data using built-in set of classes. Now there is no problem of using that old fashioned Crypto APIs although many classes uses those Crypto APIs behind the scene. But we can safely use these classes without worrying about the implementation of these classes. In next article (which I hope will be published soon) I will describe the myths and usage of AsymmetricAlgorithm.
About the Sample Code
Sample code provided with this article let's you to select the algorithm to use to encrypt or decypt data (as shown in the picture above). Also it let's you to specify your own IV and Key. The code has two ways of working. One with the textbox, means you write something in the textbox and then encrypt or decrypt that. Secondly, you can choose files to encrypt or decrypt them.
The information provided in this article was taken from Microsoft Developers Network (MSDN) and the Wrox Publications book Cryptography in .NET. I used only a sample chapter (chapter 2) from that book. Rest I used my own experience on working with Cryptography in .NET.
About the Author
Sameers (theAngrycodeR) has did his master in computer sciences in Feb. 2002. He is the Project Manager in City Soft (Pakistan) and has developed and managed a number of projects. He proved his expertise in Visual Basic 6 and now working in VB .NET. He is the author of many articles on CodeProject.com as well as on the Microsoft .NET Community Site, GotDotNet. Also submitted many source codes on Planet-Source-Code.com. The complete information about the author can be found here.
be angry with theAngrycodeR