Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# Windows Forms
Войти
Регистрация
Восстановить пароль
 
AXLL
5 / 5 / 1
Регистрация: 30.06.2015
Сообщений: 33
1

Почему реализация ГОСТ 89 работает с Encoding.UTF8 и не работает с Encoding.ASCII?

01.11.2017, 15:34. Просмотров 287. Ответов 4

Класс GOSTCrypto
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
//S-блок
        protected byte[][] S_Block = {
              new byte[] { 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF },
              new byte[] { 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF },
              new byte[] { 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF },
              new byte[] { 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF },
              new byte[] { 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF },
              new byte[] { 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF },
              new byte[] { 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF },
              new byte[] { 0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF }
        };
        //генерация ключа
        protected uint[] GenerateKeys(byte[] key)
        {
            if (key.Length != 32) throw new Exception("Длина ключа не 64 бита");
            var subkeys = new uint[8];
            for (int i = 0; i < 8; i++) subkeys[i] = BitConverter.ToUInt32(key, 4 * i);
            return subkeys;
        }
        //Метод подстановки по S-блокам работает с 4-битными кусочками 32-битного подблока, их достаточно удобно отделять побитовым сдвигом и дальнейшим умножением на 0x0f:
        protected uint Substitution(uint value)
        {
            uint output = 0;
            for (int i = 0; i < 8; i++)
            {
                var temp = (byte)((value >> (4 * i)) & 0x0f);
                temp = S_Block[i][temp];
                output |= (UInt32)temp << (4 * i);
            }
            return output;
        }
Шифрование (наследуется от GOSTCrypto):
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
String IEncryptable.Encode(String data, String key, bool isParallel)
        {
            return Encoding.ASCII.GetString(((IEncryptable)(this)).Encode(Encoding.ASCII.GetBytes(data), key, isParallel));
        }
 
        byte[] IEncryptable.Encode(byte[] data, String key, bool isParallel)
        {
            return ((IEncryptable)(this)).Encode(data, Encoding.ASCII.GetBytes(key), isParallel);
        }
 
        byte[] IEncryptable.Encode(byte[] data, byte[] key, bool isParallel)
        {
            var subkeys = GenerateKeys(key);
            var result = new byte[data.Length];
            var block = new byte[8];
 
            if (isParallel)
            {
                Parallel.For(0, data.Length / 8, i =>
                {
                    Array.Copy(data, 8 * i, block, 0, 8);
                    Array.Copy(EncodeBlock(block, subkeys), 0, result, 8 * i, 8);
                });
            }
            else
            {
                for (int i = 0; i < data.Length / 8; i++) // N блок длиной 64 бит.
                {
                    Array.Copy(data, 8 * i, block, 0, 8);
                    Array.Copy(EncodeBlock(block, subkeys), 0, result, 8 * i, 8);
                }
            }
            return result;
        }
        //шифрование
        private byte[] EncodeBlock(byte[] block, uint[] keys)
        {
            // разделить на 2 блока
            uint N1 = BitConverter.ToUInt32(block, 0);
            uint N2 = BitConverter.ToUInt32(block, 4);
 
            for (int i = 0; i < 32; i++)
            {
                int keyIndex = i < 24 ? (i % 8) : (7 - i % 8);  // до 24-го цикла: от 0 до 7; после - от 7 до 0;
                var round = (N1 + keys[keyIndex]) % uint.MaxValue;// суммирвоание (N1 + X[i]) по mod 2^32
                round = Substitution(round); // заменяем
                round = (round << 11) | (round >> 21);
                round = round ^ N2;
 
                if (i < 31) // последний цикл: N1 не изменяется; N2 = s;
                {
                    N2 = N1;
                    N1 = round;
                }
                else N2 = round;
            }
 
            var output = new byte[8];
            var N1buff = BitConverter.GetBytes(N1);
            var N2buff = BitConverter.GetBytes(N2);
 
            for (int i = 0; i < 4; i++)
            {
                output[i] = N1buff[i];
                output[4 + i] = N2buff[i];
            }
            return output;
        }
Дешифрование (наследуется от GOSTCrypto):
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
 String IDecryptable.Decode(String data, String key, bool isParallel)
        {
            return Encoding.ASCII.GetString(((IDecryptable)(this)).Decode(Encoding.ASCII.GetBytes(data), key, isParallel));
        }
 
        byte[] IDecryptable.Decode(byte[] data, String key, bool isParallel)
        {
            return ((IDecryptable)(this)).Decode(data, Encoding.ASCII.GetBytes(key), isParallel);
        }
 
        byte[] IDecryptable.Decode(byte[] data, byte[] key, bool isParallel)
        {
            var subkeys = GenerateKeys(key);
            var result = new byte[data.Length];
            var block = new byte[8];
 
            if (isParallel)
            {
                Parallel.For(0, data.Length / 8, i =>
                {
                    Array.Copy(data, 8 * i, block, 0, 8);
                    Array.Copy(DecodeBlock(block, subkeys), 0, result, 8 * i, 8);
                });
            }
            else
            {
                for (int i = 0; i < data.Length / 8; i++) // N блок длиной 64 бит.
                {
                    Array.Copy(data, 8 * i, block, 0, 8);
                    Array.Copy(DecodeBlock(block, subkeys), 0, result, 8 * i, 8);
                }
            }
            return result;
        }
        //дешифрование
        private byte[] DecodeBlock(byte[] block, uint[] keys)
        {
            // разделить на 2 блока
            uint N1 = BitConverter.ToUInt32(block, 0);
            uint N2 = BitConverter.ToUInt32(block, 4);
 
            for (int i = 0; i < 32; i++)
            {
                int keyIndex = i < 8 ? (i % 8) : (7 - i % 8); // до 24-го цикла: от 0 до 7; после - от 7 до 0;
                var round = (N1 + keys[keyIndex]) % uint.MaxValue; // суммирвоание (N1 + X[i]) по mod 2^32
                round = Substitution(round); // заменяем
                round = (round << 11) | (round >> 21);
                round = round ^ N2;
 
                if (i < 31) 
                {
                    N2 = N1;
                    N1 = round;
                }
                else N2 = round;
            }
 
            var output = new byte[8];
            var N1buff = BitConverter.GetBytes(N1);
            var N2buff = BitConverter.GetBytes(N2);
 
            for (int i = 0; i < 4; i++)
            {
                output[i] = N1buff[i];
                output[4 + i] = N2buff[i];
            }
            return output;
        }
Если использовать место Encoding.ASCII это Encoding.UTF8, то сообщение шифруется и дешифруется коректно. А только для ASCII это не работает, сообщение не дешифруется.

Добавлено через 1 час 53 минуты
Мне надо ASCII - что бы я записывал файл байтами, так как структура программы такая.
Проверил Default, Unicode - шифрование и дешифрование работают, но не могу записать в байт:
C#
1
for (int i = 0; i < TextSecret.Text.Length; i++) ByteTextFileExportText[i] = Convert.ToByte(ExportDecoder[i]); // вылетает ошибка так как байт 0...255, а я хочу пихнуть 1043 в байт и тд.
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.11.2017, 15:34
Ответы с готовыми решениями:

HttpWebResponse encoding
string charSet = response.CharacterSet; Encoding encoding; if...

Encoding и цикл for
В чём ошибка данного кода? if (richTextBox1.Text != &quot;&quot;) { String s = String.Empty; for...

Encoding: перекодировка русских букв
Доброго времени суток! Есть кусок кода string welcome = &quot;Привет Welcome&quot;; data =...

Преобразования с использованием System.Encoding
Вобщем я перехожу на С# и столкнулся с проблемой преобразования. В статье описано что чтобы...

Преобразовать String в Byte[] без использования Encoding
Всем доброго времени суток :) В общем возникла &quot;проблема&quot; имеем код - byte Send = new byte {...

4
kolorotur
Эксперт .NET
13030 / 10189 / 2642
Регистрация: 17.09.2011
Сообщений: 17,306
Завершенные тесты: 1
01.11.2017, 15:37 2
Цитата Сообщение от AXLL Посмотреть сообщение
Мне надо ASCII - что бы я записывал файл байтами
Все остальные кодировки тоже являются байтами.

Цитата Сообщение от AXLL Посмотреть сообщение
вылетает ошибка так как байт 0...255, а я хочу пихнуть 1043 в байт
В ASCII нет кириллицы, кириллический текст невозможно закодировать в ASCII.
0
AXLL
5 / 5 / 1
Регистрация: 30.06.2015
Сообщений: 33
01.11.2017, 16:04  [ТС] 3
Цитата Сообщение от kolorotur Посмотреть сообщение
Все остальные кодировки тоже являются байтами.
Тогда почему у меня ошибка тут вылетает ?
C#
1
2
3
 byte[] ByteTextFileExportText = new byte[0];
 ByteTextFileExportText = new byte[TextSecret.Text.Length];
 for (int i = 0; i < TextSecret.Text.Length; i++) ByteTextFileExportText[i] = Convert.ToByte(MassText[i]); // тут
У меня в MassText[i] лежит символ например

и вылетает исключение "Дополнительные сведения: Значение было недопустимо малым или недопустимо большим для беззнакового байта."
0
Миниатюры
Почему реализация ГОСТ 89 работает с Encoding.UTF8 и не работает с Encoding.ASCII?  
kolorotur
Эксперт .NET
13030 / 10189 / 2642
Регистрация: 17.09.2011
Сообщений: 17,306
Завершенные тесты: 1
01.11.2017, 16:14 4
Цитата Сообщение от AXLL Посмотреть сообщение
Тогда почему у меня ошибка тут вылетает ?
Потому что вы конвертируете в байт код символа, который больше максимально допустимого значения для одного байта.
Либо используйте многобайтовую кодировку, вроде той же UTF8, либо используйте однобайтовую кодировку с поддержкой кириллицы, но придется отказаться от возможности вписывать в ключ другие символы юникода.
0
AXLL
5 / 5 / 1
Регистрация: 30.06.2015
Сообщений: 33
01.11.2017, 21:22  [ТС] 5
Проблема решена. Убрал первые 2 функции.

C#
1
2
3
4
5
6
7
8
9
String IEncryptable.Encode(String data, String key, bool isParallel)
{
            return Encoding.ASCII.GetString(((IEncryptable)(this)).Encode(Encoding.ASCII.GetBytes(data), key, isParallel));
}
 
byte[] IEncryptable.Encode(byte[] data, String key, bool isParallel)
{
            return ((IEncryptable)(this)).Encode(data, Encoding.ASCII.GetBytes(key), isParallel);
}
Оставил только третью:
C#
1
byte[] IEncryptable.Encode(byte[] data, byte[] key, bool isParallel)
Ну так как теперь входные данные не String а byte[] и выходные byte[], то переписал использование функции:
C#
1
2
3
4
5
6
7
8
/*КОСТЫЛЬ*/
byte[] TextSecret_byte = new byte[TextSecret.Text.Length];
char[] TextSecret_char = TextSecret.Text.ToArray();
for (int i = 0; i < TextSecret.Text.Length; i++) TextSecret_byte[i] = Convert.ToByte(TextSecret_char[i]);
/*КОСТЫЛЬ*/
byte[] GOST_KEY_TextBox_byte = new byte[GOST_KEY_TextBox.Text.Length];
char[] GOST_KEY_TextBox_char = GOST_KEY_TextBox.Text.ToArray();
for (int i = 0; i < GOST_KEY_TextBox.Text.Length; i++) GOST_KEY_TextBox_byte[i] = Convert.ToByte(GOST_KEY_TextBox_char[i]);
Ну и вызываю так:
C#
1
var ExportEncoder = encoder.Encode(TextSecret_byte/*Исходный текст*/, GOST_KEY_TextBox_byte /*ключ*/, isParallel.Checked/*Если параллельно*/);
Теперь так как я возвращаю только byte[] а не String (так как убрал первую функцию), то диапазон стал 0...255
0
01.11.2017, 21:22
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.11.2017, 21:22

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

Что необходимо прописать в using для работы с Encoding
Что необходимо прописать в using , в начале скрипта. Для того, чтобы читало это...

Чем отличается Encoding.Unicode от Encoding.UTF16
я вот что то не пойму чем отличается Encoding.Unicode от Encoding.UTF16? и почему в браузерах...

Есть ли в С++ аналог функции Encoding.UTF8.GetBytes(plainText) из С#?
Здравствуйте уважаемые ГУРУ! Переписываю свой код из С# на С++ Необходимо строку типа string...


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

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

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