Реализация алгоритма шифрования по ГОСТ 28147-89 - C#
Формулировка задачи:
Добрый день! Пытаюсь реализовать все тот же алгоритм шифрования ГОСТ-89. Уже целую неделю долблюсь, и никак не могу понять, в чем моя ошибка. Значит, вкратце о проекте:
- В основе данного алгоритма лежит основной шаг криптопреобразования. Он реализован в структуре
Механизм зашифровки 32-З реализован в классе
Для расшифровки (32-Р) реализован аналогичный класс
при запуске шифрования на выходе получим исходный файл. Значит, все преобразования, помимо самого шифра работают корректно. Может, я что-то не так понял в самом алгоритме шифрования?
Надеюсь на вашу помощь)
З.Ы.: Весь проект в прикрепленном файле. В папке Debug есть два файла:
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;
- }
- }
- }
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;
- }
- }
- }
D32
, отличается только порядком действий в методе DecryptFile() (1 раз К0-К7 и 3 раза К7-К0). Ошибка скорее всего заключена в самом алгоритме. Как я это понял: Если в методе EncryptFile() оставить только 2 строки
Листинг программы
- ulNewFile[0] = ulongFile[0];
- return ulNewFile;
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;
- }
- }
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д