Encrypt and Decrypt Data with C#(转摘)
Introduction
Well most of the beginner and intermediate programmers like to play with cryptography. This is the part that took me to some trouble in my life. A good encryption and decryption code is easily findable in the Internet and even on The Code Project. Why another? I didn't find a suitable reason behind that one. And when I found some, I mixed them up and this is the result. I just wanted to share the result.
The Solution
I included a tiny demo solution with an implementation of the segment. Hope
it helps you. As you see from the snapshot, the CryptorEngine
class
holds the two static
methods,
encryption and decryption. The reason I put them to a separate file was because
it is the best practice as far as I know and most importantly, other blocks can
access these methods easily.
The Encryption
The encrypt
method goes like this. I need to say something about
the cipherMode of the tripleDES cryptographic service provider. We used the
ECB (Electronic Code Book). The ECB mode encrypts each block
individually. This means that any block of the plain text that are identical and
in the same message or even in a different message but encrypted with the same
key, will be transformed into identical cipher text blocks. If the plain text to
be encrypted contains substantial repetition, it is feasible for the cipher text
to be broken one block at a time. Also it is possible for an active adversary to
substitute and exchange individual blocks without detection. If a single bit of
the cipher text block is mangled, the entire corresponding plain text block will
be mangled.
public static string Encrypt(string toEncrypt, bool useHashing) { byte[] keyArray; byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt); System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader(); // Get the key from config file string key = (string)settingsReader.GetValue("SecurityKey", typeof(String)); //System.Windows.Forms.MessageBox.Show(key); //If hashing use get hashcode regards to your key if (useHashing) { MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); //Always release the resources and flush data // of the Cryptographic service provide. Best Practice hashmd5.Clear(); } else keyArray = UTF8Encoding.UTF8.GetBytes(key); TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); //set the secret key for the tripleDES algorithm tdes.Key = keyArray; //mode of operation. there are other 4 modes. //We choose ECB(Electronic code Book) tdes.Mode = CipherMode.ECB; //padding mode(if any extra byte added) tdes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tdes.CreateEncryptor(); //transform the specified region of bytes array to resultArray byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); //Release resources held by TripleDes Encryptor tdes.Clear(); //Return the encrypted data into unreadable string format return Convert.ToBase64String(resultArray, 0, resultArray.Length); }
Decryption
Well, as you can see, the decryption method is just kind of opposite of the encryption. I talked about the Cipher Mode ECB in the encrypt section. Now let's talk about the padding mode PKCS7. Padding comes when a message data block is shorter than full number of bytes needed for a cryptographic operation. Why did we choose PCKS7. This is because PCKS#7 padding string consists of a sequence of bytes, each of which equal the total number of padding bytes added.
public static string Decrypt(string cipherString, bool useHashing) { byte[] keyArray; //get the byte code of the string byte[] toEncryptArray = Convert.FromBase64String(cipherString); System.Configuration.AppSettingsReader settingsReader = new AppSettingsReader(); //Get your key from config file to open the lock! string key = (string)settingsReader.GetValue("SecurityKey", typeof(String)); if (useHashing) { //if hashing was used get the hash code with regards to your key MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider(); keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(key)); //release any resource held by the MD5CryptoServiceProvider hashmd5.Clear(); } else { //if hashing was not implemented get the byte code of the key keyArray = UTF8Encoding.UTF8.GetBytes(key); } TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider(); //set the secret key for the tripleDES algorithm tdes.Key = keyArray; //mode of operation. there are other 4 modes. //We choose ECB(Electronic code Book) tdes.Mode = CipherMode.ECB; //padding mode(if any extra byte added) tdes.Padding = PaddingMode.PKCS7; ICryptoTransform cTransform = tdes.CreateDecryptor(); byte[] resultArray = cTransform.TransformFinalBlock( toEncryptArray, 0, toEncryptArray.Length); //Release resources held by TripleDes Encryptor tdes.Clear(); //return the Clear decrypted TEXT return UTF8Encoding.UTF8.GetString(resultArray); }
Web.Config/App.Config file. Why?
You want to change your key. But you are not the developer? Or you do not even have the source! Then what? Thanks to the Web.config/app.config file idea. Keep your secret key in the config file. Change it when you need to.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <appSettings>
How to Use
To use the code sample, you can copy the CryptorEngine
to your
project and start playing or copy method bodies and paste to your application
projects.
To Do
You can try to encrypt the key and save it (encrypted) to config file for an extra bit of security.
Conclusion
This code works fine with .NET 1.1. I built the project in Visual Studio 2005 because some methods expired in .NET 2.0 and changed. For example, the configuration namespace changed a lot. So I built the example in Visual Studio 2005 to see if it works on v2.0 too. And it works with ZERO change and ZERO error.