174 lines
5.2 KiB
C#
174 lines
5.2 KiB
C#
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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)
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|