using System;
using System.IO;
using System.Text;
using System.IO.Compression;
using System.Xml.Serialization;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
namespace Library.Cryptography
{
public class CryptoDB
{
public GZipStream gzip = null; //Поток для сжатия gzip
public MemoryStream ms = null; //Поток для отдачи класса
public StreamReader sr = null; //Поток для отдачи класса
public CryptoStream crypt = null; //Криптография данных
public void Dispose()
{
if (crypt != null)
{
try
{
crypt.FlushFinalBlock();
}
catch { }
crypt = null;
}
if (gzip != null)
{
try
{
gzip.Close(); gzip.Dispose(); gzip = null;
}
catch { }
}
if (ms != null)
{
try
{
ms.Close(); ms.Dispose(); ms = null;
}
catch { }
}
if (sr != null)
{
try
{
sr.Close(); sr.Dispose(); sr = null;
}
catch { }
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////############# Временные данные для обработки запросов криптографии #############/////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private static Rijndael aes = CreateAES(); //Ключ AES256
private static string dir = Environment.CurrentDirectory + @"\tmp\"; //Дириктория
private static Rijndael CreateAES(string key = "defaultAESkey256")
{
byte[] IVa = new byte[] { 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x11, 0x12, 0x13, 0x14, 0x0e, 0x16, 0x17 };
Rfc2898DeriveBytes deriveBytes = new Rfc2898DeriveBytes(Encoding.UTF8.GetString(IVa, 0, IVa.Length), Encoding.UTF8.GetBytes(key));
Rijndael _aes = new RijndaelManaged();
_aes.Key = deriveBytes.GetBytes(256 / 16);
_aes.IV = _aes.Key;
IVa = null; deriveBytes = null;
return _aes;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////############# Работа с данными, запись данных в файл, формат xml #############/////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Имя базы
/// Данные для сохранения
/// Криптовать содержимое файла или нет
/// Прятать имя базы данных под md5
public static void Write(string dbName, object data, bool crypto = true, bool MD5 = false)
{
try
{
//Путь к файлу xml
string FileCry = (dir + (MD5 ? md5.text(dbName) : dbName));
//Создаем каталог для данных
Directory.CreateDirectory(dir);
//Записываем файл
File.WriteAllBytes(FileCry, Write(data, crypto));
//Создаем бекап файла
File.Copy(FileCry, (dir + (MD5 ? md5.text(dbName + ".tmp") : (dbName + ".tmp"))), true);
//Чистим ресурсы
FileCry = null;
}
catch { }
//Чистим ресурсы
dbName = null; data = null;
}
/// Данные для конвертирования в byte[]
/// Криптовать содержимое файла или нет
public static byte[] Write(object data, bool crypto = true)
{
//Класс для работы с данными
CryptoDB cryptoDB = new CryptoDB();
byte[] res = null;
try
{
//Создаем xml в виде String
XmlSerializer xmlSerializer = new XmlSerializer(data.GetType());
StringWriter textWriter = new StringWriter();
xmlSerializer.Serialize(textWriter, data);
//Создаем xml формат
if (crypto)
{
//Записываем криптованную базу xml
cryptoDB.ms = new MemoryStream(); //Поток для записи данных в файл
cryptoDB.crypt = new CryptoStream(cryptoDB.ms, aes.CreateEncryptor(), CryptoStreamMode.Write); //Записывает шифрованные данные в поток ms
cryptoDB.gzip = new GZipStream(cryptoDB.crypt, CompressionMode.Compress); //Запаковываем в gzip
//Записываем в поток все данные
byte[] mass = Encoding.UTF8.GetBytes(textWriter.ToString());
cryptoDB.gzip.Write(mass, 0, mass.Length);
//Чистим ресурсы
cryptoDB.gzip.Close(); cryptoDB.gzip.Dispose(); cryptoDB.gzip = null;
cryptoDB.crypt.Close(); cryptoDB.crypt.Dispose(); cryptoDB.crypt = null;
mass = null;
//Записываем результат
res = cryptoDB.ms.ToArray();
}
else
{
//Записываем не криптованную базу xml
res = Encoding.UTF8.GetBytes(textWriter.ToString());
}
//Чистим ресурсы
textWriter.Close(); textWriter.Flush(); textWriter.Dispose(); textWriter = null; xmlSerializer = null;
}
catch { }
//Чистим ресурсы
cryptoDB.Dispose(); cryptoDB = null; data = null;
return res;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////############# Работа с данными, чтение данных из файла в формате json #############/////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Сериализация
/// Имя базы
/// Расшифровывать содержимое файла или нет
/// Имя файла указанно в формате md5
public static T Read(string dbName, bool crypto = true, bool MD5 = false) where T : new()
{
T result = default(T);
try
{
string FileCry = (dir + (MD5 ? md5.text(dbName) : dbName));
Reset: result = Read(File.ReadAllBytes(FileCry), crypto);
if (result == null)
{
//Берем данные из бекапа
if (FileCry != (dir + (MD5 ? md5.text(dbName + ".tmp") : (dbName + ".tmp"))))
{
FileCry = (dir + (MD5 ? md5.text(dbName + ".tmp") : (dbName + ".tmp")));
goto Reset;
}
}
//Чистим ресурсы
FileCry = null;
}
catch { }
//Чистим ресурсы и возвращаем результат
dbName = null;
return (result == null ? new T() : result);
}
/// Сериализация
/// Содержимое для конвертации в класс
/// Расшифровывать содержимое или нет
public static T Read(byte[] sourse, bool crypto = true, bool EroorNull = false) where T : new()
{
//Класс для работы с данными
CryptoDB cryptoDB = new CryptoDB();
T result = default(T);
try
{
XmlSerializer deserializer = new XmlSerializer(typeof(T));
if (crypto)
{
//Считываем криптованную базу xml
cryptoDB.ms = new MemoryStream(sourse); //Считываем массив
cryptoDB.crypt = new CryptoStream(cryptoDB.ms, aes.CreateDecryptor(), CryptoStreamMode.Read); //Расшифровываем массив
cryptoDB.gzip = new GZipStream(cryptoDB.crypt, CompressionMode.Decompress, true); //Распаковываем gzip
cryptoDB.sr = new StreamReader(cryptoDB.gzip); //хз, но получаем типа string
result = (T)deserializer.Deserialize(cryptoDB.sr); //Возвращаем класс после обработчки xml
}
else
{
//Считываем не криптованную базу xml
cryptoDB.ms = new MemoryStream(sourse);
TextReader textReader = new StreamReader(cryptoDB.ms);
result = (T)deserializer.Deserialize(textReader);
textReader.Close(); textReader.Dispose(); textReader = null;
}
deserializer = null;
}
catch { }
//Чистим ресурсы и возвращаем результат
cryptoDB.Dispose(); cryptoDB = null; sourse = null;
if (EroorNull) { return result; } else { return (result == null ? new T() : result); }
}
}
}