Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.77/140: Рейтинг темы: голосов - 140, средняя оценка - 4.77
35 / 10 / 6
Регистрация: 12.06.2013
Сообщений: 24
1

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

02.03.2014, 20:16. Просмотров 28453. Ответов 13
Метки нет (Все метки)


Добрый день! Пытаюсь реализовать все тот же алгоритм шифрования ГОСТ-89. Уже целую неделю долблюсь, и никак не могу понять, в чем моя ошибка. Значит, вкратце о проекте:
- В основе данного алгоритма лежит основной шаг криптопреобразования. Он реализован в структуре BasicSteep:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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 строки
C#
1
2
ulNewFile[0] = ulongFile[0];
return ulNewFile;
при запуске шифрования на выходе получим исходный файл. Значит, все преобразования, помимо самого шифра работают корректно. Может, я что-то не так понял в самом алгоритме шифрования?
Надеюсь на вашу помощь)

З.Ы.: Весь проект в прикрепленном файле. В папке Debug есть два файла: 1.txt - 8-ми байтовый текстовый файл для зашифровки и файл key - 256-битовый файл ключа.
3
Вложения
Тип файла: zip Crypto.zip (82.2 Кб, 399 просмотров)
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
02.03.2014, 20:16
Ответы с готовыми решениями:

Алгоритм шифрования ГОСТ 28147-89. Режим простой замены
Реализовывал алгоритм по wiki. Но что то не то получилось.Вот код: using System; using...

Нужны исходники программы шифрования и дешифрования файлов на базе алгоритма ГОСТ 28147-89
у кого есть исходники программы шифрования и дешифрования файлов на базе алгоритма ГОСТ 28147-89 в...

Реализация шифра ГОСТ 28147-89
Всем привет. Вот решил загнаться комбинированной системой шифрования с шифрами ГОСТ 28147-89 и RSA....

Реализация алгоритма ГОСТ Р 34.10-94
Есть ли у кого-нибудь исходник программы, реализующую данный алгоритм?

13
35 / 10 / 6
Регистрация: 12.06.2013
Сообщений: 24
03.03.2014, 00:21  [ТС] 2
Всем спасибо, ошибку нашел, все работает. Если кому будет интересно - выложу исправленный код.
0
Администратор
Эксперт .NET
9014 / 4289 / 744
Регистрация: 17.04.2012
Сообщений: 9,095
Записей в блоге: 14
03.03.2014, 11:49 3
Andoku, был бы очень признателен за работающий код. Можете выложить сюда
0
35 / 10 / 6
Регистрация: 12.06.2013
Сообщений: 24
03.03.2014, 13:58  [ТС] 4
Лучший ответ Сообщение было отмечено tezaurismosis как решение

Решение

tezaurismosis, без проблем. Ошибка была таки в алгоритме. Оказывается, последний шаг 32-З и 32-Р должен отличаться от предыдущих 31-го тем, что в нем не производится сдвиг по цепочке в конце.
Помимо этого исправления, провел рефакторинг кода, полностью сменил GUI (планирую развивать дальше, ввести режим гаммирования и имитовставки). Итак, структура BasicStep (изменения прокомментированы):
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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;
        }
    }
}

Класс реализации 32-З:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using System;
 
namespace Crypto
{
    class E32 : Converter    //Реализован класс Converter для преобразования данных
    {
        byte[] encrByteFile;
        uint[] uintKey;
        ulong[] ulongFile;
 
        private E32() { }
 
        public E32(byte[] file, byte[] key)
        {
            //Все 3 метода - методы класса Converter
            uintKey = GetUIntKeyArray(key);
            ulongFile = GetULongDataArray(file);
 
            encrByteFile = ConvertToByte(EncryptFile());
        }
 
        public byte[] GetEncryptFile
        {
            get { return encrByteFile; }
        }
 
        private ulong[] EncryptFile()
        {
            BasicStep[] K = new BasicStep[8];
            ulong[] ulongEncrFile = new ulong[ulongFile.Length];
            
            //Добавлен внешний цикл for для реализации возможности шифровать любые... 
            //...массивы данных, кратные 8 байтам
            for (int k = 0; k < ulongFile.Length; k++) 
            {
                ulongEncrFile[k] = ulongFile[k];
 
                for (int j = 0; j < 3; j++)
                {
                    for (int i = 0; i < K.Length; i++)
                    {
                        K[i] = new BasicStep(ulongEncrFile[k], uintKey[i]);
                        ulongEncrFile[k] = K[i].BasicEncrypt(false);
                    }
                }
 
                for (int i = K.Length - 1; i >= 0; i--)
                {
                    K[i] = new BasicStep(ulongEncrFile[k], uintKey[i]);
 
                    if (i != 0)
                        ulongEncrFile[k] = K[i].BasicEncrypt(false);
                    else      //Если шаг последний, передать true
                        ulongEncrFile[k] = K[i].BasicEncrypt(true); 
                }
            }
 
            return ulongEncrFile;
        }
    }
}

Проект в прикрепленном файле. Пока что работают только 4 кнопки:
1. Load для загрузки ключа из файла key.
2. Load для загрузки файла для шифрования.
3. Encrypt для запуска шифрования.
4. Decrypt для расшифровки.
3
Вложения
Тип файла: zip Crypto2.zip (81.3 Кб, 1694 просмотров)
6228 / 3529 / 898
Регистрация: 28.10.2010
Сообщений: 5,926
03.03.2014, 19:27 5
Andoku, ты молодец. В шифровании не смыслю, но если это то, то наверное имело смысл унаследоваться от SymmetricAlgorithm.

P.S. а для устрашения класс назвать SovietUnionAlgorithm
0
35 / 10 / 6
Регистрация: 12.06.2013
Сообщений: 24
03.03.2014, 22:30  [ТС] 6
Петррр, спасибо Да, он самый - ГОСТ 28147-89. Только я тоже в криптографии никакой, буквально 2 недели назад начал копаться. Вон про тот же SymmetricAlgorithm впервые от тебя услышал.

З.Ы.: SovietUnionAlgorithm - ага, и главное на гитхабе им посветить, а то наши люди такого не боятся
0
3 / 2 / 1
Регистрация: 13.05.2013
Сообщений: 234
24.10.2014, 21:25 7
Здравствуйте! Подскажите, пожалуйста, как адаптировать данный код для шифрования файлов? Не очень понимаю как это переделать(
0
4 / 4 / 0
Регистрация: 18.09.2008
Сообщений: 47
25.10.2014, 01:55 8
Andoku, заметил такое поведение программы - вводим допустим слово "велоцираптор", делаем Encrypt и Decrypt, и на выходе имеем "велоцира".
0
35 / 10 / 6
Регистрация: 12.06.2013
Сообщений: 24
30.10.2014, 00:04  [ТС] 9
Сколько времени прошло, а тема еще жива

DEMON_RUS, алгоритм работает с массивом байтов. Все, что вам нужно сделать - это преобразовать нужный файл в этот массив и скормить программе.

ReM, это потому, что в том файле реализован только режим простой замены. Текст разбивается на блоки по 8 байт, остальное отбрасывается. Чтобы этого не было, нужна реализация гаммирования, тогда можно будет работать с любыми размерами текста и одинаковые куски текста будут иметь разный вид в зашифрованном виде.
Оно пишется достаточно просто, вот ссылка на доработанную версию.
0
3 / 2 / 1
Регистрация: 13.05.2013
Сообщений: 234
28.01.2015, 19:14 10
Andoku, Привет Разбирал вашу прогу последнюю "Crypto2.zip" и нашел такое: шифруем значит исходный файл, получаем шифрованный (в вашем случае текст, в моем файл - не суть). Берем этот шифрованный и снова шифруем - получаем чудом исходный) Класс D-32 вообще нигде не используется как я понял.. Но тем не менее всё работает каким-то образом..) Подскажи, пожалуйста, может я что неправильно понимаю, аль где недоглядел..)
0
3 / 2 / 1
Регистрация: 13.05.2013
Сообщений: 234
11.02.2015, 19:44 11
Может кто увидит, может кто поможет.. Разбирал программу последнюю по ссылке https://github.com/ViatcheslawS/Crypto
Переделал её под свои нужды (проект прикрепил) и выявил, что шифрование идёт неверно (если зашифровать исходный файл и потом снова этот зашифрованный файл ещё раз зашифровать - получаем нормальный исходный файл, что неверно)
Пытался найти ошибку в отладчике - ввиду отсутствия опыта в программировании выявить ошибку самостоятельно мне не удалось.. Помогите разобраться, или подскажите каким способом можно это сделать (через отладчик к сожалению не смог( ) Может есть какие-нибудь проверочные данные, которые уже подсчитаны или что-то подобное..

Зацепка, которую тоже не смог применить в поиске ошибки: если зашифровать текст из 16 символов "0123456789ABCDEF", то после шифрования в файл будет писать следующий массив(фото1). Первые 8 байт различные цифры, а последующие 8 - почему-то нули..
если же зашифровать текст из 17 символов "0123456789ABCDEFG", то после шифрования в файл будет писать уже следующий массив(фото2).
Help
0
Миниатюры
Реализация алгоритма шифрования по ГОСТ 28147-89   Реализация алгоритма шифрования по ГОСТ 28147-89  
Вложения
Тип файла: rar gost_28147-89.rar (94.5 Кб, 288 просмотров)
3 / 2 / 1
Регистрация: 13.05.2013
Сообщений: 234
12.02.2015, 01:27 12
Вообщем благодаря этой интересной статье разобрался что да как, может кому пригодится) Там есть примеры шифрования и реализации. (На языке "Глагол") И теперь знаю, что расшифрование в режиме гаммирования производится точно также, как и зашифрование, то есть функция зашифрования является одновременно и функцией расшифрования
0
0 / 0 / 0
Регистрация: 21.04.2012
Сообщений: 4
16.02.2015, 17:23 13
Andoku, Andoku, режим гаммирования и имитовставки получился?
0
0 / 0 / 0
Регистрация: 27.11.2013
Сообщений: 3
25.06.2015, 11:43 14
Здравствуйте.
У меня есть несколько реализаций Основного шага (Р32). Первый я нашел вот здесь - Алгоритм шифрования ГОСТ 28147-89. Режим простой замены и второй вот здесь http://habrahabr.ru/post/256843/

Не смотря на то, что второй вариант мне показался более правильным при зашифровке и расшифровке правильный результат выводит только первый.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
 {
           var result = new byte[8];
         UInt32 a = BitConverter.ToUInt32(N, 0);
         UInt32 b = BitConverter.ToUInt32(N, 4);
 
         List<UInt32> key2 = new List<UInt32>(); 
           key2 = ecript ? CreateKeysZ() : CreateKeysR();        
         
 
         for (int x = 0; x < 32; x++)
         {
            // if (x == 24) key2.Reverse();
             var fValue = f( (a + (UInt32)key2[x] % uint.MaxValue));
             var round = b ^ fValue;
             if (x < 31)
             {
                 b = a;
                 a = round;
             }
             else
             {
                 b = round;
             }
         }
 var output = new byte[8];
         var N1buff = BitConverter.GetBytes(a);
         var N2buff = BitConverter.GetBytes(b);
 
         for (int i = 0; i < 4; i++)
         {
             output[i] = N1buff[i];
             output[4 + i] = N2buff[i];
         }
}
 
public static UInt32 f(UInt32 x)
        {        
           byte index,sBlock;
           uint result = 0;
           for (int i = 0; i < 4; i++ )
           {      
               index = (byte)(x >> (8 * i) & 0x0f);
               sBlock = tables[i][index];
               result |= (uint)sBlock << (8 * i);
           }
 
            /* Rotate left 11 bits */
           return result << 11 | result >> (21);
        }
В блоке замены я делю код не по 4 бита, а по 8 (это не мое решение, вынужден так делать). В остальном все как по ГОСТУ. Подскажите, что здесь не правильно. Лично я не вижу ошибок. Заранее благодарен за ответ.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.06.2015, 11:43

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.

Реализация шифрования по ГОСТ 28147-89
Добрый день. Возникла необходимость реализовать данный алгоритм шифрования. Изучил труды Винокурова...

Рализовать Si блок алгоритма шифрования ГОСТ 28147
Задание 1. Рализовать Si блок алгоритма шифрования ГОСТ 28147

алгоритм шифрования ГОСТ 28147-89
писалось на коленке за 1 день. режим простой замены.для имитовставки воспользоваться 2 раундами....

Алгоритм шифрования ГОСТ 28147-89
Всем привет, реализую алгоритм данный алгоритм шифрования, хотелось бы прояснить пару моментов. Не...

Алгоритм симметричного шифрования ГОСТ 28147-89
Доброго времени суток, товарищи. Вот такую задачку подкинули по информационной безопасности....

Некорректно работает программа шифрования и дешифрования (ГОСТ 28147-89)
Прошу помочь с обнаружением и устранением ошибки(ошибок) в коде программы, реализующей шифрование и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.