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