177 lines
4.9 KiB
C#
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);
|
|
}
|
|
}
|