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

Уведомление

Icon
Error

2 Страницы12>
Опции
К последнему сообщению К первому непрочитанному
Offline EgorOkhotin  
#1 Оставлено : 2 июля 2019 г. 15:20:14(UTC)
EgorOkhotin

Статус: Активный участник

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

Сказал(а) «Спасибо»: 4 раз
Следующий алгоритм действий:

Для подписи

Хэш:
Открываю контекст
Создаю хэш поинтер CryptCreateHash
Вычисляю хэш

Подписываю данные:
получаю длину хэша CryptGetHashParam
если хэш не подходит по длине то кидаю исключение
устанавливаю хэш CryptSetHashParam
(Все это делаю с параметром HP_HASHVAL и флагом NoFlags)

Получаю длину подписываемого значения CryptSignHash
Создаю буфер
Подписываю хэш
Возвращаю результат



Проверка:
Точно также как и предыдущем пункте вычисляю хэш
Освобождаю память
Создаю объект хэша заново
Устанавливаю значение хэша также как и при подписи,
Проверяю значение с помощью CryptVerifySignature с флагом 0 и описанием null

Что я делаю не так? Если описание не точное и где-то нужно уточнить то прошу сказать что именно.

Сертификат при подписи и проверке один. При подписи я открываю контейнер и функцией CryptGetUserKey беру ключ для подписывания, а
при проверке из сертификата того же самого беру только публичный ключ и импортирую его с помощью CryptImportKey.
После прасинга ключа из сертификата он получется длиной 101 байт.
Offline two_oceans  
#2 Оставлено : 3 июля 2019 г. 7:05:53(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 396 раз в 366 постах
Автор: EgorOkhotin Перейти к цитате
Хэш:
Открываю контекст
Создаю хэш поинтер CryptCreateHash
Вычисляю хэш

Подписываю данные:
получаю длину хэша CryptGetHashParam
если хэш не подходит по длине то кидаю исключение
устанавливаю хэш CryptSetHashParam
(Все это делаю с параметром HP_HASHVAL и флагом NoFlags)
Намудрили, но должно работать. Нет необходимости на одном и том же компьютере получать значение хэша, а потом его снова ставить - можно использовать тот же объект хэша. Для дальнейшего подписания контекст, на котором создаете подписываемый хэш должен открываться с указанием контейнера.
Автор: EgorOkhotin Перейти к цитате
Получаю длину подписываемого значения CryptSignHash
Создаю буфер
Подписываю хэш
Возвращаю результат
Тут проблемка в том, что такой алгоритм будет запрашивать пин-код дважды. Для пользователя это неудобно и создает впечатление что пин-код введен неправильно. Для голой подписи на низком уровне размер подписи для алгоритма заранее известен. Для гост это размер хэша * 2. Я еще добавляю несколько байт "для страховки" - так нет необходимости запрашивать размер буфера для подписи и пин-код запрашивает один раз.
Автор: EgorOkhotin Перейти к цитате
Проверка:
Точно также как и предыдущем пункте вычисляю хэш
Освобождаю память
Создаю объект хэша заново
Устанавливаю значение хэша также как и при подписи,
Опять же намудрили, но должно работать. Вычисление хэша при проверке отличается тем что контекст, на котором создаете объект хэша для проверки может создаваться без указания контейнера с флагом VERIFY_CONTEXT.
Автор: EgorOkhotin Перейти к цитате
Проверяю значение с помощью CryptVerifySignature с флагом 0 и описанием null
Если что-то вроде этого CryptVerifySignature(hHash,PByte(SignedData.Str),SignedData.Len,hPubKey,nil,0) то правильно.
Автор: EgorOkhotin Перейти к цитате
Что я делаю не так? Если описание не точное и где-то нужно уточнить то прошу сказать что именно.

Сертификат при подписи и проверке один. При подписи я открываю контейнер и функцией CryptGetUserKey беру ключ для подписывания, а
Даже любопытно куда вы потом его указываете, потому что этот ключ потом некуда указывать при подписании хэша. Алгоритмы гост также не требуют ключа при создании объекта хэша (указывается 0/null). Опишите этот момент подробнее.

Достаточно создать объект хэша на контексте с контейнером и объект хэша неявно унаследует ссылку на контейнер. При подписании хэша остается указать константу AT_KEYEXCHANGE или AT_SIGNATURE для выбора из контейнера правильного ключа (подозреваю что в этот параметр Вы и передали ключ).
CryptSignHash(hHash, dwKeySpec, nil{description}, 0{flags}, PByte(Rez.str), DataLen)
Автор: EgorOkhotin Перейти к цитате
при проверке из сертификата того же самого беру только публичный ключ и импортирую его с помощью CryptImportKey.
После прасинга ключа из сертификата он получется длиной 101 байт.
Странная длина, перепроверю что у меня.

Вообще нетрудно получить значение KP_CERTIFICATE от ключа полученного CryptGetUserKey или считать сертификат из файла. Это будет образ cертификата в памяти. Его передать в CertCreateCertificateContext и из полученного контекста выбрать PublicKeyInfo и передать в CryptImportPublicKeyInfo.
Offline EgorOkhotin  
#3 Оставлено : 3 июля 2019 г. 7:50:08(UTC)
EgorOkhotin

Статус: Активный участник

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

Сказал(а) «Спасибо»: 4 раз
Хэш всегда одинаковый и создаю я его с помощью VERIFY_CONTEXT.
CryptVerifySignature тоже также как и выше.

Я пытался импортировать ключ через CryptImportPublicKeyInfo но у меня вылетает Access Violation Exception. Не совсем понимаю почему. Я брал pCertContext -> pCertInfo -> SubjectPublicKeyInfo. Я не силен в плюсах и возможно где-то ошибся. Я планировал все делать через сертификаты так как проверка проверка не должна зависить от контейнера, только от публичного ключа.

По поводу импорта публичного ключа. Я нашел на гитхабе парсер ASN1 и из сертификата доставал ключ, закидывал его в этот парсер. Я нашел это в репозитории GostCryptography. Возможно тут есть ошибка со стандартным парсером из сертификата, который передает неверные данные парсеру.

Работа с ключами у меня реализована следующим образом.

Публичный ключ : сертификат -> достаем ключ -> ans1 парсер -> CryptImportKey(hProv, keyBytes, keyBytes.Length, null, flags, hKey). Вот в импорт кей я уже кидаю публичный
Приватный ключ :
сертификат ->
получаем имя контейнера ->
открываем провайдер вместе с контейнером ->
SetProviderParameter(hProv, keyNumber, PP_KEYEXCHANGE_PIN, keyPasswordData) -> //keyNumber = AT_KEYEXCHANGE
CryptGetUserKey(hProv, keyNumber, hKey)

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

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

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

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 396 раз в 366 постах
Цитата:
Я пытался импортировать ключ через CryptImportPublicKeyInfo но у меня вылетает Access Violation Exception. Не совсем понимаю почему.

Цитата:
По поводу импорта публичного ключа. Я нашел на гитхабе парсер ASN1 и из сертификата доставал ключ, закидывал его в этот парсер. Я нашел это в репозитории GostCryptography. Возможно тут есть ошибка со стандартным парсером из сертификата, который передает неверные данные парсеру.
Тут наверно интересно что в keyBytes (в шестнадцатиричной записи до 04 40 включительно) и что возвращает CryptImportKey, какое значение после CryptImportKey показывает GetLastError().

Посмотрел, что у меня в памяти по адресу SubjectPublicKeyInfo для одного из сертификатов:
Код:
4 байта указатель на строку алгоритма        Algorithm.pszObjId
  1.2.643.7.1.1.1.1
4 байта длина параметров алгоритма           Algorithm.Parameters.cbData 21 байт
4 байта указатель на данные параметров       Algorithm.Parameters.pbData
  30 13 06 07 2A 85 03 02 02 24 00 06 08 2A 85 03 07 01 01 02 02
  или 2 оида ASN:SEQUENCE:OID:1.2.643.2.2.36.0,OID:1.2.643.7.1.1.2.2
4 байта длина открытого ключа                PublicKey.cbData            66 байт
4 байта указатель на данные ключа            PublicKey.pbData
  04 40 ...

То есть распарсенная строка алгоритма и 2 блоба на нераспарсенные данные сертификата. Такое даже с парсером наверно несложно сделать.

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

Offline EgorOkhotin  
#5 Оставлено : 3 июля 2019 г. 13:42:50(UTC)
EgorOkhotin

Статус: Активный участник

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

Сказал(а) «Спасибо»: 4 раз
keyBytes.png (38kb) загружен 3 раз(а).

Вот keyBytes перед импортом

06200000492E00004D41473100010000301306072A85030202240006082A850307010102021B63870B4C85D1F3AB70193A912799175A2580C0BF680BEB36E0F950F30320D36788FF06DC54DECF93EFDBE603623AE081BBA95753B65E3D0E1C355CDF201647

ErrCode после импорта равен 0
Указатель на ключ изменился и похож на валидный 2800115412816

Вот сырой сертификат cert.txt (4kb) загружен 2 раз(а).
Вручную смотрел сертификат вот этим
https://holtstrom.com/mi...el/tools/asn1decoder.php


Что-то еще нужно?
UPDATE:
Вот SubjectPublicKeyInfo. Ровно 100 байт получается, потом нули идут.
3082015B3120301E06092A864886F70D0109011611696E666F4063727970746F70726F2E72753118301606052A85036401120D31303337373030303835343434311A301806082A85030381030101120C303037373137313037393931310B300906035504

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

Offline Aleksandr G*  
#6 Оставлено : 3 июля 2019 г. 15:19:00(UTC)
Aleksandr G*

Статус: Активный участник

Группы: Участники
Зарегистрирован: 13.09.2016(UTC)
Сообщений: 126

Сказал(а) «Спасибо»: 8 раз
Поблагодарили: 35 раз в 28 постах
Усиленный контроль ключей включен? (С ним CryptVerifySignature после CryptImportKey не работает, согласно руководству прогаммиста следует использовать CryptImportPublicKeyInfo)
Offline EgorOkhotin  
#7 Оставлено : 3 июля 2019 г. 16:05:45(UTC)
EgorOkhotin

Статус: Активный участник

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

Сказал(а) «Спасибо»: 4 раз
Автор: Aleksandr G* Перейти к цитате
Усиленный контроль ключей включен? (С ним CryptVerifySignature после CryptImportKey не работает, согласно руководству прогаммиста следует использовать CryptImportPublicKeyInfo)


Я ничего не менял, так, что да включен. Дело в том что CryptImportPublicKeyInfo кидает AccessViolation, что я делаю не так еще не понял.
Offline EgorOkhotin  
#8 Оставлено : 3 июля 2019 г. 17:26:00(UTC)
EgorOkhotin

Статус: Активный участник

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

Сказал(а) «Спасибо»: 4 раз
Я нашел проблемы при маршаллинге. И получаю новую ошибку.
https://www.cryptopro.ru....aspx?g=posts&t=4281 помогла вот эта тема

Теперь ошибка 0x8009310b при CryptImportPublicKeyInfo. Что делать с ней? :)

SubjectPublicKey нужной длины. Все как было указано выше.

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

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

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

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

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 396 раз в 366 постах
Цитата:
Вот keyBytes перед импортом
Мне кажется (на первый взгляд, глубоко не вникал) что структура неправильная: заголовок правдоподобный на первый взгляд, потом недекодированные параметры 21 байт, потом судя по сертификату "голый" открытый ключ 64 байт, не указано самого алгоритма ключа. Сами данные ключа на месте, но обертка бывшая в сертификате исчезла в процессе. Ключ вполне мог импортироваться как гост-2001 вместо гост-2012, ведь алгоритм не указан, а длина совпадает. Для справки контекст создавали с типом 80?

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


Зато из данных keyBytes легко можно собрать структуру SubjectPublicKeyInfo.
Пусть все данные будут в одном блоке памяти Block (массив байт), тогда если делать с выравниванием на двойное слово, размером структуры SubjectPublicKeyInfo 24 байта, алгоритмом гост-2012 256, указатель на Block будем передавать в CryptImportPublicKeyInfoA:


Цитата:
Вот SubjectPublicKeyInfo. Ровно 100 байт получается
На мой взгляд SubjectPublicKeyInfo не похожа на правильную структуру. Согласно тому что у меня программа показывает и по справке с течнет первым должен идти указатель на строку, а складывается впечатление у Вас там ASN структура 30 82 01 5B (то есть последовательность длиной 15B = 347 байт, никак не 100 байт. Допустим, что первые 4 байта все же указатель случайно напомнивший структуру, тогда следующие 4 байта должны быть количество байт, но там 3120301E - непонятно что, так как 1E не должно быть в строках, а 31 не очень похоже на выравнивание указателей. зато если разбить как 3120 потом 301E потом 0609 очень похоже на продолжение ASN структуры. То есть это недекодированная ASN структура, а не структура SubjectPublicKeyInfo. Затем 2A864886F70D010901 какой-то странный оид. Дальше наверно нет смысла рассматривать, как уже выяснили длина в начале не совпадает значит структура будет "битая".

Хорошо, по длине прикинем, у меня 20-24 байта сама стуктура SubjectPublicKeyInfo. Пусть данные на которые ссылка в структуре идут сразу после нее, тогда: + 66 байт ключ + 21 байт параметры + 17 байт строка алгоритма + #0 в конце строки = 125 байт минимум, 136 байт с выравниванием указателей на двойное слово, 154 байта если Юникод с выравниванием. То есть 100 байт маловато если все данные "в одном куске памяти" даже если выкинуть параметры. Однако параметры в сертификате присутствуют, так что нет причин их выкидывать.

Цитата:
Я ничего не менял, так, что да включен.
По умолчанию контроль ключей в положении "1", то есть "нормальный". Усиленный это "2", без контроля "0". Если стандартная установка КС1/КС2 и ничего не меняли - усиленный контроль изначально должен быть выключен.
Цитата:
Я нашел проблемы при маршаллинге. И получаю новую ошибку.
К сожалению, я про маршаллинг вообще ничего не знаю, так как такой термин не встречал в моем языке/среде программирования. Изменилось ли содержание получаемых структур после исправлений? Если да, то наверно нужно новую версию.
Цитата:
0x8009310B
Встречено неверное значение тега ASN1. Надо полагать, передаваемые данные неверные.

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

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

Статус: Активный участник

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

Сказал(а) «Спасибо»: 4 раз
Автор: two_oceans Перейти к цитате
. Изменилось ли содержание получаемых структур после исправлений? Если да, то наверно нужно новую версию.Встречено неверное значение тега ASN1. Надо полагать, передаваемые данные неверные.


У меня х64 система.

Да изменилось. Вот что содержит SubjectPublicKeyInfo когда через CERT_INFO заирраю:
E0BEE0DA260200001500000000000000E00FC5F4260200004200000000000000F80FC5F4260200000000000000000000

Вот что содержит структура которую я намапил из SubjectPublicKeyInfo(она тоже не проходит выкидывает 0x80093104):
B4B5D6DA26020000
15000000
C8B5D6DA26020000
42000000
E0B5D6DA26020000
00000000
312E322E3634332E372E312E312E312E3100
0000
301306072A85030202240006082A85030701010202
004200
04401B63870B4C85D1F3AB70193A912799175A2580C0BF680BEB36E0F950F30320D36788FF06DC54DECF93EFDBE603623AE081BBA95753B65E3D0E1C355CDF201647



Пробовал нули которые до строки идут заменять с 32 на 64 бита.
Кодировка строки алгоритма ASCII. Длина массива получется 18 вместа с '\0'
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest
2 Страницы12>
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.