using System; using System.IO; using System.Security.Cryptography; // https://stackoverflow.com/a/2791259 // AES-256-CBC public class Crypto { /* notes: - key size = 256 bits (32 bytes) - block/iv size = 128 bits (16 bytes) */ private static void WriteBytes(byte[] bytes) { for (int i = 0; i < bytes.Length; i++) { byte b = bytes[i]; Console.Write("0x" + b.ToString("x2")); bool last = i == bytes.Length - 1; Console.Write(last ? Environment.NewLine : ", "); } } // https://www.random.org/bytes/ private static byte[] _salt = { 0x28, 0x7c, 0x6a, 0xa2, 0x2e, 0xa6, 0x46, 0x4b, 0x68, 0xef, 0x91, 0xec, 0x0e, 0x8c, 0x3e, 0x50 }; public static string EncryptString(string plainText, string sharedSecret) { string outStr = null; RijndaelManaged algorithm = null; try { Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt); algorithm = new RijndaelManaged(); algorithm.Key = key.GetBytes(algorithm.KeySize / 8); // 32 bytes for a key ICryptoTransform encryptor = algorithm.CreateEncryptor(algorithm.Key, algorithm.IV); using (MemoryStream msEncrypt = new MemoryStream()) { msEncrypt.Write(algorithm.IV, 0, algorithm.IV.Length); using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) swEncrypt.Write(plainText); outStr = Convert.ToBase64String(msEncrypt.ToArray()); } } finally { if (algorithm != null) algorithm.Clear(); } return outStr; } public static string DecryptString(string cipherText, string sharedSecret) { RijndaelManaged algorithm = null; string plaintext = null; try { Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt); byte[] bytes = Convert.FromBase64String(cipherText); using (MemoryStream msDecrypt = new MemoryStream(bytes)) { algorithm = new RijndaelManaged(); algorithm.Key = key.GetBytes(algorithm.KeySize / 8); algorithm.IV = DeriveIV(msDecrypt, algorithm.BlockSize / 8); ICryptoTransform decryptor = algorithm.CreateDecryptor(algorithm.Key, algorithm.IV); using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) using (StreamReader srDecrypt = new StreamReader(csDecrypt)) plaintext = srDecrypt.ReadToEnd(); } } finally { if (algorithm != null) algorithm.Clear(); } return plaintext; } private static byte[] DeriveIV(Stream s, int length) { byte[] iv = new byte[length]; if (s.Read(iv, 0, length) != length) throw new Exception("Failed to derive IV from stream."); return iv; } }