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

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;

        }

    }

}