Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Текст программы.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
102.68 Кб
Скачать

SteganogramMessage.Cs

using System;

using System.Linq;

using System.Text;

using System.IO;

using VStepanov.CourseWork.First.Cryptography;

namespace VStepanov.CourseWork.First.Steganography

{

    /// <summary>

    /// Задаёт константы, определяющие тип сообщения.

    /// </summary>

    [Flags]

    public enum MessageType

    {

        /// <summary>

        /// Сообщение содержит текстовые данные.

        /// </summary>

        Text      = 0x01,

        /// <summary>

        /// Сообщение содержит двоичный файл.

        /// </summary>

        File      = 0x02,

        /// <summary>

        /// Сообщение зашифровано.

        /// </summary>

        Encrypted = 0x04

    }

    /// <summary>

    /// Структура, описывающая стеганографическое сообщение.

    /// </summary>

    public struct SteganogramMessage

    {

        #region Константы

        /// <summary>

        /// Число байт для хранения типа сообщения.

        /// </summary>

        private const int MessageTypeLength   = 1;

        /// <summary>

        /// Число байт для хранения расширения файла.

        /// </summary>

        private const int FileExtensionLength = 8;

        /// <summary>

        /// Число байт для хранения информации о сообщении.

        /// </summary>

        public static readonly int MessageHeaderSize = MessageTypeLength + FileExtensionLength;

        #endregion

        #region Поля

        private string _fileExtension;

        /// <summary>

        /// Расширение файла. Всегда занимает размер в 8 байт, при необходимости дополняется пробелами слева.

        /// </summary>

        public string FileExtension

        {

            get { return _fileExtension; }

            set { _fileExtension = value.PadLeft(FileExtensionLength).Substring(0, FileExtensionLength); }

        }

        /// <summary>

        /// Тип сообщения.

        /// </summary>

        public MessageType MessageType { get; set; }

        private byte[] _data;

        /// <summary>

        /// Байты сообщения.

        /// </summary>

        public byte[] Data

        {

            get { return _data.ToArray(); }

            private set { _data = value; }

        }

        #endregion

        #region Конструкторы

        /// <summary>

        /// Создаёт открытое сообщение.

        /// </summary>

        /// <param name="data">Данные сообщения.</param>

        private SteganogramMessage(byte[] data)

        {

            this = new SteganogramMessage();

            Data = data;

        }

        /// <summary>

        /// Создаёт зашифрованное заданным паролем сообщение.

        /// </summary>

        /// <param name="data">Данные сообщения.</param>

        /// <param name="password">Пароль, которым будет зашифровано сообщение.</param>

        private SteganogramMessage(byte[] data, string password)

        {

            this = new SteganogramMessage();

            Data = data;

            EncryptMessage(password);

        }

        #region Из строки с сообщением

        /// <summary>

        /// Создаёт текстовое сообщение.

        /// </summary>

        /// <param name="s">Текст, подлежащий стеганографированию.</param>

        /// <returns>Сообщение, содержащее текст, переданный в параметре s.</returns>

        public static SteganogramMessage FromString(string s)

        {

            byte[] data = Encoding.UTF8.GetBytes(s);

            var message  = new SteganogramMessage(data);

            message.MessageType |= MessageType.Text;

            message.FileExtension = String.Empty;

            return message;

        }

        /// <summary>

        /// Создаёт зашифрованное паролем текстовое сообщение.

        /// </summary>

        /// <param name="s">Текст, подлежащий стеганографированию.</param>

        /// <param name="password">Пароль, которым будет зашифрованно сообщение.</param>

        /// <returns>Сообщение, содержащее текст, переданный в параметре s, зашифрованный паролем password.</returns>

        public static SteganogramMessage FromString(string s, string password)

        {

            byte[] data = Encoding.UTF8.GetBytes(s);

            var message  = new SteganogramMessage(data, password);

            message.MessageType |= MessageType.Text;

            message.FileExtension = String.Empty;

            return message;

        } 

        #endregion

        #region Из файла

        /// <summary>

        /// Создаёт сообщение, содержащее данные из произвольного файла.

        /// </summary>

        /// <param name="file">Информация о файле, который необходимо поместить в сообщение.</param>

        /// <returns>Сообщение, содержащее данные из файла, заданного параметром file.</returns>

        public static SteganogramMessage FromFile(FileInfo file)

        {

            byte[] data;

            using (BinaryReader br = new BinaryReader(file.OpenRead()))

            {

                data = br.ReadBytes((int)file.Length);

            }

            var message = new SteganogramMessage(data);

            message.MessageType |= MessageType.File;

            message.FileExtension = file.Extension;

            return message;

        }

        /// <summary>

        /// Создаёт зашифрованное паролем сообщение, содержащее данные из произвольного файла.

        /// </summary>

        /// <param name="file">Информация о файле, который необходимо поместить в сообщение.</param>

        /// <param name="password">Пароль, которым будет зашифрованно сообщение.</param>

        /// <returns>Сообщение, содержащее данные из файла, заданного параметром file, зашифрованные паролем password.</returns>

        public static SteganogramMessage FromFile(FileInfo file, string password)

        {

            byte[] data;

            using (BinaryReader br = new BinaryReader(file.OpenRead()))

            {

                data = br.ReadBytes((int)file.Length);

            }

            var message = new SteganogramMessage(data, password);

            message.MessageType |= MessageType.File;

            message.FileExtension = file.Extension;

            return message;

        }  

        #endregion

        #endregion

        #region Работа с дампами

        /// <summary>

        /// Переводит структуру в массив байт, пригодный для записи и обратного конвертирования в структуру.

        /// </summary>

        /// <param name="steganogramMessage">Структура для перекодировки.</param>

        /// <returns>Массив байт, представляющий собой переданную структуру.</returns>

        public static byte[] GetBytes(SteganogramMessage steganogramMessage)

        {

            byte[] data = new byte[MessageHeaderSize + steganogramMessage.Data.Length];

            data[0] = (byte)steganogramMessage.MessageType;

            Encoding.UTF8.GetBytes(steganogramMessage.FileExtension).CopyTo(data, MessageTypeLength);

            steganogramMessage.Data.CopyTo(data, MessageHeaderSize);

            return data;

        }

        /// <summary>

        /// Переводит массив байт в структуру.

        /// </summary>

        /// <param name="bytes">Массив байт, представляющий собой структуру.</param>

        /// <returns>Структура SteganogramInfo, восстановленная из переданного массива байт.</returns>

        public static SteganogramMessage FromBytes(byte[] bytes)

        {

            SteganogramMessage message = new SteganogramMessage();

            message.MessageType = (MessageType)bytes[0];

            message.FileExtension = Encoding.UTF8.GetString(bytes.Skip(MessageTypeLength).Take(FileExtensionLength).ToArray());

            message.Data = bytes.Skip(MessageHeaderSize).ToArray();

            return message;

        } 

        #endregion

        #region Шифровка/дешифровка сообщения

        /// <summary>

        /// Шифровка сообщения указанным ключом.

        /// </summary>

        /// <param name="password">Ключ шифрования.</param>

        public void EncryptMessage(string password)

        {

            if (!MessageType.HasFlag(MessageType.Encrypted))

            {

                Data = XorCodec.Encrypt(Data, password);

                MessageType |= MessageType.Encrypted;

            }

        }

        /// <summary>

        /// Дешифровка сообщения указанным ключом.

        /// </summary>

        /// <param name="password">Ключ шифрования.</param>

        public void DecryptMessage(string password)

        {

            if (MessageType.HasFlag(MessageType.Encrypted))

            {

                Data = XorCodec.Decrypt(Data, password);

                MessageType &= ~MessageType.Encrypted;

            }

        }   

        #endregion

    }

}