using System.Security.Cryptography; using System.Text; namespace ServiceLib.Common { public class AesUtils { private const int KeySize = 256; // AES-256 private const int IvSize = 16; // AES block size private const int Iterations = 10000; private static readonly byte[] Salt = Encoding.ASCII.GetBytes("saltysalt".PadRight(16, ' ')); // google浏览器默认盐值 private static readonly string DefaultPassword = Utils.GetMd5(Utils.GetHomePath() + "AesUtils"); /// /// Encrypt /// /// Plain text /// Password for key derivation or direct key in ASCII bytes /// Base64 encoded cipher text with IV public static string Encrypt(string text, string? password = null) { if (string.IsNullOrEmpty(text)) return string.Empty; var plaintext = Encoding.UTF8.GetBytes(text); var key = GetKey(password); var iv = GenerateIv(); using var aes = Aes.Create(); aes.Key = key; aes.IV = iv; using var ms = new MemoryStream(); ms.Write(iv, 0, iv.Length); using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(plaintext, 0, plaintext.Length); cs.FlushFinalBlock(); } var cipherTextWithIv = ms.ToArray(); return Convert.ToBase64String(cipherTextWithIv); } /// /// Decrypt /// /// Base64 encoded cipher text with IV /// Password for key derivation or direct key in ASCII bytes /// Plain text public static string Decrypt(string cipherTextWithIv, string? password = null) { if (string.IsNullOrEmpty(cipherTextWithIv)) return string.Empty; var cipherTextWithIvBytes = Convert.FromBase64String(cipherTextWithIv); var key = GetKey(password); var iv = new byte[IvSize]; Buffer.BlockCopy(cipherTextWithIvBytes, 0, iv, 0, IvSize); var cipherText = new byte[cipherTextWithIvBytes.Length - IvSize]; Buffer.BlockCopy(cipherTextWithIvBytes, IvSize, cipherText, 0, cipherText.Length); using var aes = Aes.Create(); aes.Key = key; aes.IV = iv; using var ms = new MemoryStream(); using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write)) { cs.Write(cipherText, 0, cipherText.Length); cs.FlushFinalBlock(); } var plainText = ms.ToArray(); return Encoding.UTF8.GetString(plainText); } private static byte[] GetKey(string? password) { if (password.IsNullOrEmpty()) { password = DefaultPassword; } using var pbkdf2 = new Rfc2898DeriveBytes(password, Salt, Iterations, HashAlgorithmName.SHA256); return pbkdf2.GetBytes(KeySize / 8); } private static byte[] GenerateIv() { var randomNumber = new byte[IvSize]; using var rng = RandomNumberGenerator.Create(); rng.GetBytes(randomNumber); return randomNumber; } } }