
- •VStepanov.CourseWork.First Common.Cs
- •VStepanov.CourseWork.First.Binary BmpInfo.Cs
- •ByteMixer.Cs
- •Relocator.Cs
- •VStepanov.CourseWork.First.Cryptography
- •XorCodec.Cs
- •VStepanov.CourseWork.First.Steganography Steganogram.Cs
- •SteganogramBmp.Cs
- •SteganogramInfo.Cs
- •SteganogramMessage.Cs
- •VStepanov.CourseWork.First.Gui AnimatedForm.Cs
- •FileAddForm.Cs
- •GuiMethods.Cs
- •PasswordRequest.Cs
- •Program.Cs
- •SplashForm.Cs
- •TextAddForm.Cs
- •TextReadForm.Cs
- •Лист регистрации изменений
VStepanov.CourseWork.First.Cryptography
XorCodec.Cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using VStepanov.CourseWork.First;
[assembly: CLSCompliant(true)]
namespace VStepanov.CourseWork.First.Cryptography
{
/// <summary>
/// Статический класс, реализующий XOR-шифрование.
/// Защита от статистического взлома усилена тем, что в качестве ключа используется повторяющийся SHA512-хеш от пароля.
/// </summary>
public static class XorCodec
{
/// <summary>
/// Длинна хеша SHA512 в байтах.
/// </summary>
private const int Sha512Length = 64;
/// <summary>
/// Рассчитывает количество полных повторений хеша и остаток, необходимое для того чтобы сравнять длину сообщения и длинну ключа.
/// </summary>
/// <param name="message">Сообщение, для которого необходимо сгенерировать ключ.</param>
/// <returns>Двухэлементный кортеж - количество полных повторений хеша и необходимый остаток, чтобы сравнять длину сообщения и длинну ключа.</returns>
private static Tuple<int, int> ComputeKeyLength(byte[] message)
{
int lengthOfMessage = message.Length;
int countOfRepeats = lengthOfMessage / Sha512Length;
int remainder = lengthOfMessage % Sha512Length;
return new Tuple<int, int>(countOfRepeats, remainder);
}
/// <summary>
/// Генерирует массив-ключ из заданного пароля.
/// </summary>
/// <param name="password">Пароль, на основе которого будет составлен ключ шифрования.</param>
/// <param name="keyLengthParameters">Двухэлементный кортеж, содержащий параметры ключа.</param>
/// <returns>Массив-ключ, сгенерированный на основе заданного пароля.</returns>
private static byte[] GenerateKeyArray(string password, Tuple<int, int> keyLengthParameters)
{
var hasherSha512 = new SHA512Managed();
byte[] passwordAsBytes = Encoding.Unicode.GetBytes(password);
byte[] passwordHash = hasherSha512.ComputeHash(passwordAsBytes);
hasherSha512.Dispose();
return CommonMethods.ExpandArray(passwordHash, keyLengthParameters.Item1, keyLengthParameters.Item2);
}
/// <summary>
/// Зашифровывает массив байт заданным ключом.
/// </summary>
/// <param name="message">Массив байт для шифровки.</param>
/// <param name="password">Пароль, которым будет производиться шифрование.</param>
/// <returns>Исходный массив байт, зашифрованный переданным паролем.</returns>
public static byte[] Encrypt(byte[] message, string password)
{
var keyLengthParameters = ComputeKeyLength(message);
byte[] key = GenerateKeyArray(password, keyLengthParameters);
byte[] encryptedMessage = (byte[])message.Clone();
Parallel.For(0, message.Length, i => encryptedMessage[i] ^= key[i]);
return encryptedMessage;
}
/// <summary>
/// Расшифровывает массив байт заданным ключом.
/// </summary>
/// <param name="message">Массив байт для шифровки.</param>
/// <param name="password">Пароль, которым будет производиться дешифровка.</param>
/// <returns>Исходный массив байт, расшифрованный переданным паролем.</returns>
public static byte[] Decrypt(byte[] message, string password)
{
var keyLengthParameters = ComputeKeyLength(message);
byte[] key = GenerateKeyArray(password, keyLengthParameters);
byte[] decryptedMessage = (byte[])message.Clone();
Parallel.For(0, message.Length, i => decryptedMessage[i] ^= key[i]);
return decryptedMessage;
}
}
}