Статус: Новичок
Группы: Участники
Зарегистрирован: 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();
}
|
|
|
|
Статус: Эксперт
Группы: Участники
Зарегистрирован: 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 по госту сопоставлен). Как вариант - можно вынести сопоставление в отдельный файл конфигурации, тогда связка не будет хардкодированной, но и не из системной функции тоже.
|
1 пользователь поблагодарил two_oceans за этот пост.
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 12.11.2018(UTC) Сообщений: 4 Откуда: Сургут Сказал(а) «Спасибо»: 2 раз
|
Спасибо за ответ!
Кто-нибудь может прокомментировать функционирование приведенного выше кода на C#? Хотелось бы реализовать определение хэш-алгоритма также как у MS.
|
|
|
|
Статус: Новичок
Группы: Участники
Зарегистрирован: 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.
Возможно, данная информация будет кому-то интересна и полезна...
|
|
|
|
Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 12,701 Сказал «Спасибо»: 500 раз Поблагодарили: 2049 раз в 1589 постах
|
|
|
1 пользователь поблагодарил Андрей * за этот пост.
|
|
|
Статус: Участник
Группы: Участники
Зарегистрирован: 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 или из-за того, что программа на Си?
|
|
|
|
Статус: Эксперт
Группы: Участники
Зарегистрирован: 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)
| Причина: Не указана
|
1 пользователь поблагодарил two_oceans за этот пост.
|
dorogo оставлено 30.11.2018(UTC)
|
|
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Important Information:
The Форум КриптоПро uses cookies. By continuing to browse this site, you are agreeing to our use of cookies.
More Details
Close