encrypt/decrypt using symmetric algorithm
Published: 2. February 2012 | Updated: 2. February 2012License: Microsoft Public License (MS-PL)
Categories: Security » Encryption
Tags: C# Security
Class for encrypting, decrypting bytes, text or files using symmetric algorithms. Also enables generate salt and initialization vector (IV).
Import namespaces
using System; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text;
Class
Methods uses optional parameters introduced in C# 4.0. For older C# versions just change "int? keySize = null" to "int? keySize" and "int passwordIterations = 1000" to " int passwordIterations".
public static class SymmetricEncryption { private static readonly Random Random = new Random(); public static byte[] GenerateSalt() { var salt = new byte[16]; Random.NextBytes(salt); return salt; } public static byte[] GenerateInitializationVector(SymmetricAlgorithm algorithm) { if (algorithm == null) throw new ArgumentNullException("algorithm"); int size = algorithm.LegalBlockSizes[0].MinSize / 8; var iv = new byte[size]; Random.NextBytes(iv); return iv; } public static void EncryptFile(SymmetricAlgorithm algorithm, string filePath, string password, string salt, string iv, int? keySize = null, int passwordIterations = 1000) { EncryptFile(algorithm, filePath, Encoding.UTF8.GetBytes(password), Encoding.UTF8.GetBytes(salt), Encoding.UTF8.GetBytes(iv), keySize, passwordIterations); } public static void EncryptFile(SymmetricAlgorithm algorithm, string filePath, byte[] password, byte[] salt, byte[] iv, int? keySize = null, int passwordIterations = 1000) { if (algorithm == null) throw new ArgumentNullException("algorithm"); if (String.IsNullOrEmpty(filePath)) throw new ArgumentException("File path is null or empty", "filePath"); if (!File.Exists(filePath)) throw new FileNotFoundException("File does not exist", filePath); if (password == null || password.Length == 0) throw new ArgumentException("Password is empty", "password"); if (salt == null || salt.Length < 8) throw new ArgumentException("Salt is not at least eight bytes", "salt"); if (iv == null || iv.Length < (algorithm.LegalBlockSizes[0].MinSize / 8)) throw new ArgumentException("Specified initialization vector (IV) does not match the block size for this algorithm", "iv"); var fileBytes = File.ReadAllBytes(filePath); var encryptedBytes = EncryptBytes(algorithm, fileBytes, password, salt, iv, keySize, passwordIterations); File.WriteAllBytes(filePath, encryptedBytes); } public static string EncryptText(SymmetricAlgorithm algorithm, string text, string password, string salt, string iv, int? keySize = null, int passwordIterations = 1000) { if (algorithm == null) throw new ArgumentNullException("algorithm"); if (String.IsNullOrEmpty(text)) throw new ArgumentException("Text is null or empty", "text"); if (String.IsNullOrEmpty(password)) throw new ArgumentException("Password is null or empty", "password"); if (String.IsNullOrEmpty(salt) || salt.Length < 8) throw new ArgumentException("Salt is not at least eight bytes", "salt"); if (String.IsNullOrEmpty(iv) || iv.Length < (algorithm.LegalBlockSizes[0].MinSize / 8)) throw new ArgumentException("Specified initialization vector (IV) does not match the block size for this algorithm", "iv"); var encryptedBytes = EncryptBytes(algorithm, Encoding.UTF8.GetBytes(text), Encoding.UTF8.GetBytes(password), Encoding.UTF8.GetBytes(salt), Encoding.UTF8.GetBytes(iv), keySize, passwordIterations); return Convert.ToBase64String(encryptedBytes); } public static byte[] EncryptBytes(SymmetricAlgorithm algorithm, byte[] data, byte[] password, byte[] salt, byte[] iv, int? keySize = null, int passwordIterations = 1000) { if (algorithm == null) throw new ArgumentNullException("algorithm"); if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data"); if (password == null || password.Length == 0) throw new ArgumentException("Password is empty", "password"); if (salt == null || salt.Length < 8) throw new ArgumentException("Salt is not at least eight bytes", "salt"); if (iv == null || iv.Length < (algorithm.LegalBlockSizes[0].MinSize / 8)) throw new ArgumentException("Specified initialization vector (IV) does not match the block size for this algorithm", "iv"); if (keySize == null) keySize = algorithm.LegalKeySizes[0].MaxSize; byte[] keyBytes; using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, passwordIterations)) { keyBytes = rfc2898DeriveBytes.GetBytes(keySize.Value / 8); } byte[] encrypted; using (var encryptor = algorithm.CreateEncryptor(keyBytes, iv)) { using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) { cryptoStream.Write(data, 0, data.Length); cryptoStream.FlushFinalBlock(); encrypted = memoryStream.ToArray(); memoryStream.Close(); cryptoStream.Close(); } } } return encrypted; } public static void DecryptFile(SymmetricAlgorithm algorithm, string filePath, string password, string salt, string iv, int? keySize = null, int passwordIterations = 1000) { DecryptFile(algorithm, filePath, Encoding.UTF8.GetBytes(password), Encoding.UTF8.GetBytes(salt), Encoding.UTF8.GetBytes(iv), keySize, passwordIterations); } public static void DecryptFile(SymmetricAlgorithm algorithm, string filePath, byte[] password, byte[] salt, byte[] iv, int? keySize = null, int passwordIterations = 1000) { if (algorithm == null) throw new ArgumentNullException("algorithm"); if (String.IsNullOrEmpty(filePath)) throw new ArgumentException("File path is null or empty", "filePath"); if (!File.Exists(filePath)) throw new FileNotFoundException("File does not exist", filePath); if (password == null || password.Length == 0) throw new ArgumentException("Password is empty", "password"); if (salt == null || salt.Length < 8) throw new ArgumentException("Salt is not at least eight bytes", "salt"); if (iv == null || iv.Length < (algorithm.LegalBlockSizes[0].MinSize / 8)) throw new ArgumentException("Specified initialization vector (IV) does not match the block size for this algorithm", "iv"); var fileBytes = File.ReadAllBytes(filePath); var decryptedBytes = DecryptBytes(algorithm, fileBytes, password, salt, iv, keySize, passwordIterations); File.WriteAllBytes(filePath, decryptedBytes); } public static string DecryptText(SymmetricAlgorithm algorithm, string encryptedText, string password, string salt, string iv, int? keySize = null, int passwordIterations = 1000) { if (algorithm == null) throw new ArgumentNullException("algorithm"); if (String.IsNullOrEmpty(encryptedText)) throw new ArgumentException("Encrypted text are empty", "encryptedText"); if (String.IsNullOrEmpty(password)) throw new ArgumentException("Password is null or empty", "password"); if (String.IsNullOrEmpty(salt) || salt.Length < 8) throw new ArgumentException("Salt is not at least eight bytes", "salt"); if (String.IsNullOrEmpty(iv) || iv.Length < (algorithm.LegalBlockSizes[0].MinSize / 8)) throw new ArgumentException("Specified initialization vector (IV) does not match the block size for this algorithm", "iv"); var decrypted = DecryptBytes(algorithm, Convert.FromBase64String(encryptedText), Encoding.UTF8.GetBytes(password), Encoding.UTF8.GetBytes(salt), Encoding.UTF8.GetBytes(iv), keySize, passwordIterations); return Encoding.UTF8.GetString(decrypted); } public static byte[] DecryptBytes(SymmetricAlgorithm algorithm, byte[] encryptedData, byte[] password, byte[] salt, byte[] iv, int? keySize = null, int passwordIterations = 1000) { if (algorithm == null) throw new ArgumentNullException("algorithm"); if (encryptedData == null || encryptedData.Length == 0) throw new ArgumentException("Encrypted data is null or empty", "encryptedData"); if (password == null || password.Length == 0) throw new ArgumentException("Password is null or empty", "password"); if (salt == null || salt.Length < 8) throw new ArgumentException("Salt is not at least eight bytes", "salt"); if (iv == null || iv.Length < (algorithm.LegalBlockSizes[0].MinSize / 8)) throw new ArgumentException("Specified initialization vector (IV) does not match the block size for this algorithm", "iv"); if (keySize == null) keySize = algorithm.LegalKeySizes[0].MaxSize; byte[] keyBytes; using (var rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt, passwordIterations)) { keyBytes = rfc2898DeriveBytes.GetBytes(keySize.Value / 8); } byte[] plainTextBytes; int decryptedBytesCount; using (var decryptor = algorithm.CreateDecryptor(keyBytes, iv)) { using (var memoryStream = new MemoryStream(encryptedData)) { using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) { plainTextBytes = new byte[encryptedData.Length]; decryptedBytesCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); memoryStream.Close(); cryptoStream.Close(); } } } return plainTextBytes.Take(decryptedBytesCount).ToArray(); } }
Use
// encrypting/decrypting text string text = "text for encryption"; string password = "my secret password"; string salt = "w9=z4]0h"; // at least 8 chars long string iv = "fd98w7z3yupz0q41"; // have to match the algorithm block size - for all cases can be 16 chars using (var aes = Aes.Create()) { string encrypted = SymmetricEncryption.EncryptText(aes, text, password, salt, iv); string decrypted = SymmetricEncryption.DecryptText(aes, encrypted, password, salt, iv); Console.WriteLine("Aes encrypted: {0}", encrypted); Console.WriteLine("Aes decrypted: {0}", decrypted); } Console.WriteLine(); using (var des = DES.Create()) { string encrypted = SymmetricEncryption.EncryptText(des, text, password, salt, iv); string decrypted = SymmetricEncryption.DecryptText(des, encrypted, password, salt, iv); Console.WriteLine("DES encrypted: {0}", encrypted); Console.WriteLine("DES decrypted: {0}", decrypted); } Console.WriteLine(); using (var rc2 = RC2.Create()) { string encrypted = SymmetricEncryption.EncryptText(rc2, text, password, salt, iv); string decrypted = SymmetricEncryption.DecryptText(rc2, encrypted, password, salt, iv); Console.WriteLine("RC2 encrypted: {0}", encrypted); Console.WriteLine("RC2 decrypted: {0}", decrypted); } Console.WriteLine(); using (var rijndael = Rijndael.Create()) { string encrypted = SymmetricEncryption.EncryptText(rijndael, text, password, salt, iv); string decrypted = SymmetricEncryption.DecryptText(rijndael, encrypted, password, salt, iv); Console.WriteLine("Rijndael encrypted: {0}", encrypted); Console.WriteLine("Rijndael decrypted: {0}", decrypted); } Console.WriteLine(); using (var tripleDES = TripleDES.Create()) { string encrypted = SymmetricEncryption.EncryptText(tripleDES, text, password, salt, iv); string decrypted = SymmetricEncryption.DecryptText(tripleDES, encrypted, password, salt, iv); Console.WriteLine("Triple DES encrypted: {0}", encrypted); Console.WriteLine("Triple DES decrypted: {0}", decrypted); } // encrypting/descrypting files using (var rijndael = Rijndael.Create()) { string path = @"C:\Folder\file.jpg"; SymmetricEncryption.EncryptFile(rijndael, path, password, salt, iv); SymmetricEncryption.DecryptFile(rijndael, path, password, salt, iv); }Console Output:
Aes encrypted: 9NIvW9WVC6QE6IYy9Q3HbxxzLc/HiIAni9okcDdsGK8=
Aes decrypted: text for encryption
DES encrypted: gUvAyi47xdNcRt0HGnO8/nqvORBfoLBp
DES decrypted: text for encryption
RC2 encrypted: SW4B1k7Cl5YCEoviM0Lo36VQcDCH9Avh
RC2 decrypted: text for encryption
Rijndael encrypted: 9NIvW9WVC6QE6IYy9Q3HbxxzLc/HiIAni9okcDdsGK8=
Rijndael decrypted: text for encryption
Triple DES encrypted: T009J1U672i53oPsP/a0nT7XmXyptdLr
Triple DES decrypted: text for encryption
Aes decrypted: text for encryption
DES encrypted: gUvAyi47xdNcRt0HGnO8/nqvORBfoLBp
DES decrypted: text for encryption
RC2 encrypted: SW4B1k7Cl5YCEoviM0Lo36VQcDCH9Avh
RC2 decrypted: text for encryption
Rijndael encrypted: 9NIvW9WVC6QE6IYy9Q3HbxxzLc/HiIAni9okcDdsGK8=
Rijndael decrypted: text for encryption
Triple DES encrypted: T009J1U672i53oPsP/a0nT7XmXyptdLr
Triple DES decrypted: text for encryption
| Send us feedback about this snippet » |





