using System; using System.IO; using System.Security.Cryptography; using System.Text; public static class Hash { static byte[] hash_bytes = new byte[512]; static public uint CRC32(string id) { //NOTE: avoiding memory allocations: using static memory buffer, // avoding string contacation var encoding = System.Text.Encoding.ASCII; int byte_len = encoding.GetByteCount(id); var buffer = byte_len <= hash_bytes.Length ? hash_bytes : new byte[byte_len]; encoding.GetBytes(id, 0, id.Length, buffer, 0); return Crc32.Compute(buffer, id.Length); } static public uint CRC32(Stream s) { return Crc32.Compute(s); } static public uint CRC32File(string path) { FileStream fs = File.OpenRead(path); uint fcrc = CRC32(fs); fs.Close(); return fcrc; } static public bool CheckFileCRC32(string path, uint crc) { try { uint fcrc = CRC32File(path); if(fcrc != crc) { Log.Error("File CRC32 error: " + path + " " + fcrc + " VS " + crc); return false; } else { Log.Debug("File CRC32 OK: " + path); return true; } } catch(Exception) { return false; } } static public uint CRC28(string id) { return CRC32(id) & 0xFFFFFFF; } static public uint CRC20(string id) { return CRC32(id) & 0xFFFFF; } static public uint CRC32(byte[] bytes) { return Crc32.Compute(bytes, bytes.Length); } static public uint CRC28(byte[] bytes) { return CRC32(bytes) & 0xFFFFFFF; } static public uint CRC20(byte[] bytes) { return CRC32(bytes) & 0xFFFFF; } } /// /// AES (Advanced Encryption Standard) implementation with 128-bit key (default) /// - 128-bit AES is approved by NIST, but not the 256-bit AES /// - 256-bit AES is slower than the 128-bit AES (by about 40%) /// - Use it for secure data protection /// - Do NOT use it for data protection in RAM (in most common scenarios) /// public static class AES { public static int KeyLength = 128; // TODO: Generate random VI each encryption and store it with encrypted value //private const string SaltKey = "ShMG8hLyZ7k~Ge5@"; //private const string VIKey = "~6YUi0Sv5@|{aOZO"; private const string SaltKey = "ShxG8hLyZ@k~3e5@"; private const string VIKey = "~6,UB0Sv5@|{aO8O"; public static string Encrypt(byte[] value, string password) { var keyBytes = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(SaltKey)).GetBytes(KeyLength / 8); var symmetricKey = new RijndaelManaged { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros }; var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.UTF8.GetBytes(VIKey)); using (var memoryStream = new MemoryStream()) { using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) { cryptoStream.Write(value, 0, value.Length); cryptoStream.FlushFinalBlock(); cryptoStream.Close(); memoryStream.Close(); return Convert.ToBase64String(memoryStream.ToArray()); } } } public static string Encrypt(string value, string password) { return Encrypt(Encoding.UTF8.GetBytes(value), password); } public static string Decrypt(string value, string password) { var cipherTextBytes = Convert.FromBase64String(value); var keyBytes = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(SaltKey)).GetBytes(KeyLength / 8); var symmetricKey = new RijndaelManaged { Mode = CipherMode.CBC, Padding = PaddingMode.None }; var decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.UTF8.GetBytes(VIKey)); using (var memoryStream = new MemoryStream(cipherTextBytes)) { using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)) { var plainTextBytes = new byte[cipherTextBytes.Length]; var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length); memoryStream.Close(); cryptoStream.Close(); return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount).TrimEnd("\0".ToCharArray()); } } } public static int Encrypt(Stream src, Stream dst, string password) { var keyBytes = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(SaltKey)).GetBytes(KeyLength / 8); var symmetricKey = new RijndaelManaged { Mode = CipherMode.CBC, Padding = PaddingMode.Zeros }; var encryptor = symmetricKey.CreateEncryptor(keyBytes, Encoding.UTF8.GetBytes(VIKey)); int total = 0; using (var cryptoStream = new CryptoStream(dst, encryptor, CryptoStreamMode.Write)) { total = src.CopyToEx(cryptoStream); cryptoStream.FlushFinalBlock(); } return total; } public static int Decrypt(Stream src, Stream dst, string password) { var keyBytes = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(SaltKey)).GetBytes(KeyLength / 8); var symmetricKey = new RijndaelManaged { Mode = CipherMode.CBC, Padding = PaddingMode.None }; var decryptor = symmetricKey.CreateDecryptor(keyBytes, Encoding.UTF8.GetBytes(VIKey)); int total = 0; using (var cryptoStream = new CryptoStream(src, decryptor, CryptoStreamMode.Read)) { total = cryptoStream.CopyToEx(dst); } return total; } }