Ключевое слово в защите информации
КЛЮЧЕВОЕ СЛОВО
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход или Регистрация.

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Mikhail Kislovskiy  
#1 Оставлено : 30 мая 2019 г. 16:27:31(UTC)
Mikhail Kislovskiy

Статус: Участник

Группы: Участники
Зарегистрирован: 24.05.2019(UTC)
Сообщений: 18
Российская Федерация
Откуда: Moscow

Всем приятного времени суток.

Использую КриптоПро .Net.
Для получения хэша в документации нашёл вот такую реализацию:

Gost3411_2012_256 gost3411 = new Gost3411_2012_256CryptoServiceProvider();
byte[] hashValue = gost3411.ComputeHash(hex);

Так же до этого искал open-source реализации данного стандарта стрибог.
Нашёл на просторах хабра вот такую статью - https://habr.com/ru/post/188152/.

Решил сравнить выполнение двух разных реализаций, используя тестовые параметры из стандарта - https://tools.ietf.org/html/rfc6986#section-6.1?

И как заключение был удивлен тем, что КриптоПро не прошел проверку на контрольных значений у сообщений M1 и M2 из стандарта, как ля 256 бит, так и для 512, в то время как реализация с хабра не испытала с такой проверкой никаких проблем.

Собственно хотелось бы понять, в чём проблема КриптоПро или Хабра?
В каких параметрах именно разница, а так же где найти эти параметры матриц в КриптоПро?
Offline Максим Коллегин  
#2 Оставлено : 30 мая 2019 г. 18:44:03(UTC)
Максим Коллегин

Статус: Сотрудник

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,393
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 37 раз
Поблагодарили: 717 раз в 621 постах
Выложите получающиеся значения.
Знания в базе знаний, поддержка в техподдержке
Offline two_oceans  
#3 Оставлено : 31 мая 2019 г. 7:30:55(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 1,602
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 395 раз в 366 постах
Автор: Mikhail Kislovskiy Перейти к цитате
Gost3411_2012_256 gost3411 = new Gost3411_2012_256CryptoServiceProvider();
byte[] hashValue = gost3411.ComputeHash(hex);

И как заключение был удивлен тем, что КриптоПро не прошел проверку на контрольных значений у сообщений M1 и M2 из стандарта, как ля 256 бит, так и для 512, в то время как реализация с хабра не испытала с такой проверкой никаких проблем.

Собственно хотелось бы понять, в чём проблема КриптоПро или Хабра?
В каких параметрах именно разница, а так же где найти эти параметры матриц в КриптоПро?
Интересная тема. Найти параметры скорее всего невозможно, так как для гост-2012 (стрибог) все уже специфицировано в стандарте, даже установить оид параметров программно нельзя (хотя оид параметров алгоритма хэширования указывается в сертификате, но похоже игнорируется), зато можно поменять представление исходных данных до передачи на расчет хэша или полученного результата после расчета хэша.

Навскидку, настораживает, что параметр называется hex. Уточните пожалуйста, это строка с шестнадцатиричным представлением ("323130"...) или шестнадцатиричное представление уже декодировали в массив байтов (0x32,0x31,0x30...)? В функции низкого уровня нужно подавать байты, а не их шестнадцатиричное представление, полагаю в класс тоже. В примере на хабре как раз подается уже массив байтов. Если представление исходных данных другое, то и результат будет совсем не тем.

Кроме того, результат может быть представлен 4 разными способами в зависимости от endian и порядка полубайтов. В криптоПро как правило используется "интеловский" порядок байт "младший байт по младшему адресу", другие средства расчета хэша могут использовать другой порядок. Например, стандарт xmldsig закрепляет ровно противоположный формат представления ("старший байт по младшему адресу" да еще и кодирует его в base64).

Попробуйте перевернуть результат тремя способами: 1) первый байт с последним (32-м для 256 бит и 64-м для 512 бит), второй с предпоследним и так далее до середины (то есть 16-й с 17-м для 256 бит и 32 с 33-м для 512 бит); 2) в каждом байте поменять половинки, что-то вроде
Код:
a[i]=((a[i] and 0xf0) >> 4) or ((a[i] and 0xf) << 4)
; 3) применить 1) потом 2). 1) это изменение endian, 2) это изменение порядка полубайтов. С исходным результатом получится 4 представления, если одно из них совпадает с контрольным значением, но нужно просто запомнить что для конкретной реализации функции применять такое(ие) преобразование(я), чтобы получить вид как в стандарте. В коде на хабре похоже формат представления уже подобран, поэтому контрольное значение как в стандарте показывает сразу без дополнительных преобразований. Какое же представление потребуется при реальном использовании - вопрос совершенно отдельный.

Отредактировано пользователем 31 мая 2019 г. 7:33:03(UTC)  | Причина: Не указана

Offline Mikhail Kislovskiy  
#4 Оставлено : 31 мая 2019 г. 16:46:55(UTC)
Mikhail Kislovskiy

Статус: Участник

Группы: Участники
Зарегистрирован: 24.05.2019(UTC)
Сообщений: 18
Российская Федерация
Откуда: Moscow

Добрый день.

Для сообщения message = "fbe2e5f0eee3c820fbeafaebef20fffbf0e1e0f0f520e0ed20e8ece0ebe5f0f2f120fff0eeec20f120faf2fee5e2202ce8f6f3ede220e8e6eee1e8f0f2d1202ce8f0f2e5e220e5d1"

Получаются следующие строки:
КриптоПро .Net
result = "E7AB4EFD0915EAAC2DAB58DAE45D0F28D14F83C57794B3338F7872C10542C19"

Для реализации с хабра:
result = "508F7E553C6501D749A66FC28C6CAC0B05746D97537FA85D9E40904EFED29D"

Напомню, что вариант с хабра совпадает с контрольным значением из стандарта.
Offline Mikhail Kislovskiy  
#5 Оставлено : 31 мая 2019 г. 16:55:33(UTC)
Mikhail Kislovskiy

Статус: Участник

Группы: Участники
Зарегистрирован: 24.05.2019(UTC)
Сообщений: 18
Российская Федерация
Откуда: Moscow

Автор: two_oceans Перейти к цитате
Навскидку, настораживает, что параметр называется hex. Уточните пожалуйста, это строка с шестнадцатиричным представлением ("323130"...) или шестнадцатиричное представление уже декодировали в массив байтов (0x32,0x31,0x30...)? В функции низкого уровня нужно подавать байты, а не их шестнадцатиричное представление, полагаю в класс тоже. В примере на хабре как раз подается уже массив байтов. Если представление исходных данных другое, то и результат будет совсем не тем.


Наименование параметра hex было взято из головы.

Я в массив байтов эту строку перевёл вот так:
private static byte[] fromHexStringToByte(string input)
{
byte[] data = new byte[input.Length / 2];
string HexByte = "";
for (int i = 0; i < data.Length; i++)
{
HexByte = input.Substring(i * 2, 2);
data[i] = Convert.ToByte(HexByte, 16);
}
return data;
}

Почему так, данный код нашел на просторах github он использовался при реализации подписи по ГОСТ 34.10-2012
https://github.com/oxaoo/GOST_34.10-2012

Что тоже важно для нас, так как необходимо также подписать потом полученную сумму.

Параметры эллиптической кривой конечно там не такие как в КриптоПро, но я пытался подставлять и те, которые указаны в документации КриптоПро, но положительного результата так и не получил.

Отредактировано пользователем 31 мая 2019 г. 16:56:51(UTC)  | Причина: Не указана

Offline two_oceans  
#6 Оставлено : 3 июня 2019 г. 5:44:10(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 1,602
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 395 раз в 366 постах
Автор: Mikhail Kislovskiy Перейти к цитате
Наименование параметра hex было взято из головы.
Я в массив байтов эту строку перевёл вот так:
...
Почему так, данный код нашел на просторах github он использовался при реализации подписи по ГОСТ 34.10-2012
https://github.com/oxaoo/GOST_34.10-2012
На вид фунуция перевода нормальная, хотя конечно я не знаю, что в Convert.ToByte. Опять же возможны заморочки с Endian - в этом случае надо заполнять байты в обратном порядке, так как младший байт в записи числа в статье скорее всего справа, а при записи "младший байт по младшему адресу" надо наоборот младший байт записать в data[0]. В этом случае (с переворотом) будет
Код:
data[data.length-i-1] = Convert.ToByte(HexByte, 16);
Попробуйте, что получится с такой строкой.
Автор: Mikhail Kislovskiy Перейти к цитате
Что тоже важно для нас, так как необходимо также подписать потом полученную сумму.

Параметры эллиптической кривой конечно там не такие как в КриптоПро, но я пытался подставлять и те, которые указаны в документации КриптоПро, но положительного результата так и не получил.
У меня вот тоже заморочки с хэшем гост-2012 по версии КриптоПро, но пока не разобрался в чем проблема. Попробую наверно тоже разными способами покрутить эталонные значения. Как ни странно с проверкой самого значения подписи гост-2012 проблемы нет. Хотя конечно значение подписи гост вообще сравнивать некорректно, оно всегда разное, но проверка xml файлов низкоуровневыми функциями майкрософт криптоапи сходится.
Цитата:
Для сообщения message = "fbe2e5f0eee3c820fbeafaebef20fffbf0e1e0f0f520e0ed20e8ece0ebe5f0f2f120fff0eeec20f120faf2fee5e2202ce8f6f3ede220e8e6eee1e8f0f2d1202ce8f0f2e5e220e5d1"

Получаются следующие строки:
КриптоПро .Net
result = "E7AB4EFD0915EAAC2DAB58DAE45D0F28D14F83C57794B3338F7872C10542C19"

Для реализации с хабра:
result = "508F7E553C6501D749A66FC28C6CAC0B05746D97537FA85D9E40904EFED29D"
В эталоне гост-2012 256 от М2 еще есть 0 "508F7E553C_0_650...", да и с ним длина шестнадцатиричной записи 63 немного странная, байт не целый.

Отредактировано пользователем 3 июня 2019 г. 6:33:54(UTC)  | Причина: Не указана

Offline two_oceans  
#7 Оставлено : 3 июня 2019 г. 5:47:30(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 1,602
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 395 раз в 366 постах
Да, в стандарте все-таки младший байт справа (big-endian нотация), то есть надо переворачивать и пример перед вычислением и результат после вычисления, тогда должно сойтись как в статье. Как оказалось этот вопрос обсуждался и ранее. Проверьте получилась ли у Вас текстовая строка из "слова о полку Игореве".

Подробнее: https://www.cryptopro.ru....aspx?g=posts&t=9038

Отредактировано пользователем 3 июня 2019 г. 7:37:55(UTC)  | Причина: Не указана

Offline Mikhail Kislovskiy  
#8 Оставлено : 3 июня 2019 г. 12:58:05(UTC)
Mikhail Kislovskiy

Статус: Участник

Группы: Участники
Зарегистрирован: 24.05.2019(UTC)
Сообщений: 18
Российская Федерация
Откуда: Moscow

Автор: two_oceans Перейти к цитате
Да, в стандарте все-таки младший байт справа (big-endian нотация), то есть надо переворачивать и пример перед вычислением и результат после вычисления, тогда должно сойтись как в статье. Как оказалось этот вопрос обсуждался и ранее. Проверьте получилась ли у Вас текстовая строка из "слова о полку Игореве".

Подробнее: https://www.cryptopro.ru....aspx?g=posts&t=9038


Добрый день.

Проверил вашу прошлую догадку про little-endian дважды перевернул, как и говорили, сначала ДО - затем ПОСЛЕ и итоговый результат совпал.

Спасибо, Вам, за разъяснение.

Может у вас будут какие-то идеи насчёт https://github.com/oxaoo/GOST_34.10-2012 данной реализации подписи по ГОСТ 34.10-2012?
Там используется закрытый ключ, но в моём случае у меня есть только открытый ключ.

С параметрами вроде тоже всё как ясно, но по итогу проверки подписи безуспешны.

Gost3410_2012_256CryptoServiceProvider GostSign = new Gost3410_2012_256CryptoServiceProvider();
byte[] SignedValue = GostSignHash(hash, GostSign, "Gost3411_2012_256");

Я же верно понимаю, что подпись при помощи КриптоПро .Net должна таким образом создаваться?
Так же вопрос, а как избежать создания нового контейнера для ключа? В нашем случае просто не нужна генерация которая в КриптоПро CSP используется, а нужно более простое решение.

Offline Mikhail Kislovskiy  
#9 Оставлено : 3 июня 2019 г. 17:05:52(UTC)
Mikhail Kislovskiy

Статус: Участник

Группы: Участники
Зарегистрирован: 24.05.2019(UTC)
Сообщений: 18
Российская Федерация
Откуда: Moscow

Поправка насчёт https://github.com/oxaoo/GOST_34.10-2012.
Не ясно, каким образом получить private key из сертификата и применить для этой реализации.

Отредактировано пользователем 3 июня 2019 г. 17:07:15(UTC)  | Причина: Не указана

Offline two_oceans  
#10 Оставлено : 4 июня 2019 г. 12:11:26(UTC)
two_oceans

Статус: Эксперт

Группы: Участники
Зарегистрирован: 05.03.2015(UTC)
Сообщений: 1,602
Российская Федерация
Откуда: Иркутская область

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 395 раз в 366 постах
Насчет того, как это выглядит на .NET не уверен, так как использовал низкоуровневое CryptoAPI. Как я понимаю, есть 2 варианта - если уже вычислен хэш, то можно подписать хэш (подходит если вычислять хэш массивного файла на одном компьютере, сервере, например, и передавать на второй компьютер, клиента с контейнером закрытого ключа); если не вычислен хэш, можно подписывать сами данные другим методом класса.

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

Однако предположим, что сертификат установлен в хнанилище сертификатов "Личные" со ссылкой на контейнер закрытого ключа, содержащий ключевую пару (и открытый и закрытый ключи). Тогда по отдельному файлу сертификата можно создать контекст сертификата, открыть хранилище "Личные", найти в хранилище такой же сертификат (по хэшу сертификата или по открытому ключу или по CN или по издателю и номеру или по сертификату целиком - способ поиска указывается флагами) и получить контекст криптопровайдера связанный с сертификатом в хранилище и с контейнером закрытого ключа. Есть правда плавающая проблема, что поиск "из коробки" бывает ничего не находит по некоторым сертификатам хотя они наверняка есть в хранилище и без проблем перечисляются - в таком случае проще перечислить все сертификаты хранилища и каждый "вручную" (в смысле в своем коде) сравнить с исходным.

На этом форуме вроде были примеры как выделить сертификат, подписать и проверить подпись на .NET, просто надо найти рабочий пример в соседних темах. Изложу как это работает в низкоуровневых функциях для общей картины, на .NET попроще, разбор подписи и проверка сертификатов удобнее, но в целом механика такая же.

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

Отредактировано пользователем 4 июня 2019 г. 12:27:21(UTC)  | Причина: Не указана

RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.