using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace AxCopilot.Services; public static class CryptoService { private static readonly byte[] AppSeed = new byte[32] { 65, 88, 45, 67, 111, 109, 109, 97, 110, 100, 101, 114, 45, 75, 101, 121, 45, 48, 49, 48, 52, 45, 115, 106, 46, 98, 97, 101, 99, 107, 167, 92 }; private static readonly byte[] AppSalt = new byte[16] { 88, 67, 77, 68, 83, 97, 108, 116, 158, 39, 193, 74, 179, 6, 127, 216 }; private static byte[]? _appKey; private static byte[] GetAppKey() { if (_appKey != null) { return _appKey; } using Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(AppSeed, AppSalt, 100000, HashAlgorithmName.SHA256); _appKey = rfc2898DeriveBytes.GetBytes(32); return _appKey; } public static string PortableEncrypt(string plainText) { if (string.IsNullOrEmpty(plainText)) { return ""; } byte[] appKey = GetAppKey(); using Aes aes = Aes.Create(); aes.Key = appKey; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; aes.GenerateIV(); using ICryptoTransform cryptoTransform = aes.CreateEncryptor(); byte[] bytes = Encoding.UTF8.GetBytes(plainText); byte[] array = cryptoTransform.TransformFinalBlock(bytes, 0, bytes.Length); byte[] array2 = new byte[16 + array.Length]; Buffer.BlockCopy(aes.IV, 0, array2, 0, 16); Buffer.BlockCopy(array, 0, array2, 16, array.Length); return Convert.ToBase64String(array2); } public static string PortableDecrypt(string base64) { if (string.IsNullOrEmpty(base64)) { return ""; } try { byte[] array = Convert.FromBase64String(base64); if (array.Length < 17) { return ""; } byte[] appKey = GetAppKey(); byte[] array2 = new byte[16]; Buffer.BlockCopy(array, 0, array2, 0, 16); byte[] array3 = new byte[array.Length - 16]; Buffer.BlockCopy(array, 16, array3, 0, array3.Length); using Aes aes = Aes.Create(); aes.Key = appKey; aes.IV = array2; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; using ICryptoTransform cryptoTransform = aes.CreateDecryptor(); byte[] bytes = cryptoTransform.TransformFinalBlock(array3, 0, array3.Length); return Encoding.UTF8.GetString(bytes); } catch { return ""; } } public static string EncryptIfEnabled(string plainText, bool encryptionEnabled) { return encryptionEnabled ? PortableEncrypt(plainText) : plainText; } public static string DecryptIfEnabled(string value, bool encryptionEnabled) { if (string.IsNullOrEmpty(value)) { return ""; } if (!encryptionEnabled) { return value; } string text = PortableDecrypt(value); return string.IsNullOrEmpty(text) ? value : text; } private static byte[] GetOrCreateMasterKey() { string text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot"); string path = Path.Combine(text, ".master_key"); if (File.Exists(path)) { byte[] encryptedData = File.ReadAllBytes(path); return ProtectedData.Unprotect(encryptedData, null, DataProtectionScope.CurrentUser); } byte[] bytes = RandomNumberGenerator.GetBytes(32); Directory.CreateDirectory(text); File.WriteAllBytes(path, ProtectedData.Protect(bytes, null, DataProtectionScope.CurrentUser)); return bytes; } public static byte[] EncryptBytes(byte[] plainBytes) { byte[] orCreateMasterKey = GetOrCreateMasterKey(); byte[] bytes = RandomNumberGenerator.GetBytes(12); byte[] array = new byte[16]; byte[] array2 = new byte[plainBytes.Length]; using AesGcm aesGcm = new AesGcm(orCreateMasterKey, 16); aesGcm.Encrypt(bytes, plainBytes, array2, array); byte[] array3 = new byte[28 + array2.Length]; Buffer.BlockCopy(bytes, 0, array3, 0, 12); Buffer.BlockCopy(array, 0, array3, 12, 16); Buffer.BlockCopy(array2, 0, array3, 28, array2.Length); return array3; } public static byte[] DecryptBytes(byte[] encrypted) { if (encrypted.Length < 28) { throw new CryptographicException("Invalid encrypted data"); } byte[] orCreateMasterKey = GetOrCreateMasterKey(); byte[] array = new byte[12]; byte[] array2 = new byte[16]; byte[] array3 = new byte[encrypted.Length - 28]; Buffer.BlockCopy(encrypted, 0, array, 0, 12); Buffer.BlockCopy(encrypted, 12, array2, 0, 16); Buffer.BlockCopy(encrypted, 28, array3, 0, array3.Length); byte[] array4 = new byte[array3.Length]; using AesGcm aesGcm = new AesGcm(orCreateMasterKey, 16); aesGcm.Decrypt(array, array3, array2, array4); return array4; } public static void EncryptToFile(string filePath, string content) { byte[] bytes = Encoding.UTF8.GetBytes(content); byte[] bytes2 = EncryptBytes(bytes); File.WriteAllBytes(filePath, bytes2); } public static string DecryptFromFile(string filePath) { if (!File.Exists(filePath)) { return ""; } byte[] encrypted = File.ReadAllBytes(filePath); byte[] bytes = DecryptBytes(encrypted); return Encoding.UTF8.GetString(bytes); } }