145 lines
4.5 KiB
C#

using System;
using System.Text;
using System.Security.Cryptography;
namespace Inputs.ComSystem
{
/// <summary>
/// Ñòàòè÷åñêèé êëàññ äëÿ AES-256 ECB øèôðîâàíèÿ/äåøèôðîâàíèÿ
/// Èñïîëüçóåòñÿ äëÿ äâîéíîãî ðóêîïîæàòèÿ ñ ïëàòàìè ESP32
/// </summary>
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();
/// <summary>
/// Èíèöèàëèçàöèÿ AES êëþ÷à (ðàñøèôðîâêà ÷åðåç XOR 0x37)
/// Âûçûâàåòñÿ àâòîìàòè÷åñêè ïðè ïåðâîì èñïîëüçîâàíèè
/// </summary>
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);
}
}
}
}
/// <summary>
/// Øèôðóåò 16-áàéòíûé áëîê (32 hex ñèìâîëà)
/// </summary>
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);
}
/// <summary>
/// Ðàñøèôðîâûâàåò 16-áàéòíûé áëîê (32 hex ñèìâîëà)
/// </summary>
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);
}
/// <summary>
/// Ãåíåðèðóåò ñëó÷àéíûé 16-áàéòíûé áëîê (32 hex ñèìâîëà)
/// </summary>
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();
}
}
}