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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Владимир Шаронов  
#1 Оставлено : 12 ноября 2018 г. 23:17:28(UTC)
Владимир Шаронов

Статус: Новичок

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

Сказал(а) «Спасибо»: 2 раз
Коллеги, подскажите, пож-та, как зная ALG_ID алгоритма открытого ключа ОДНОЗНАЧНО получить ALG_ID соответствующего хэш-алгоритма для цифровой подписи?

Прошу обратить внимание на следующий код. В данном примере я жестко прописываю OID хэш-алгоритма и проверяю, соответствует ли ему в паре с алгоритмом открытого ключа алгоритм подписи. Можно ли зная ТОЛЬКО алгоритм открытого ключа ОДНОЗНАЧНО получить соответствующий ему хэш-алгоритм для цифровой подписи по-умолчанию без хардкодирования?

Код:

//получаю алгид = 11811 для алгоритма открытого ключа (1.2.643.2.2.19 - ГОСТ Р 34.10-2001)
ALG_ID alg_pubk = CertOIDToAlgId(cert->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);

//получаю алгид = 32798 для хэш-алгоритма (1.2.643.2.2.9 - ГОСТ Р 34.11-94)
ALG_ID alg_hash = CertOIDToAlgId(szOID_CP_GOST_R3411); //прописываю хэш-алгоритм "ХАРДКОДОМ"

//создаю пару алгидов для определения алгоритма подписи
ALG_ID alg_sign[] = { alg_hash, alg_pubk };

//получаю информацию об алгоритме подписи 1.2.643.2.2.3 - ГОСТ Р 34.11/34.10-2001
//таким образом я осуществляю валидацию алгоритма
//если я например, использую в качестве хэш-алгоритма алгид от оида szOID_CP_GOST_R3411_12_256, то oid_sign будет = NULL
auto oid_sign = CryptFindOIDInfo(CRYPT_OID_INFO_SIGN_KEY, alg_sign, CRYPT_SIGN_ALG_OID_GROUP_ID);


То что мне нужно работает на более высоком уровне в классе SignedCms из .NET. В приведенном ниже примере для подписания на вход методу подаются только подписываемые данные и сертификат. Каким образом здесь определяется хэш-алгоритм для подписи?

Код:

public static byte[] Sign(byte[] data, X509Certificate2 certificate)
{
    if(data == null)
        throw new ArgumentNullException("data");
    if(certificate == null)
        throw new ArgumentNullException("certificate");
        
    // setup the data to sign
    ContentInfo content = new ContentInfo(data);
    SignedCms signedCms = new SignedCms(content, false);
    CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, certificate);
        
    // create the signature
    signedCms.ComputeSignature(signer);
    return signedCms.Encode();
}
Offline two_oceans  
#2 Оставлено : 13 ноября 2018 г. 8:00:53(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 394 раз в 366 постах
Добрый день!
В принципе это смахивает на очередное изобретение велосипеда: с одной стороны, вопрос неоднократно спрашивался, если просмотреть форум с августа и найдете 2-3 похожие темы. С другой стороны, вопрос не имеет желаемого ответа. Насчет реализации в классе SignedCms из .NET ответить не смогу.

Вкратце: от хардкодирования полностью уйти почти невозможно. Системные функции слишком полагаются на реестр и установка любого конфликтующего криптопровайдера рискует нарушить работу определения algid по oid, так как oid более-менее стандартны, но algid у каждого типа криптопровайдера может отличаться для одного и того же oid. Используя CertOIDToAlgid Вы находите algid по версии неизвестно какого криптопровайдера.

Хорошая подсказка может быть в параметрах алгоритмов хэша и подписи около упомянутого в вопросе pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId по oid параметров можно однозначно определить и oid самого алгоритма (но это тоже скорее всего потребует хардкодирования). Нюансы - у гост-2012 хэширование не предусматривает параметры, поэтому в данное поле сертификата для сертификатов с ключом гост-2012 256 забиты параметры гост-2001, поэтому надежнее смотреть по идентификатору параметров подписи.

В итоге связать идентификаторы все же придется хардкодированием, ну или перебором входных параметров той функции которой валидируете - подобрать значение при котором возвращается не null. Для себя я создан специальный "словарик", который переводит одно значение oid в значение algid для криптопро (типы 75, 80, 81) и далее переводит algid криптопро в algid для других криптопровайдеров (пока только тип 90 по госту сопоставлен). Как вариант - можно вынести сопоставление в отдельный файл конфигурации, тогда связка не будет хардкодированной, но и не из системной функции тоже.
thanks 1 пользователь поблагодарил two_oceans за этот пост.
Владимир Шаронов оставлено 13.11.2018(UTC)
Offline Владимир Шаронов  
#3 Оставлено : 13 ноября 2018 г. 14:33:58(UTC)
Владимир Шаронов

Статус: Новичок

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

Сказал(а) «Спасибо»: 2 раз
Спасибо за ответ!

Кто-нибудь может прокомментировать функционирование приведенного выше кода на C#? Хотелось бы реализовать определение хэш-алгоритма также как у MS.
Offline Владимир Шаронов  
#4 Оставлено : 13 ноября 2018 г. 23:09:08(UTC)
Владимир Шаронов

Статус: Новичок

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

Сказал(а) «Спасибо»: 2 раз
Решил сегодня сам копнуть глубже и разобраться как же работает класс SignedCms из .NET.

Подаю для формирования подписи сертификат с алгоритмом открытого ключа 1.2.643.2.2.19 (ГОСТ 34.10-2001). В свойстве DigestAlgorithm объекта класса CmsSigner по-умолчанию прописан алгоритм 1.3.14.3.2.26 (SHA1). Формирую подпись, смотрю результат через ASN.1 редактор и вижу, что хэш-алгоритм там 1.2.643.2.2.9 (ГОСТ 34.11-94).

Посмотрел исходники SignedCms через ILSpy, но никакой "магии" там не нашёл...

Попробовал проделать то же самое на низком уровне (функция CryptSignMessage) с тем же ГОСТ-овским сертификатом, явно указывая для подписи хэш-алгоритм SHA1. Получаю такой же точно результат как и с SignedCms из .NET! SHA1 автоматически заменяется на ГОСТ 34.11-94.

Вывод: "магия", выбирающая соответствующий сертификату хэш-алгоритм для подписи реализована где-то на уровне криптопровайдера. По крайней мере, так с алгоритмом ГОСТ 34.10-2001.

Возможно, данная информация будет кому-то интересна и полезна...
Offline Андрей Писарев  
#5 Оставлено : 14 ноября 2018 г. 8:49:01(UTC)
Андрей *

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

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 12,691
Мужчина
Российская Федерация

Сказал «Спасибо»: 500 раз
Поблагодарили: 2045 раз в 1586 постах
Здравствуйте.

Да, верно.
Техническую поддержку оказываем тут
Наша база знаний
thanks 1 пользователь поблагодарил Андрей * за этот пост.
Владимир Шаронов оставлено 14.11.2018(UTC)
Offline dorogo  
#6 Оставлено : 29 ноября 2018 г. 16:37:59(UTC)
dorogo

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

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

Сказал(а) «Спасибо»: 9 раз
Поблагодарили: 1 раз в 1 постах
Здравствуйте, у меня такой же вопрос. Из сообщений выше до конца не смог понять.

У меня программа на Си, подписываю через CadesSignMessage.

Я получаю сертификат из личного хранилища, из него хочу получить хэш-алгоритм подписи (для подстановки в параметры).
прочитав ответы выше, хочу спросить/уточнить.

1) планирую или из pCertInfo->SignatureAlgorithm.pszObjId или из pCertInfo->SubjectPublicKeyInfo.Algorithm брать OID и в коде проставлять соответствующий хэш-алгоритм подписи вручную.
однако следущее утверждение меня смутило:
Цитата:
Хорошая подсказка может быть в параметрах алгоритмов хэша и подписи около упомянутого в вопросе pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId по oid параметров можно однозначно определить и oid самого алгоритма (но это тоже скорее всего потребует хардкодирования). Нюансы - у гост-2012 хэширование не предусматривает параметры, поэтому в данное поле сертификата для сертификатов с ключом гост-2012 256 забиты параметры гост-2001, поэтому надежнее смотреть по идентификатору параметров подписи.


Проверил - у меня корректно выдаются текущие OID-ы на разных ГОСТах, в том числе и на 2012-ом. Я не правильно понял утвеждение, или в гост-2012 может быть правильно проставлено, а может и нет?

2) и еще вопрос.
Цитата:
Подаю для формирования подписи сертификат с алгоритмом открытого ключа 1.2.643.2.2.19 (ГОСТ 34.10-2001). В свойстве DigestAlgorithm объекта класса CmsSigner по-умолчанию прописан алгоритм 1.3.14.3.2.26 (SHA1). Формирую подпись, смотрю результат через ASN.1 редактор и вижу, что хэш-алгоритм там 1.2.643.2.2.9 (ГОСТ 34.11-94).

Посмотрел исходники SignedCms через ILSpy, но никакой "магии" там не нашёл...

Попробовал проделать то же самое на низком уровне (функция CryptSignMessage) с тем же ГОСТ-овским сертификатом, явно указывая для подписи хэш-алгоритм SHA1. Получаю такой же точно результат как и с SignedCms из .NET! SHA1 автоматически заменяется на ГОСТ 34.11-94.


Попробовал ставить в параметры, так же, другой хэш-алгоритм в параметры, на что получал ошибку, а не "автоматическую замену на нужный хэш-алгоритм".
Это из-за того, что я подписываю через CadesSignMessage или из-за того, что программа на Си?
Offline two_oceans  
#7 Оставлено : 30 ноября 2018 г. 5:13:10(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 110 раз
Поблагодарили: 394 раз в 366 постах
Автор: dorogo Перейти к цитате
1) планирую или из pCertInfo->SignatureAlgorithm.pszObjId
Это будет алгоритм подписи удостоверяющего центра, а не алгоритм конечного сертификата. Лучше бросить такую идею, так как у большинства тестовых УЦ алгоритмы УЦ могут отличаться от алгоритмов сертификата конечного пользователя. Соответственно программа будет глючить с тестовыми сертификатами. С аккредитованными несколько получше, запрещено сертификаты гост-2012 подписывать гост-2001 и наоборот, но тоже пока нет 100% уверенности что у сертификатов гост-2012 у УЦ и конечного сертификата будут всегда совпадать значения длины ключа.
Автор: dorogo Перейти к цитате
или из pCertInfo->SubjectPublicKeyInfo.Algorithm брать OID и в коде проставлять соответствующий хэш-алгоритм подписи вручную.
Да, именно так и предлагал сделать выше.
Автор: dorogo Перейти к цитате
однако следущее утверждение меня смутило:
Цитата:
Хорошая подсказка может быть в параметрах алгоритмов хэша и подписи около упомянутого в вопросе pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId по oid параметров можно однозначно определить и oid самого алгоритма (но это тоже скорее всего потребует хардкодирования). Нюансы - у гост-2012 хэширование не предусматривает параметры, поэтому в данное поле сертификата для сертификатов с ключом гост-2012 256 забиты параметры гост-2001, поэтому надежнее смотреть по идентификатору параметров подписи.
Проверил - у меня корректно выдаются текущие OID-ы на разных ГОСТах, в том числе и на 2012-ом. Я не правильно понял утвеждение, или в гост-2012 может быть правильно проставлено, а может и нет?
Наверно не совсем точно выразился. SubjectPublicKeyInfo.Algorithm видно при обычном просмотре (двойным кликом) сертификата и там все в порядке. Речь идет про 2 дополнительных оида следующих непосредственно после SubjectPublicKeyInfo.Algorithm, которых не видно при обычном просмотре, но видно при разборе содержимого сертификата в контексте сертификата. В этих "условно скрытых" оидах по формату указываются параметры алгоритма хэширования и параметры алгоритма подписи. Первая мысль - использовать параметры алгоритма хэширования чтобы узнать какой алгоритм хэширования. И тут облом - именно первый оид (параметры алгоритма хэширования) забит заглушкой для 256 битного гост-2012. При этом в 512 битном гост-2012 также значение-заглушка, но из-за другой длины алгоритма, там заглушка другого значения, с некоторой натяжкой ее можно использовать пока не появились другие алгоритмы такой же длины. В принципе совершенно верно, что значение параметров алгоритма хэширования может быть указано и правильно, но к сожалению на это полагаться нельзя.

С "магией" все сложно, полагаю зависит скорее от конкретной установленной версии криптопровайдера, а нет от Си или использования CadesSignMessage. В соседних темах наоборот мучаются с новыми криптопровайдерами, которые "магически" ставят контейнеры гост-2001 как будто это гост-2012 256 бит.

Отредактировано пользователем 30 ноября 2018 г. 6:32:16(UTC)  | Причина: Не указана

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