
- •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
- •Лист регистрации изменений
ByteMixer.Cs
using System;
using System.Threading.Tasks;
namespace VStepanov.CourseWork.First.Binary
{
/// <summary>
/// Статический класс, содержащий методы для "примешивания" и экстракции произвольных данных из исходных.
/// </summary>
public static class ByteMixer
{
/// <summary>
/// Размещает данные сообщения в исходных данных, используя
/// указанное число последних бит исходных данных для изменения.
/// </summary>
/// <param name="originalData">Исходные данные.</param>
/// <param name="dataToMix">Данные, которые необходимо примешать.</param>
/// <param name="nLastBitsUsing">Число последних бит, используемых для записи сообщения.</param>
/// <returns>Исходные данные, последние биты которых содержат данные сообщения.</returns>
/// <exception cref="ArgumentException">Возникает при недостатке исходных данных для записи в них сообщения.</exception>
public static byte[] MixDataIntoBytes(byte[] originalData, byte[] dataToMix, int nLastBitsUsing)
{
byte[] relocatedData = Relocator.Split(dataToMix, nLastBitsUsing);
byte[] mixedData = (byte[])originalData.Clone();
if (mixedData.Length < relocatedData.Length)
{
throw new ArgumentException("Исходных данных не хватает для размещения переданного сообщения.\n");
}
byte ereaser = (byte)~((1 << nLastBitsUsing) - 1);
Parallel.For(0, mixedData.Length, i =>
{
mixedData[i] &= ereaser;
mixedData[i] |= relocatedData[i];
});
return mixedData;
}
/// <summary>
/// Извлекает сообщение из указанного числа последних бит исходных данных.
/// </summary>
/// <param name="container">Исходные данные, содержащие сообщение.</param>
/// <param name="nLastBitsUsing">Число последних бит, используемых для записи сообщения.</param>
/// <returns>Сообщение, извлечённое из последних бит исходных данных.</returns>
public static byte[] ExtractDataFromBytes(byte[] container, int nLastBitsUsing)
{
int parts = CommonMethods.GetPartsCount(nLastBitsUsing);
byte[] clearData = (byte[])container.Clone();
byte ereaser = (byte)((1 << nLastBitsUsing) - 1);
Parallel.For(0, clearData.Length, i => clearData[i] &= ereaser);
return Relocator.Join(clearData, nLastBitsUsing);
}
}
}
Relocator.Cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VStepanov.CourseWork.First.Binary
{
/// <summary>
/// Статический класс, содержащий методы для перераспледеления бит в байтах.
/// </summary>
public static class Relocator
{
/// <summary>
/// Разбивает каждый байт из переданного массива байтов на число частей,
/// соответствующее заданному количеству используемых последних бит,
/// и смещает каждый полученный фрагмент в младшие биты.
/// </summary>
/// <param name="bytes">Исходный массив байт.</param>
/// <param name="nLastBitsUsing">Число используемых последних бит в каждом байте.</param>
/// <returns>Массив байт, содержащий разбитые и сдвинутые исходные байты.</returns>
public static byte[] Split(byte[] bytes, int nLastBitsUsing)
{
int parts = CommonMethods.GetPartsCount(nLastBitsUsing);
byte[] res = new byte[bytes.Length * parts];
Action<int> splitByte = i =>
{
byte b = bytes[i];
for (int j = 0; j < parts; j++)
{
res[i * parts + j] = (byte)(b & ((1 << nLastBitsUsing) - 1));
b >>= nLastBitsUsing;
}
};
Parallel.For(0, bytes.Length, splitByte);
return res;
}
/// <summary>
/// Производит операцию, обратную к производимой методом <see cref="Split"/>.
/// </summary>
/// <param name="bytes">Массив разбитых на части и смещённых байт.</param>
/// <param name="nLastBitsUsing">Число используемых последних бит в каждом байте.</param>
/// <returns>Массив байт, содержащий "собранные обратно" байты из переданного массива.</returns>
public static byte[] Join(byte[] bytes, int nLastBitsUsing)
{
int parts = CommonMethods.GetPartsCount(nLastBitsUsing);
if (bytes.Length % parts != 0)
{
throw new ArgumentException("Возможно, часть данных была утеряна");
}
byte[] res = new byte[bytes.Length / parts];
Action<int> joinByte = i =>
{
for (int j = 0; j < parts; j++)
{
res[i] |= (byte)(bytes[i * parts + j] << (j * nLastBitsUsing));
}
};
Parallel.For(0, res.Length, joinByte);
return res;
}
}
}