Utilizing the symmetric key functionality requires several different values to be synchronized between who encrypts and decrypts the data. These are: Password, the Salt value, the Initialization Vector, and the number of iterations.
The salt value is added to the password before hashing. This protects data against dictionary attacks. An attempt to decrypt the data with common passwords would fail without adding the same salt value.
The user cannot use the password directly as encrypted key since the key length would vary in size. Instead, the System.Security.Cryptography.Rfc2898DeriveBytes class is used to turn a password into a key of fixed byte length. This class requires all four elements: The password, the Salt value, the Initialization Vector, and the number of iterations.
Considering that the System.IO and System.Security.Cryptography namespaces are included, the following example to encrypt a file using the Rijndael algorithm:
using System.IO; using System.Security.Cryptography; private void EncrypFile(string _FileToEncrypt, string _cryptoFile, string _Password) { // Step 1. Create the Stream objects FileStream inFile = new FileStream(_FileToEncrypt, FileMode.Open, FileAccess.Read); FileStream outFile = new FileStream(_cryptoFile, FileMode.OpenOrCreate, FileAccess.Write); // Step 2. Create the Symetrical algo object SymmetricAlgorithm symAlgo = new RijndaelManaged(); // Step 3. Specify a key (optional) byte[] salt = Encoding.ASCII.GetBytes("This is my salt"); Rfc2898DeriveBytes theKey = new Rfc2898DeriveBytes(_Password, salt); symAlgo.Key = theKey.GetBytes(symAlgo.KeySize / 8); symAlgo.IV = theKey.GetBytes(symAlgo.BlockSize / 8); // Read the unencrypted file file into fileData byte[] fileData = new byte[inFile.Length]; inFile.Read(fileData, 0, (int)inFile.Length); // Step 4. Create the ICryptoTransfor object ICryptoTransform encryptor = symAlgo.CreateEncryptor(); // Step 5. Create teh Crypto Stream object CryptoStream encryptStream = new CryptoStream(outFile, encryptor, CryptoStreamMode.Write); // Step 6. Write the contents to the CryptoStream encryptStream.Write(fileData, 0, fileData.Length); // Close file handles encryptStream.Close(); inFile.Close(); outFile.Close(); }The counterpart to decrypt a file is as follows:
private void DecryptFile(string _FileToDencrypt, string _cryptoFile, string _Password) { // Step 1. Create the Stream objects FileStream outFile = new FileStream(_FileToDencrypt, FileMode.OpenOrCreate, FileAccess.Write); FileStream inFile = new FileStream(_cryptoFile, FileMode.Open, FileAccess.Read); // Step 2. Create the Symetrical algo object SymmetricAlgorithm symAlgo = new RijndaelManaged(); // Step 3. Specify a key (optional) byte[] salt = Encoding.ASCII.GetBytes("This is my salt"); Rfc2898DeriveBytes theKey = new Rfc2898DeriveBytes(_Password, salt); symAlgo.Key = theKey.GetBytes(symAlgo.KeySize / 8); symAlgo.IV = theKey.GetBytes(symAlgo.BlockSize / 8); // Step 4. Create the ICryptoTransfor object ICryptoTransform decryptor = symAlgo.CreateDecryptor(); // Step 5. Create the Crypto Stream object CryptoStream decryptStream = new CryptoStream(inFile, decryptor, CryptoStreamMode.Read); // Step 6. Write the contents to the CryptoStream // Read the encrypted file file into fileData byte[] fileData = new byte[inFile.Length]; decryptStream.Read(fileData, 0, (int)inFile.Length); // Save unecrypted data outFile.Write(fileData, 0, fileData.Length); // Close the file handles decryptStream.Close(); inFile.Close(); outFile.Close(); }
Note that the code can be modified to use the other C# symmetric encryption algorithms supported by .NET Framework.