Реализация алгоритма шифрования по ГОСТ 28147-89 - C#

Узнай цену своей работы

Формулировка задачи:

Добрый день! Пытаюсь реализовать все тот же алгоритм шифрования ГОСТ-89. Уже целую неделю долблюсь, и никак не могу понять, в чем моя ошибка. Значит, вкратце о проекте: - В основе данного алгоритма лежит основной шаг криптопреобразования. Он реализован в структуре

BasicSteep

:
using System;
 
namespace Crypto
{
    struct BasicStep
    {
        uint N1, N2, X;
 
        public BasicStep(ulong dateFragment, uint keyFragment) 
        {
            N1 = (uint)(dateFragment >> 32);     //Младшая часть файла
            N2 = (uint)((dateFragment << 32) >> 32);     //Старшая часть файла
            X = keyFragment;
        }
 
        public ulong BasicEncrypt()
        {
            return (FourthAndFifthStep(ThirdStep(SecondStep(FirstStep()))));
        }
        
        //Сложение по модулю 2^32 младшей части с фрагментом ключа
        private uint FirstStep()
        {
            return (uint)((X + N1) % (Convert.ToUInt64(Math.Pow(2, 32)))); 
        }
        
        //Использование таблицы замены
        private uint SecondStep(uint S)
        {
            uint newS, S0, S1, S2, S3, S4, S5, S6, S7;
            
            //Разбиваем младшую часть файла на 8 4-х битовых чисел
            S0 = S >> 28;
            S1 = (S << 4) >> 28;
            S2 = (S << 8) >> 28;
            S3 = (S << 12) >> 28;
            S4 = (S << 16) >> 28;
            S5 = (S << 20) >> 28;
            S6 = (S << 24) >> 28;
            S7 = (S << 28) >> 28;
 
            //Производим замену по таблице замен
            S0 = ReplacementTab.Table0[S0];
            S1 = ReplacementTab.Table0[0x10 + S1];
            S2 = ReplacementTab.Table0[0x20 + S2];
            S3 = ReplacementTab.Table0[0x30 + S3];
            S4 = ReplacementTab.Table0[0x40 + S4];
            S5 = ReplacementTab.Table0[0x50 + S5];
            S6 = ReplacementTab.Table0[0x60 + S6];
            S7 = ReplacementTab.Table0[0x70 + S7];
 
            //Склеиваем 4-х битовые числа в одно 32-х битовое
            newS = S7 + (S6 << 4) + (S5 << 8) + (S4 << 12) + (S3 << 16) +
                    (S2 << 20) + (S1 << 24) + (S0 << 28);
 
            return newS;
        }
 
        //Циклический сдвиг на 11 бит влево
        private uint ThirdStep(uint S)
        {
            return (uint) (S << 11) | (S >> 21);
        }
 
        private ulong FourthAndFifthStep(uint S)
        {
            ulong N;
            
            S = (N2 ^ S);        //Сложение по модулю 2 старшего фрагмента данных с полученным из.... 
                                       //... ThirdStep() числом
            //Сдвиг по цепочке
            N2 = N1;
            N1 = S;
 
            //Склеиваем младший и старший фрагмент в один 64-х битовый блок данных
            N = ((ulong)N2) | (((ulong)N1) << 32);
 
            return N;
        }
    }
}
Механизм зашифровки 32-З реализован в классе

E32

:
using System;
 
namespace Crypto
{
    class E32
    {
        static E32 e32 = null;
        byte[] byteFile, byteKey, encrByteFile;
        uint[] uintKey;
        ulong[] ulongFile, ulNewFile;
 
        private E32() { }
 
        private E32(byte[] file, byte[] key)
        {
            byteFile = file;
            byteKey = key;
 
            //Создание массива из 32-х битовых фрагментов ключа
            DatePartition part = new DatePartition(byteKey, DatePartition.FileType.Key);
            uintKey = part.GetKey;
 
            //Создание массива из 64-х битовых фрагментов данных
            part = new DatePartition(byteFile, DatePartition.FileType.File);
            ulongFile = part.GetFile;
 
            ulNewFile = ulongFile;
 
            //Получение зашифрованного фрагмента данных в виде байт-массива encrByteFile[]
            ConvertToByte(EncryptFile());
        }
 
        //Публичное свойство для получения зашифрованного байт-массива
        public byte[] GetEncryptFile
        {
            get { return encrByteFile; }
        }
     
        //Публичный метод для получения единственного экземпляра объекта класса
        public static E32 StartE32(byte[] file, byte[] key)
        {
            if (e32 == null)
                e32 = new E32(file, key);
            
            return e32;
        }
 
        //Непосредственная реализация 32-З (3 раза К0-К7 и 1 раз К7-К0)
        private ulong[] EncryptFile()
        {
            BasicStep[] K = new BasicStep[8];
            ulNewFile[0] = ulongFile[0];
 
            for (int j = 0; j < 3; j++)
            {
                for (int i = 0; i < K.Length; i++)
                {
                    K[i] = new BasicStep(ulNewFile[0], uintKey[i]);
                    ulNewFile[0] = K[i].BasicEncrypt();
                }
            }
 
            for (int i = K.Length - 1; i >= 0; i--)
            {
                K[i] = new BasicStep(ulNewFile[0], uintKey[i]);
                ulNewFile[0] = K[i].BasicEncrypt();
            }
 
            return ulNewFile;
        }
 
        //Метод для конвертации массива ulong в байт-массив
        private void ConvertToByte(ulong[] fl)
        {
            byte[] newFile = new byte[8];
            uint part1, part2;
            string str, str1, str2;
            string[] arrStr = new string[8];
 
            part1 = (uint)(fl[0] >> 32);
            part2 = (uint)((fl[0] << 32) >> 32);
 
            str1 = Convert.ToString(part1, 2);
            while (str1.Length < 32)
                str1 = "0" + str1;
 
            str2 = Convert.ToString(part2, 2);
            while (str2.Length < 32)
                str2 = "0" + str2;
 
            str = str1 + str2;
 
            int count = 0;
 
            for (int i = 0; i < str.Length; i++)
            {
                if ((i % 8 == 0) && (i != 0))
                    count++;
 
                arrStr[count] += str[i];
            }
 
            for (int i = 0; i < arrStr.Length; i++)
            {
                newFile[i] = Convert.ToByte(arrStr[i], 2);
            }
 
            encrByteFile = newFile;
        }
    }
}
Для расшифровки (32-Р) реализован аналогичный класс

D32

, отличается только порядком действий в методе DecryptFile() (1 раз К0-К7 и 3 раза К7-К0). Ошибка скорее всего заключена в самом алгоритме. Как я это понял: Если в методе EncryptFile() оставить только 2 строки
ulNewFile[0] = ulongFile[0];
return ulNewFile;
при запуске шифрования на выходе получим исходный файл. Значит, все преобразования, помимо самого шифра работают корректно. Может, я что-то не так понял в самом алгоритме шифрования? Надеюсь на вашу помощь) З.Ы.: Весь проект в прикрепленном файле. В папке Debug есть два файла:

1.txt

- 8-ми байтовый текстовый файл для зашифровки и файл

key

- 256-битовый файл ключа.

Решение задачи: «Реализация алгоритма шифрования по ГОСТ 28147-89»

textual
Листинг программы
using System;
 
namespace Crypto
{
    struct BasicStep
    {
        uint N1, N2, X;
 
        public BasicStep(ulong dateFragment, uint keyFragment)
        {
            N1 = (uint)(dateFragment >> 32);
            N2 = (uint)((dateFragment << 32) >> 32);
            X = keyFragment;
        }
 
        public ulong BasicEncrypt(bool IsLastStep)
        {
            return (FourthAndFifthStep(IsLastStep, ThirdStep(SecondStep(FirstStep()))));
        }
 
        private uint FirstStep()
        {
            return (uint)((X + N1) % (Convert.ToUInt64(Math.Pow(2, 32))));
        }
 
        private uint SecondStep(uint S)
        {
            uint newS, S0, S1, S2, S3, S4, S5, S6, S7;
 
            S0 = S >> 28;
            S1 = (S << 4) >> 28;
            S2 = (S << 8) >> 28;
            S3 = (S << 12) >> 28;
            S4 = (S << 16) >> 28;
            S5 = (S << 20) >> 28;
            S6 = (S << 24) >> 28;
            S7 = (S << 28) >> 28;
 
            S0 = ReplacementTab.Table0[S0];
            S1 = ReplacementTab.Table0[0x10 + S1];
            S2 = ReplacementTab.Table0[0x20 + S2];
            S3 = ReplacementTab.Table0[0x30 + S3];
            S4 = ReplacementTab.Table0[0x40 + S4];
            S5 = ReplacementTab.Table0[0x50 + S5];
            S6 = ReplacementTab.Table0[0x60 + S6];
            S7 = ReplacementTab.Table0[0x70 + S7];
 
            newS = S7 + (S6 << 4) + (S5 << 8) + (S4 << 12) + (S3 << 16) +
                    (S2 << 20) + (S1 << 24) + (S0 << 28);
 
            return newS;
        }
 
        private uint ThirdStep(uint S)
        {
            return (uint)(S << 11) | (S >> 21);
        }
 
        //Теперь принимает в качестве параметра IsLastStep
        private ulong FourthAndFifthStep(bool IsLastStep, uint S)
        {
            ulong N;
 
            S = (S ^ N2);
 
            //Если шаг последний - сдвиг по цепочке не производится
            if (!IsLastStep) 
            {
                N2 = N1;
                N1 = S;
            }
            else
                N2 = S;
 
            N = ((ulong)N2) | (((ulong)N1) << 32);
 
            return N;
        }
    }
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

7   голосов , оценка 3.714 из 5
Похожие ответы