using System;
using System.Text;
using System.Security.Cryptography;
namespace Inputs.ComSystem
{
///
/// Статический класс для AES-256 ECB шифрования/дешифрования
/// Используется для двойного рукопожатия с платами ESP32
///
public static class AESCrypto
{
// Зашифрованный AES ключ (XOR 0x37) - как в прошивке платы
private static readonly byte[] AES_ENCRYPTED_KEY = new byte[]
{
0x69, 0x40, 0xC7, 0x0E, 0xF2, 0xC7, 0x45, 0x70,
0x72, 0xCD, 0x28, 0x58, 0x99, 0x8F, 0x73, 0xA8,
0x5F, 0x5F, 0xED, 0xB4, 0xC1, 0x62, 0xB4, 0x24,
0xAC, 0xD7, 0xA3, 0xD6, 0xD8, 0x0B, 0x50, 0x37
};
private static byte[] _aesKey32;
private static readonly object _lockObject = new object();
///
/// Инициализация AES ключа (расшифровка через XOR 0x37)
/// Вызывается автоматически при первом использовании
///
private static void InitCrypto()
{
lock (_lockObject)
{
if (_aesKey32 == null)
{
_aesKey32 = new byte[32];
for (int i = 0; i < 32; i++)
{
_aesKey32[i] = (byte)(AES_ENCRYPTED_KEY[i] ^ 0x37);
}
}
}
}
///
/// Шифрует 16-байтный блок (32 hex символа)
///
public static string EncryptHexBlock16(string plainHex)
{
InitCrypto();
byte[] plain = HexToBytes(plainHex);
if (plain.Length != 16)
throw new ArgumentException("Plain must be 16 bytes (32 hex chars)");
byte[] cipher = Aes256EcbEncrypt(plain);
return BytesToHex(cipher);
}
///
/// Расшифровывает 16-байтный блок (32 hex символа)
///
public static string DecryptHexBlock16(string cipherHex)
{
InitCrypto();
byte[] cipher = HexToBytes(cipherHex);
if (cipher.Length != 16)
throw new ArgumentException("Cipher must be 16 bytes (32 hex chars)");
byte[] plain = Aes256EcbDecrypt(cipher);
return BytesToHex(plain);
}
///
/// Генерирует случайный 16-байтный блок (32 hex символа)
///
public static string GenerateRandomBlock16Hex()
{
byte[] buffer = new byte[16];
using (var rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(buffer);
}
return BytesToHex(buffer);
}
// ========== Приватные методы AES ==========
private static byte[] Aes256EcbEncrypt(byte[] data)
{
using (var aes = Aes.Create())
{
aes.Key = _aesKey32;
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.None;
using (var encryptor = aes.CreateEncryptor())
{
return encryptor.TransformFinalBlock(data, 0, data.Length);
}
}
}
private static byte[] Aes256EcbDecrypt(byte[] data)
{
using (var aes = Aes.Create())
{
aes.Key = _aesKey32;
aes.Mode = CipherMode.ECB;
aes.Padding = PaddingMode.None;
using (var decryptor = aes.CreateDecryptor())
{
return decryptor.TransformFinalBlock(data, 0, data.Length);
}
}
}
// ========== Hex конвертация ==========
private static byte[] HexToBytes(string hex)
{
hex = hex.Trim();
if (hex.Length % 2 != 0)
throw new ArgumentException("Hex string length must be even");
byte[] result = new byte[hex.Length / 2];
for (int i = 0; i < result.Length; i++)
{
result[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return result;
}
private static string BytesToHex(byte[] bytes)
{
StringBuilder sb = new StringBuilder(bytes.Length * 2);
foreach (byte b in bytes)
{
sb.AppendFormat("{0:X2}", b);
}
return sb.ToString();
}
}
}