0 / 0 / 0
Регистрация: 25.04.2013
Сообщений: 9
1

Некорректно работает программа шифрования и дешифрования (ГОСТ 28147-89)

13.03.2019, 21:36. Показов 2349. Ответов 5

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

При написании кода опирался на алгоритм, приведенный в одной из статей на хабре, на информацию из википедии об этом алгоритме и на код из библиотеки Bouncy Castle.

Проблема: программа шифрует сообщение (это не точно), но при попытке расшифровать полученное зашифрованное сообщение, исходное сообщение не получается. Ниже прикрепляю код и скриншоты небольшого тест работы программы.

P.S. Дублирующийся код и множество переменных, без которых можно было бы обойтись, оставил для наглядности алгоритма.

P.S.S. Проверки на некорректность введенных данных пока не выполняю, ибо и с корректно веденными данными программа работает неверно.

P.S.S.S. Заранее спасибо!

Скриншоты:
https://i.ibb.co/TKV1yRJ/2019-03-14-01-30-16.png
https://i.ibb.co/VQc8QXG/2019-03-14-01-31-02.png

Java
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package ciphers;
 
import java.io.*;
 
public class GHOST2814789 {
    private static int[] key = {
            0x0123,
            0x4567,
            0x89AB,
            0xCDEF,
            0x0124,
            0x4567,
            0x89AB,
            0xCDEF
    };
 
    private static byte[] S = {
            0x4, 0xA, 0x9, 0x2, 0xD, 0x8, 0x0, 0xE, 0x6, 0xB, 0x1, 0xC, 0x7, 0xF, 0x5, 0x3,
            0xE, 0xB, 0x4, 0xC, 0x6, 0xD, 0xF, 0xA, 0x2, 0x3, 0x8, 0x1, 0x0, 0x7, 0x5, 0x9,
            0x5, 0x8, 0x1, 0xD, 0xA, 0x3, 0x4, 0x2, 0xE, 0xF, 0xC, 0x7, 0x6, 0x0, 0x9, 0xB,
            0x7, 0xD, 0xA, 0x1, 0x0, 0x8, 0x9, 0xF, 0xE, 0x4, 0x6, 0xC, 0xB, 0x2, 0x5, 0x3,
            0x6, 0xC, 0x7, 0x1, 0x5, 0xF, 0xD, 0x8, 0x4, 0xA, 0x9, 0xE, 0x0, 0x3, 0xB, 0x2,
            0x4, 0xB, 0xA, 0x0, 0x7, 0x2, 0x1, 0xD, 0x3, 0x6, 0x8, 0x5, 0x9, 0xC, 0xF, 0xE,
            0xD, 0xB, 0x4, 0x1, 0x3, 0xF, 0x5, 0x9, 0x0, 0xA, 0xE, 0x7, 0x6, 0x8, 0x2, 0xC,
            0x1, 0xF, 0xD, 0x0, 0x5, 0x7, 0xA, 0x4, 0x9, 0x2, 0x3, 0xE, 0x6, 0xB, 0x8, 0xC
    };
 
    public static void main(String[] args) throws FileNotFoundException, IOException {
        String s = modifyFile("/home/anatoliy/Документы/Enctyption/src/input");
    }
 
    public static String modifyFile(String inputFilePath) throws FileNotFoundException, IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String initStrMsg = getMsgFromFile(inputFilePath);
        byte[] initBytesMsg = initStrMsg.getBytes();
        byte[] resultBytesMsg = new byte[initBytesMsg.length];
        boolean forEncryption;
 
        System.out.println("Исходное сообщение:\n" + initStrMsg + "\n");
 
        System.out.print("Введите цифру, соответствующую необходимому режиму работы алгоритма шифрования ГОСТ 28147-89\n" +
                           "(зашифровать - 1, расшифровать - любая другая запись): ");
 
        forEncryption = (reader.readLine().equals("1")) ? true : false;
        reader.close();
 
        for (int i = 1; i * 8 <= initBytesMsg.length ; i++) {
            processBlock(forEncryption, initBytesMsg, resultBytesMsg, (i - 1) * 8);
        }
 
        return outputMsgToFile(new String(resultBytesMsg));
    }
 
    private static String getMsgFromFile(String filePath) throws FileNotFoundException, IOException {
        BufferedReader fileReader = new BufferedReader(new FileReader(filePath));
        String message = "";
 
        while (fileReader.ready()) {
            message += fileReader.readLine() + '\n';
        }
 
        message = message.substring(0, message.length() - 1);
 
        fileReader.close();
 
        return message;
    }
 
    private static String outputMsgToFile(String msg) throws IOException {
        String outputfilePath = "/home/anatoliy/Документы/Enctyption/src/output";
        BufferedWriter fileWriter = new BufferedWriter(new FileWriter(outputfilePath));
 
        fileWriter.write(msg);
        fileWriter.close();
 
        return outputfilePath;
    }
 
    private static void processBlock(boolean forEncryption, byte[] in, byte[] out, int off) {
        int N1 = bytesToInt(in, off),
            N2 = bytesToInt(in, off + 4),
            CM1 = 0, CM2 = 0, K = 0, R = 0;
 
        if (forEncryption) {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 8; j++) {
                    CM1 = N1 + key[j];
                    K = f(CM1);
                    R = (K << 11) | (K >>> 21);
                    CM2 = R ^ N2;
                    N2 = N1;
                    N1 = CM2;
                }
            }
            for (int i = 7; i >= 0; i--) {
                CM1 = N1 + key[i];
                K = f(CM1);
                R = (K << 11) | (K >>> 21);
                CM2 = R ^ N2;
 
                if (i == 0) break;
 
                N2 = N1;
                N1 = CM2;
            }
        } else {
            for (int i = 0; i < 8; i++) {
                CM1 = N1 + key[i];
                K = f(CM1);
                R = (K << 11) | (K >>> 21);
                CM2 = R ^ N2;
                N2 = N1;
                N1 = CM2;
            }
            for (int i = 0; i < 3; i++) {
                for (int j = 7; j >= 0; j--) {
                    CM1 = N1 + key[j];
                    K = f(CM1);
                    R = (K << 11) | (K >>> 21);
                    CM2 = R ^ N2;
 
                    if (j == 0) break;
 
                    N2 = N1;
                    N1 = CM2;
                }
            }
        }
 
        N2 = CM2;
 
        intToBytes(N1, out, off);
        intToBytes(N2, out, off + 4);
    }
 
    public static int f(int CM1) {
        int result = 0;
 
        for (int i = 0; i < 8; i++) {
            result += S[i * 16 + ((CM1 >> ((7 - i) * 4)) & 0xF)] << ((7 - i) * 4);
        }
 
        return result;
    }
 
    private static int bytesToInt(byte[] in, int off) {
        return  (in[off]     << 24) +
                (in[off + 1] << 16) +
                (in[off + 2] << 8) +
                 in[off + 3];
    }
 
    private static void intToBytes(int in, byte[] out, int off) {
        out[0] = (byte)(in >> 24);
        out[1] = (byte)(in >> 16);
        out[2] = (byte)(in >> 8);
        out[3] = (byte)(in);
    }
}
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.03.2019, 21:36
Ответы с готовыми решениями:

Не совсем понятен алгоритм шифрования/дешифрования шифра ГОСТ 28147-89
Подробный алгоритм в файле. Ключ для...

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

ГОСТ 28147-89 на C++
Здравствуйте уважаемые, Решил попрактиковаться и написать алгоритм шифрования и дешифрования...

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

5
425 / 174 / 69
Регистрация: 14.12.2017
Сообщений: 401
13.03.2019, 23:00 2
Лучший ответ Сообщение было отмечено Anatoliy9697 как решение

Решение

Ключ 103000100A00010F00300200D000200003072000020C0300002000C00200 0302 (HEX)
Текст 20F2010A30101B02 (HEX)
Проверяйте на каждом раунде:
(то есть выполнили 1-й раунд - проверили результат - все ОК - идем дальше - не ОК - смотрим почему )
Текст N1=20F2010A N2=30101B02

раунд = 1

A1 = BC725A5 Б1 = 20F2010A

раунд = 2

A2 = E5D5C1B5 Б2 = BC725A5

раунд = 3

A3 = EE17E1EA Б3 = E5D5C1B5

раунд = 4

A4 = 76174FE8 Б4 = EE17E1EA

раунд = 5

A5 = 2ACD5347 Б5 = 76174FE8

раунд = 6

A6 = 6A0C391F Б6 = 2ACD5347

раунд = 7

A7 = 2A2F795D Б7 = 6A0C391F

раунд = 8

A8 = 7DF3C16E Б8 = 2A2F795D

раунд = 9

A9 = 27FA5B3A Б9 = 7DF3C16E

раунд = 10

A10 = B1CF4FEB Б10 = 27FA5B3A

раунд = 11

A11 = 53F0BC34 Б11 = B1CF4FEB

раунд = 12

A12 = F0F92444 Б12 = 53F0BC34

раунд = 13

A13 = 3A3D75B Б13 = F0F92444

раунд = 14

A14 = F987C4CA Б14 = 3A3D75B

раунд = 15

A15 = C6380FD2 Б15 = F987C4CA

раунд = 16

A16 = 5A5D0962 Б16 = C6380FD2

раунд = 17

A17 = DD8FE463 Б17 = 5A5D0962

раунд = 18

A18 = 48C71CA6 Б18 = DD8FE463

раунд = 19

A19 = D353E695 Б19 = 48C71CA6

раунд = 20

A20 = 3B66D90F Б20 = D353E695

раунд = 21

A21 = 3AACFE2D Б21 = 3B66D90F

раунд = 22

A22 = 20CCA179 Б22 = 3AACFE2D

раунд = 23

A23 = B9A5C8D9 Б23 = 20CCA179

раунд = 24

A24 = 5D3E7A2F Б24 = B9A5C8D9

раунд = 25

A25 = 6643D599 Б25 = 5D3E7A2F

раунд = 26

A26 = D41A4844 Б26 = 6643D599

раунд = 27

A27 = AE20B802 Б27 = D41A4844

раунд = 28

A28 = E56D0251 Б28 = AE20B802

раунд = 29

A29 = 32E6C04 Б29 = E56D0251

раунд = 30

A30 = A9B26AA9 Б30 = 32E6C04

раунд = 31

A31 = 3F91B5D2 Б31 = A9B26AA9

раунд = 32

A32 = 3F91B5D2 Б32 = CFC18072

A33 =CFC18072 Б33 =3F91B5D2

результат = CFC180723F91B5D2
1
0 / 0 / 0
Регистрация: 25.04.2013
Сообщений: 9
14.03.2019, 08:06  [ТС] 3
On18, большое спасибо, что вы откликнулись! Только я хотел бы еще узнать, какую таблицу замен вы использовали?
0
425 / 174 / 69
Регистрация: 14.12.2017
Сообщений: 401
14.03.2019, 22:04 4
S-box для приложений ЦБ РФ. (наиболее распостраненные)

Добавлено через 37 минут
У вас же они тоже:
Код
private static byte[] S = {
            0x4, 0xA, 0x9, 0x2, 0xD, 0x8, 0x0, 0xE, 0x6, 0xB, 0x1, 0xC, 0x7, 0xF, 0x5, 0x3,
0
0 / 0 / 0
Регистрация: 25.04.2013
Сообщений: 9
18.03.2019, 18:57  [ТС] 5
Спасибо за помощь!

Результаты раундов при ваших входных данных помогли найти ряд мелких ошибок.
Долго просидел с тем, что вывод программы полностью соответствовал написанным вами результатам раундов, но при попытке расшифровать полученное сообщение, исходное не получалось. Проблемой оказалось то, что я зашифрованное сообщение копировал из выходного файла и вставлял во входной файл, из-за чего появлялись какие-то лишние байты. Причину появления этих странных байтов и природу их содержимого пока не выяснил.

Прикрепляю итоговый код программы для тех, кто будет искать примеры реализаций ГОСТ 28147-89 на Java. Фактически это просто вычлененный из библиотеки Bouncy Castle соответствующий алгоритм шифрования.
Java
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package ciphers;
 
import java.io.*;
 
public class GHOST2814789 {
    private static int[] key = {
            0x0123,
            0x4567,
            0x89AB,
            0xCDEF,
            0x0124,
            0x4567,
            0x89AB,
            0xCDEF
    };
 
    private static byte[] S = {
            0x4, 0xA, 0x9, 0x2, 0xD, 0x8, 0x0, 0xE, 0x6, 0xB, 0x1, 0xC, 0x7, 0xF, 0x5, 0x3,
            0xE, 0xB, 0x4, 0xC, 0x6, 0xD, 0xF, 0xA, 0x2, 0x3, 0x8, 0x1, 0x0, 0x7, 0x5, 0x9,
            0x5, 0x8, 0x1, 0xD, 0xA, 0x3, 0x4, 0x2, 0xE, 0xF, 0xC, 0x7, 0x6, 0x0, 0x9, 0xB,
            0x7, 0xD, 0xA, 0x1, 0x0, 0x8, 0x9, 0xF, 0xE, 0x4, 0x6, 0xC, 0xB, 0x2, 0x5, 0x3,
            0x6, 0xC, 0x7, 0x1, 0x5, 0xF, 0xD, 0x8, 0x4, 0xA, 0x9, 0xE, 0x0, 0x3, 0xB, 0x2,
            0x4, 0xB, 0xA, 0x0, 0x7, 0x2, 0x1, 0xD, 0x3, 0x6, 0x8, 0x5, 0x9, 0xC, 0xF, 0xE,
            0xD, 0xB, 0x4, 0x1, 0x3, 0xF, 0x5, 0x9, 0x0, 0xA, 0xE, 0x7, 0x6, 0x8, 0x2, 0xC,
            0x1, 0xF, 0xD, 0x0, 0x5, 0x7, 0xA, 0x4, 0x9, 0x2, 0x3, 0xE, 0x6, 0xB, 0x8, 0xC
    };
 
    public static void main(String[] args) throws FileNotFoundException, IOException {
        String s = modifyFile("/home/anatoliy/Документы/Enctyption/src/input");
    }
 
    public static String modifyFile(String inputFilePath) throws FileNotFoundException, IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String initStrMsg = getMsgFromFile(inputFilePath);
        String resultStrMsg = null;
        byte[] initBytesMsg = initStrMsg.getBytes();
        byte[] resultBytesMsg = new byte[initBytesMsg.length];
        byte[] checkBytesMsg = new byte[initBytesMsg.length];
        boolean forEncryption;
 
        System.out.println("Исходное сообщение:\n" + initStrMsg + "\n");
 
        System.out.print("Введите цифру, соответствующую необходимому режиму работы алгоритма шифрования ГОСТ 28147-89\n" +
                           "(зашифровать - 1, расшифровать - любая другая запись): ");
 
        forEncryption = (reader.readLine().equals("1")) ? true : false;
        reader.close();
 
        for (int i = 1; i * 8 <= initBytesMsg.length ; i++) {
            processBlock(forEncryption, initBytesMsg, resultBytesMsg, (i - 1) * 8);
        }
 
        for (int i = 1; i * 8 <= resultBytesMsg.length ; i++) {
            processBlock(false, resultBytesMsg, checkBytesMsg, (i - 1) * 8);
        }
 
        System.out.println("\nИтоговое сообщение:\n" + (resultStrMsg = new String(resultBytesMsg)));
 
        System.out.println("\nИсходное сообщение, полученное из итогового:\n" + (new String(checkBytesMsg)));
 
        return outputMsgToFile(resultStrMsg);
    }
 
    private static String getMsgFromFile(String filePath) throws FileNotFoundException, IOException {
        BufferedReader fileReader = new BufferedReader(new FileReader(filePath));
        String message = "";
 
        while (fileReader.ready()) {
            message += fileReader.readLine() + '\n';
        }
 
        message = message.substring(0, message.length() - 1);
 
        fileReader.close();
 
        return message;
    }
 
    private static String outputMsgToFile(String msg) throws IOException {
        String outputfilePath = "/home/anatoliy/Документы/Enctyption/src/output";
        BufferedWriter fileWriter = new BufferedWriter(new FileWriter(outputfilePath));
 
        fileWriter.write(msg);
        fileWriter.close();
 
        return outputfilePath;
    }
 
    private static void processBlock(boolean forEncryption, byte[] in, byte[] out, int off) {
        int N1 = bytesToInt(in, off),
                N2 = bytesToInt(in, off + 4),
                tmp;
 
        if (forEncryption) {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 8; j++) {
                    tmp = N1;
                    N1 = N2 ^ mainStep(N1, key[j]);
                    N2 = tmp;
                }
            }
            for (int i = 7; i > 0; i--) {
                tmp = N1;
                N1 = N2 ^ mainStep(N1, key[i]);
                N2 = tmp;
            }
        } else {
            for (int i = 0; i < 8; i++) {
                tmp = N1;
                N1 = N2 ^ mainStep(N1, key[i]);
                N2 = tmp;
            }
            for (int i = 0; i < 3; i++) {
                for (int j = 7; j >= 0; j--) {
                    if ((i == 2) && (j == 0)) {
                        break;
                    }
                    tmp = N1;
                    N1 = N2 ^ mainStep(N1, key[j]);
                    N2 = tmp;
                }
            }
        }
 
        N2 = N2 ^ mainStep(N1, key[0]);
 
        intToBytes(N1, out, off);
        intToBytes(N2, out, off + 4);
    }
 
    private static int mainStep(int n1, int key) {
        int CM1 = (key + n1),
                K = 0;
 
        for (int i = 0; i < 8; i++) {
            K += S[i * 16 + ((CM1 >> (i * 4)) & 0xF)] << (i * 4);
        }
 
        return K << 11 | K >>> 21;
    }
 
    private static int bytesToInt(byte[] in, int off) {
        return  ((in[off + 3] << 24) & 0xff000000) +
                ((in[off + 2] << 16) & 0xff0000) +
                ((in[off + 1] << 8)  & 0xff00) +
                 (in[off]            & 0xff);
    }
 
    private static void intToBytes(int in, byte[] out, int off) {
        out[off + 3] = (byte)(in >>> 24);
        out[off + 2] = (byte)(in >>> 16);
        out[off + 1] = (byte)(in >>> 8);
        out[off] =     (byte)in;
    }
}
0
425 / 174 / 69
Регистрация: 14.12.2017
Сообщений: 401
18.03.2019, 19:57 6
Цитата Сообщение от Anatoliy9697 Посмотреть сообщение
Результаты раундов при ваших входных данных помогли найти ряд мелких ошибок.
Вот и хорошо что пригодилось.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.03.2019, 19:57

ГОСТ 28147-69 | Сложение по модулю 2^32
Здравствуйте, занимаюсь реализацией режима простой замены, преподаватель потребовал...

Гост 28147-89 режим гаммирования
Доброе время суток всем! Прошу сильно не пинать. В криптографии я полный ноль, поэтому надеюсь на...

ГОСТ 28147-89 пример шифрации (вручную)
Есть ли где-нибудь пример шифрации небольшого сообщения по ГОСТу 28147-89? Добавлено через 17...

Как расшифровать сообщение по алгоритму ГОСТ 28147-89?
Друзья! Я написал программу, которая реализует шифрование. Сверился с этим документом. Теперь...


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

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

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