Files

177 lines
4.9 KiB
C#

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);
}
}