Реализация алгоритма шифрования по ГОСТ 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; } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д