Криптография, работа с хешами

Дата публикации: 31.01.2011
Дата редактирования: 01.02.2011
Состояние: завершена

    Написал для себя статический класс, содержащий в себе набор методов, предназначенных для работы с MD5-хешами, а так же набор методов по шифрованию и дешифровке (пригодятся для сокрытия содержимого конфигурационных файлов от шаловливых ручек некоторых пользователей). Имена и описания методов вполне понятно описывают их назначение, потому не буду заниматься дополнительным описанием и приведением примеров их использования.

Исходный код (C# 3.0):

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.IO;
   6:  using System.Security.Cryptography;
   7:  using System.Xml.Linq;
   8:  using System.Xml;
   9:   
  10:  namespace Bushman.Security.Cryptography {
  11:   
  12:      /// <summary>
  13:      /// В классе собраны различные методы по шифрованию и расшифровыванию данных, проверки их контрольных 
  14:      /// сумм, генерации ключей, векторов инициализаций и т.п.
  15:      /// </summary>
  16:      public static class Security {
  17:          /// <summary>
  18:          /// Получение строкового значения MD5-хеша для файла.
  19:          /// </summary>
  20:          /// <param name="fileName">Имя файла, MD5-хэш которого необходимо получить</param>
  21:          /// <returns>Строковое значение MD5-хэша</returns>
  22:          public static string GetFileMD5Hash(string fileName) {
  23:              if (!File.Exists(fileName))
  24:                  throw new FileNotFoundException(string.Format(Resource.FileNotFound, fileName));
  25:   
  26:              System.Security.Cryptography.MD5 x = System.Security.Cryptography.MD5.Create();
  27:              byte[] data = null;
  28:              using (FileStream fs = new FileStream(fileName, FileMode.Open)) {
  29:                  data = x.ComputeHash(fs);
  30:              }
  31:              StringBuilder sBuilder = new StringBuilder();
  32:              for (int i = 0; i < data.Length; i++)
  33:                  sBuilder.Append(data[i].ToString("x2"));
  34:   
  35:              return sBuilder.ToString();
  36:          }
  37:   
  38:          /// <summary>
  39:          /// Получение строкового значения MD5-хеша для строки.
  40:          /// </summary>
  41:          /// <param name="text">строка, MD5-хэш которой необходимо получить</param>
  42:          /// <returns>Строковое значение MD5-хэша</returns>
  43:          public static string GetStringMD5Hash(string text) {
  44:              MD5 md5Hasher = MD5.Create();
  45:              byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(text));
  46:   
  47:              StringBuilder sBuilder = new StringBuilder();
  48:              for (int i = 0; i < data.Length; i++) {
  49:                  sBuilder.Append(data[i].ToString("x2"));
  50:              }
  51:              return sBuilder.ToString();
  52:          }
  53:   
  54:          /// <summary>
  55:          /// Проверка того, соответствует ли MD5-хэш указанного файла тому MD5-хешу, строковое значение которого передаётся для сравнения
  56:          /// </summary>
  57:          /// <param name="fileName">Имя файла, MD5-хэш которого нужно проверить</param>
  58:          /// <param name="md5hash">Строковое значение оригинального MD5-хеша</param>
  59:          /// <returns>True - хеши совпадают. False - не совпадают</returns>
  60:          public static bool VerifyMd5Hash(string fileName, string md5hash) {
  61:              if (!File.Exists(fileName))
  62:                  throw new FileNotFoundException(Resource.FileNotFound, fileName);
  63:              string hashOfInput = GetFileMD5Hash(fileName);
  64:   
  65:              StringComparer comparer = StringComparer.OrdinalIgnoreCase;
  66:              if (0 == comparer.Compare(hashOfInput, md5hash)) {
  67:                  return true;
  68:              }
  69:              return false;
  70:          }
  71:   
  72:          /// <summary>
  73:          /// Сохранение массива байтов в файл. С помощью этого метода можно сохранять во
  74:          /// внешний файл ключ симметричного шифрования или вектор инициализации.
  75:          /// </summary>
  76:          /// <param name="bytes">Массив байтов, которые необходимо сохранить в файл</param>
  77:          /// <param name="keyFileName">Имя файла</param>
  78:          public static void SaveBytesToFile(byte[] bytes, string keyFileName) {
  79:              using (FileStream fs = new FileStream(keyFileName, FileMode.CreateNew, FileAccess.Write)) {
  80:                  fs.Write(bytes, 0, bytes.Length);
  81:                  fs.Close();
  82:              }
  83:          }
  84:          /// <summary>
  85:          /// Считывание массива байтов из файла. С помощью этого метода можно извлекать из
  86:          /// внешнего файла ключ симметричного шифрования или вектор инициализации.
  87:          /// </summary>
  88:          /// <param name="fileName">Имя файла</param>
  89:          /// <returns>Массив байтов</returns>
  90:          public static byte[] GetBytesFromFile(string fileName) {
  91:              using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) {
  92:                  byte[] bytes = new byte[fs.Length];
  93:                  fs.Read(bytes, 0, (int)fs.Length);
  94:                  fs.Close();
  95:                  return bytes;
  96:              }
  97:          }
  98:   
  99:          /// <summary>
 100:          /// Генерация строки, которую можно использовать в качестве произвольного имени для файла
 101:          /// </summary>
 102:          /// <param name="byteSize">Размер в байтах</param>
 103:          /// <returns>Сгенерированная строка</returns>
 104:          public static string GenerateString(int byteSize) {
 105:              byte[] bytes = new byte[255];
 106:              RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
 107:              rand.GetBytes(bytes);
 108:              return BitConverter.ToUInt64(bytes, 0).ToString("X");
 109:          }
 110:   
 111:          /// <summary>
 112:          /// Получение строкового представления массива байтов в формате шестнадцатеричных символов
 113:          /// </summary>
 114:          /// <param name="bytes">Массив байтов</param>
 115:          /// <returns>Результат представлен в формате шестнадцатеричных символов</returns>
 116:          public static string GetHexString(byte[] bytes) {
 117:              StringBuilder sb = new StringBuilder();
 118:              sb.Append("0x");
 119:              foreach (byte item in bytes) {
 120:                  sb.Append(item.ToString("X"));
 121:              }
 122:              return sb.ToString();
 123:          }
 124:          /// <summary>
 125:          /// Получение строкового представления массива байтов в формате кодировки Base64
 126:          /// </summary>
 127:          /// <param name="bytes">Массив байтов</param>
 128:          /// <returns>Результат представлен в формате кодировки Base64</returns>
 129:          public static string GetBase64String(byte[] bytes) {
 130:              return Convert.ToBase64String(bytes);
 131:          }
 132:   
 133:          /// <summary>
 134:          /// Шифрование текстового файла симметричным ключом
 135:          /// </summary>
 136:          /// <param name="symmetricKey">Симметричный ключ</param>
 137:          /// <param name="iv">Вектор инициализации</param>
 138:          /// <param name="sourceFileName">Имя файла, содержимое которого требуется зашифровать</param>
 139:          /// <param name="resultFileName">Имя файла, в котором должен быть сохранён результат шифрования</param>
 140:          public static void EncriptingFile(byte[] symmetricKey, byte[] iv, string sourceFileName, string resultFileName) {
 141:              using (FileStream unencryptedFile = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read)) {
 142:                  using (FileStream encryptedFile = new FileStream(resultFileName, FileMode.OpenOrCreate, FileAccess.Write)) {
 143:                      RijndaelManaged myAlg = new RijndaelManaged();
 144:                      myAlg.Key = symmetricKey;
 145:                      myAlg.IV = iv;
 146:                      byte[] fileData = new byte[unencryptedFile.Length];
 147:                      unencryptedFile.Read(fileData, 0, (int)unencryptedFile.Length);
 148:                      ICryptoTransform encryptor = myAlg.CreateEncryptor();
 149:                      using (CryptoStream encruptStream = new CryptoStream(encryptedFile, encryptor, CryptoStreamMode.Write)) {
 150:                          encruptStream.Write(fileData, 0, (int)unencryptedFile.Length);
 151:   
 152:                          encruptStream.Close();
 153:                      }
 154:                      encryptedFile.Close();
 155:                  }
 156:                  unencryptedFile.Close();
 157:              }
 158:   
 159:          }
 160:   
 161:          /// <summary>
 162:          /// Расшифровать текстовый файл симметричным ключом и сохранить результат в новом файле.
 163:          /// </summary>
 164:          /// <param name="symmetricKey">Симметричный ключ</param>
 165:          /// <param name="iv">Вектор инициализации</param>
 166:          /// <param name="sourceFileName">Имя зашифрованного файла</param>
 167:          /// <param name="resultFileName">Имя файла, в котором должен быть сохранён расшифрованный результат</param>
 168:          /// <param name="encoding">Кодировка, которую следует использовать</param>
 169:          public static void UnencriptingFile(byte[] symmetricKey, byte[] iv, string sourceFileName, string resultFileName, Encoding encoding) {
 170:              using (FileStream unencryptedFile = new FileStream(resultFileName, FileMode.Create, FileAccess.Write)) {
 171:                  using (FileStream encryptedFile = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read)) {
 172:                      //Создаём объект синхронного шифрования и назначаем ему ключ и вектор инициализации
 173:                      RijndaelManaged myAlg = new RijndaelManaged();
 174:                      myAlg.Key = symmetricKey;
 175:                      myAlg.IV = iv;
 176:                      //Создаём объект-дешифратор
 177:                      ICryptoTransform unencryptor = myAlg.CreateDecryptor();
 178:                      //Расшифровываем информацию и записываем её в новый файл
 179:                      using (CryptoStream encruptStream = new CryptoStream(encryptedFile, unencryptor, CryptoStreamMode.Read)) {
 180:                          //Read the stream.
 181:                          StreamReader SReader = new StreamReader(encruptStream, encoding);
 182:                          byte[] bytes = new byte[encryptedFile.Length];
 183:                          StreamWriter sw = new StreamWriter(unencryptedFile);
 184:                          sw.Write(SReader.ReadToEnd());
 185:                          sw.Flush();
 186:                          sw.Close();
 187:                          SReader.Close();
 188:                          encruptStream.Close();
 189:                      }
 190:                      encryptedFile.Close();
 191:                  }
 192:                  unencryptedFile.Close();
 193:              }
 194:          }
 195:   
 196:          /// <summary>
 197:          /// Расшифровать текстовый файл симметричным ключом и сохранить результат в потоке MemoryStream.
 198:          /// </summary>
 199:          /// <param name="symmetricKey">Симметричный ключ</param>
 200:          /// <param name="iv">Вектор инициализации</param>
 201:          /// <param name="sourceFileName">Имя зашифрованного файла</param>
 202:          /// <param name="encoding">Кодировка, которую следует использовать</param>
 203:          /// <returns>Расшифрованные данные возвращаются в потоке</returns>
 204:          public static MemoryStream UnencriptingFileToStream(byte[] symmetricKey, byte[] iv, string sourceFileName, Encoding encoding) {
 205:              MemoryStream ms = new MemoryStream();
 206:              using (FileStream encryptedFile = new FileStream(sourceFileName, FileMode.Open, FileAccess.Read)) {
 207:                  //Создаём объект синхронного шифрования и назначаем ему ключ и вектор инициализации
 208:                  RijndaelManaged myAlg = new RijndaelManaged();
 209:                  myAlg.Key = symmetricKey;
 210:                  myAlg.IV = iv;
 211:                  //Создаём объект-дешифратор
 212:                  ICryptoTransform unencryptor = myAlg.CreateDecryptor();
 213:                  //Расшифровываем информацию и записываем её в новый файл
 214:                  using (CryptoStream encruptStream = new CryptoStream(encryptedFile, unencryptor, CryptoStreamMode.Read)) {
 215:                      StreamReader SReader = new StreamReader(encruptStream, encoding);
 216:                      StreamWriter sw = new StreamWriter(ms);
 217:                      string xxx = SReader.ReadToEnd();
 218:                      sw.Write(xxx);
 219:                      sw.Flush();
 220:                      ms.Position = 0;
 221:                      sw.Close();
 222:                      SReader.Close();
 223:                      encruptStream.Close();                    
 224:                  }
 225:                  encryptedFile.Close();
 226:              }
 227:              return ms;
 228:          }
 229:      }
 230:  }


Comments