hellbound/Assets/Scripts/Core/Utils/Crypto.cs

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