using System; using System.Text; using System.Security.Cryptography; using System.Linq; namespace Deckard.Jared { /// /// AES256 class uses the AES algorithm with a provided 256 bit key and a random 128 bit IV to meet PCI standards /// The IV is randomly generated before each encryption and encoded with the final encrypted string /// public class AES256 { // Symmetric algorithm interface is used to store the AES service provider private SymmetricAlgorithm AESProvider; /// /// Constructor for AES class that takes a byte array for the key /// /// 256 bit key (32 bytes) public AES256(byte[] key) { // Throw error if key is not 256 bits if (key.Length != 32) throw new CryptographicException("Key must be 256 bits (32 bytes)"); // Initialize AESProvider with AES algorithm service AESProvider = new AesCryptoServiceProvider(); AESProvider.KeySize = 256; // Set the key for AESProvider AESProvider.Key = key; } /// /// Constructor for AES class that generates the key from a hashed, salted password /// /// Password used to generate the key (Minimum of 8 characters) /// Salt used to secure hash from rainbow table attacks (Minimum of 8 characters) public AES256(string password, string salt) { // Throw error if the password or salt are too short if (password.Length < 8) throw new CryptographicException("Password must be at least 8 characters long"); if (salt.Length < 8) throw new CryptographicException("Salt must be at least 8 characters long"); // Initialize AESProvider with AES algorithm service AESProvider = new AesCryptoServiceProvider(); AESProvider.KeySize = 256; // Initialize a hasher with the 256 bit SHA algorithm SHA256 sha256 = System.Security.Cryptography.SHA256.Create(); // Hash salted password byte[] key = sha256.ComputeHash(UnicodeEncoding.Unicode.GetBytes(password + salt)); // Set the key for AESProvider AESProvider.Key = key; } /// /// Encrypts a string with AES algorithm /// /// String to encrypt /// Encrypted string with IV prefix public string Encrypt(string plainText) { // Create new random IV AESProvider.GenerateIV(); // Initialize encryptor now that the IV is set ICryptoTransform encryptor = AESProvider.CreateEncryptor(); // Convert string to bytes byte[] plainBytes = UnicodeEncoding.Unicode.GetBytes(plainText); // Encrypt plain bytes byte[] secureBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length); // Add IV to the beginning of the encrypted bytes secureBytes = AESProvider.IV.Concat(secureBytes).ToArray(); // Return encrypted bytes as a string return Convert.ToBase64String(secureBytes); } /// /// Decrypts a string with AES algorithm /// /// Encrypted string with IV prefix /// Decrypted string public string Decrypt(string secureText) { // Convert encrypted string to bytes byte[] secureBytes = Convert.FromBase64String(secureText); // Take IV from beginning of secureBytes AESProvider.IV = secureBytes.Take(16).ToArray(); // Initialize decryptor now that the IV is set ICryptoTransform decryptor = AESProvider.CreateDecryptor(); // Decrypt bytes after the IV byte[] plainBytes = decryptor.TransformFinalBlock(secureBytes, 16, secureBytes.Length - 16); // Return decrypted bytes as a string return UnicodeEncoding.Unicode.GetString(plainBytes); } } }