Creating an Encryption Utility in C# [Part 2 of 3]
Introduction
This is Part Two of a Three-part series. Click here to read Part One.
We used over 10 web hosting companies before we found Server Intellect. Their dedicated servers and add-ons were setup swiftly, in less than 24 hours. We were able to confirm our order over the phone. They respond to our inquiries within an hour. Server Intellect's customer support and assistance are the best we've ever experienced.
In part two of this three part series we are going to continue with our Encryption utility example and pick up where we left off. What we learned in the previous article was how many various types of encryption algorithms there are and which one of those algorithms we will be using for our example.
We were able to create a new Windows application and begin adding our libraries and our IEncrypt interface. We will now continue the example by building the Encryption Class.
Continuing with our example
The next step in our example has us creating the Key we will be using as part of the encryption process.
One note when you are developing cryptography, ciphers (crypto algorithms) are publicly available. What I mean by that is that you can look at the algorithm’s math and know exactly what it's doing. However, the math requires a secret key. With DES (and all "symmetric block ciphers"), the key is used as part of the math to encrypt the data. Also with DES the very same key must be used to decrypt the data. As you can see in our example, the key is just a sequence of bytes (it is actually a byte array, not just a single byte).
In .NET, when you create the initial symmetric block cipher object (in this case, the DES object) it will automatically generate a cryptographically-strong, random key sequence for you.
When you call the CreateEncryptor method, and if you do not pass a key to that method, the key in the base DES object is used. However, as you can see with the example we have here, you can pass your own generated key. Just remember that you must use the same key to decrypt the data that you used to encrypt the data.
As for the second argument to the CreateEncryptor method, the Salt or IV, it is used in the various Feedback modes. For example, if you encrypt some straight plain text and you do it one block at a time, and let’s say that data has repeating blocks, you could literally end up with some repeating encrypted blocks as well.
Normally you would say, well what is the big deal about that, but what that does is it could give away obvious clues to a hacker wanting to crack your encryption algorithm. What Feedback does is it will take the bits from the previous block and mathematically infuse those bits into the data with the next block as it encrypts. That way, you get even more protection and more unpredictable results.
If you're ever in the market for some great Windows web hosting, try Server Intellect. We have been very pleased with their services and most importantly, technical support.
However, the first block of data has nothing in front of it to use as feedback, so the Salt acts as a "fake" block of data used to perform the feedback math on the first block. If you do use a feedback mode (.NET uses some form of feedback by default unless it is turned off), you must also keep the Salt byte sequence used to encrypt the data because you can't decrypt the data without it. Make sure you keep both the Key and Salt private and safe at all times.
The Salt (IV) must always be exactly one block in size. One block could be different number of bits depending on the algorithm you use. For most block encryption algorithms, a block is 16 bits or 32 bits. In our example we are using a 16 bit byte array.
Accessors
The next thing we will add to our project are accessors, these accessors are called mutator methods, and are sometimes called a "setter".
/// Property for PrivateKey Value
///
private Byte[] PrivateKey
{
get { return _strPrivateKey; }
}
///
/// Property for the Salt Value
///
private Byte[] Salt
{
get { return _strSalt; }
};
You will notice that both of these accessors return byte arrays. These arrays represent the Key and Salt values for our example.
We are using Server Intellect and have found that by far, they are the most friendly, responsive, and knowledgeable support team we've ever dealt with!
Methods
Now we want to create our methods. In this example we will have 4 methods:
EncryptString
This is the method where we will pass our original string value and return a string that represents our encrypted value.
/// Encrypt the passed string
///
///
/// String to Encrypt
public string EncryptString(string plainTextString)
{
string strValue = String.Empty;
try
{
System.Security.Cryptography.RijndaelManaged cryptObj = new RijndaelManaged();
if (plainTextString != string.Empty)
{
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, cryptObj.CreateEncryptor(PrivateKey, Salt), CryptoStreamMode.Write);
StreamWriter sw = new StreamWriter(cs);
sw.Write(plainTextString);
sw.Flush();
cs.FlushFinalBlock();
ms.Flush();
strValue = Convert.ToBase64String(ms.GetBuffer(), 0, (int)ms.Length);
}
else
strValue = string.Empty;
}
catch (Exception ex)
{
// Make sure that the application that is consuming this
// .DLL gets the message returned so it can be displayed.
MessageBox.Show("Unable to Encrypt the passed string: \r\n\r\n " + ex.Message.ToString(), "Error");
} // Return the Encrypted String
return strValue; }
DecryptString
This is the method where we will pass our encoded value and return a string value that represents our original value.
Yes, it is possible to find a good web host. Sometimes it takes a while. After trying several, we went with Server Intellect and have been very happy. They are the most professional, customer service friendly and technically knowledgeable host we've found so far.
/// Decrypt the passed string
///
///
/// String to Decrypt
public string DecryptString(string encodedTextString)
{
string strValue = String.Empty;
try
{
System.Security.Cryptography.RijndaelManaged cryptObj = new RijndaelManaged();
//cryptObj.Padding = PaddingMode.None;
//cryptObj.Mode = CipherMode.CBC;
if (encodedTextString != string.Empty)
{
byte[] buf = Convert.FromBase64String(encodedTextString.Trim());
MemoryStream ms = new MemoryStream(buf);
ms.Position = 0;
CryptoStream cs = new CryptoStream(ms, cryptObj.CreateDecryptor(PrivateKey, Salt), CryptoStreamMode.Read);
StreamReader sr = new StreamReader(cs);
strValue = sr.ReadToEnd();
}
else
strValue = String.Empty;
}
catch (Exception ex)
{
// Make sure that the application that is consuming this
// .DLL gets the message returned so it can be displayed.
MessageBox.Show("Unable to Decrypt the passed string: \r\n\r\n " + ex.Message.ToString(), "Error");
}
// Return the decrypted text
return strValue;
}
EncodeString
This is the method where we will pass our encrypted value and return a string value that represents our encoded value.
/// Encode the passed string
///
///
/// Encrypted String to Encode
public string EncodeString(string encryptedTextString)
{
// Local Declarations
byte[] baValue = null;
string strValue = String.Empty;
try
{
// Encode the Passed String
baValue = Encoding.Unicode.GetBytes(encryptedTextString);
strValue = Convert.ToBase64String(baValue);
}
catch (Exception ex)
{
// Make sure that the application that is consuming this
// .DLL gets the message returned so it can be displayed.
MessageBox.Show("Unable to Encode the passed string: \r\n\r\n " + ex.Message.ToString(), "Error");
}
// Return the Encoded Value
return strValue;
}
We chose Server Intellect for its dedicated servers, for our web hosting. They have managed to handle virtually everything for us, from start to finish. And their customer service is stellar.
DecodeString
This is the method where we will pass our encoded value and return a string value that represents our encrypted value.
/// Decode the passed string
///
///
/// Encoded String to Decode
public string DecodeString(string encodedTextString)
{
// Local Declarations
byte[] baValue = null;
string strValue = String.Empty;
try
{
// Decode the Passed String
baValue = Convert.FromBase64String(encodedTextString);
strValue = Encoding.Unicode.GetString(baValue);
}
catch (Exception ex)
{
// Make sure that the application that is consuming this
// .DLL gets the message returned so it can be displayed.
MessageBox.Show("Unable to Decode the passed string: \r\n\r\n " + ex.Message.ToString(), "Error");
}
// Return the Decoded String
return strValue;
}
We have now created the Encryption Class for our example. In our next article Part Three of the series we will design the GUI interface that will complete our Encryption Utility.
What we have Learned
- What is Encryption
- How to use a Key during the Encryption
- How to use a Salt (IV) value during the Encryption
- How to create the Accessors we will be using
- How to create the methods we will be using
Click here to read Part Three.
We migrated our web sites to Server Intellect over one weekend and the setup was so smooth that we were up and running right away. They assisted us with everything we needed to do for all of our applications. With Server Intellect's help, we were able to avoid any headaches!
Attachments
|