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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline vanesrilax  
#1 Оставлено : 24 января 2020 г. 11:02:34(UTC)
vanesrilax

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

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

Поблагодарили: 1 раз в 1 постах
Здравствуйте!
Установил:
КриптоПро CSP 5.0 для Windows
КриптоПро .NET 1.0.7132.0 (NET-x64-rus.msi)
КриптоПро .NET SDK 1.0.7132.0 (NETSDK-x64-rus.msi)
Мне необходимо авторизовать пользователей на сайте через ESIA
Пишу программу которая на вход получает строку типа:
Код:
fullname birthdate2020.01.24 08:48:17 +0100MICC01565f8ba7023-fa2b-4365-901b-e6062d4d2933

Мне эту строку нужно подписать чтоб использовать для формирования URL.
В качестве примера взял:
http://cpdn.cryptopro.ru...94-a996-37d88776309e.htm
Далее из байт я делаю base64 url safe. Получается URL типа: (base64 я обрезал для удобства просмотра)
Код:
https://esia-portal1.test.gosuslugi.ru/aas/oauth2/ac?client_id=MICC01565&client_secret=MIIUjQYJKoZIhvcNAQcCoIIUfjCCFHoCAQExDjAMBggqhQMHAQECAgUAMAsGCSqGSIb3DQEHAaCCEKMwgggEMIIHsaADAgECAhEDTIvMesQM-oDpESJGsDMu_zAKBggqhQMHAQEDAjCCASgxIDAeBgkqhkiG9w0BCQEWEW9vYjUxQG1haWwub3JiLnJ1MRgwFgYFKoUDZAESDTEwNjU2MTIwMzI4OTIxGjAYBggqhQMDgQMBARIMMDA1NjEyMDQ1ODQwMQswCQYDVQQGEwJSVTEzMDEGA1UECAwqNTYg0J7RgNC10L3QsdGD0YDQs9GB0LrQsNGPINC-0LHQu9Cw0YHRgtGMMR0wGwYDVQQHDBTQsy4g0J7RgNC10L3QsdGD0YDQszExMC8GA1UECQwo0YPQuy4g0JzQsNGA0YjQsNC70LAg0JbRg9C60L7QstCwLCDQtC40MjEcMBoGA1UECgwT0JPQkdCj0JcgItCc0JjQkNCmIjEcMBoGA1UEAwwT0JPQkdCj0JcgItCc0JjQkNCmIjAeFw0xOTAzMTQwNjIyNTVaFw0yMDAzMTQwNjMyNTVaMIIBRzEgMB4GCSqGSIb3DQEJARYRb29iNTFAbWFpbC5vcmIucnUxGjAYBggqhQMDgQMBARIMMDA1NjEyMDQ1ODQwMRgwFgYFKoUDZAESDTdA5oHuDmvpS3Vy5mN6g2Xj&redirect_uri=https%3A%2F%2Fpp.io%2F&scope=fullname+birthdate&response_type=code&state=57b9ae3d-52a1-4f49-8b48-87c5d8784167&access_type=offline&timestamp=2020.01.24+08%3A56%3A58+%2B0100

При переходе по данной ссылке ESIA мне возвращает:
Код:
error_description: ESIA-007005: The client is not authorized to request an access token using this method.
state: 57b9ae3d-52a1-4f49-8b48-87c5d8784167
error: unauthorized_client

Может я взял не тот пример для подписи?
Заранее большое спасибо!
Offline two_oceans  
#2 Оставлено : 24 января 2020 г. 12:39:32(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 75 раз
Поблагодарили: 255 раз в 239 постах
Добрый день.
С ЕСИА плотно не разбирался, но по ответу вроде как выглядит что oauth2 запрещен в принципе. Или может быть не с того IP что зарегистрировали в ЕСИА?
Offline vanesrilax  
#3 Оставлено : 24 января 2020 г. 12:44:04(UTC)
vanesrilax

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

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

Поблагодарили: 1 раз в 1 постах
Автор: two_oceans Перейти к цитате
Добрый день.
С ЕСИА плотно не разбирался, но по ответу вроде как выглядит что oauth2 запрещен в принципе. Или может быть не с того IP что зарегистрировали в ЕСИА?

Проблема в том что если я подписываю строку с помощью обычного сертификата RSA, то все работает, он просто ругается на сертификат, что в принципе логично, так как я грузил при регистрации ИС другой сертификат
Offline Артём С  
#4 Оставлено : 28 января 2020 г. 20:54:03(UTC)
Артём С

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

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

Сказал(а) «Спасибо»: 2 раз
Поблагодарили: 1 раз в 1 постах
Абсолютно та же ситуация (только на Java)
На локальной машине стоит:
CSP: КриптоПро CSP 4.0.9963 (Abel) от 23.11.2018
JCP: jcp-2.0.39852

По примеру из PKCS7Example.java (из архива jcp данной версии)
Сделал следующее

Код:

    public static byte[] sign(String text, KeyStore keyStore, String alias, String password) throws Exception {
        byte[] dataToSign = text.getBytes();
        // Заменяем GOST-алгоритм
        Utility.initJCPAlgorithms();

        final List<Certificate> certificateChain = Arrays.asList(keyStore.getCertificateChain(alias));
        // Конвертируем цепочку в X509Certificate.
        final Collection<X509Certificate> chain = Arrays.asList(certificateChain.toArray(new X509Certificate[certificateChain.size()]));
        // Сертификат подписи - первый в списке.
        final X509Certificate signerCert = chain.iterator().next();

        Store certStore = new JcaCertStore(chain);

        final PrivateKey privateKey = (PrivateKey)keyStore.getKey(alias, password.toCharArray());

        // Подготавливаем подпись.
        CMSSignedDataGenerator generator = new CMSSignedDataGenerator();

        ContentSigner contentSigner = new GostContentSignerProvider(privateKey, JCP.PROVIDER_NAME);

        SignerInfoGenerator signerInfoGenerator = new JcaSignerInfoGeneratorBuilder(
                new GostDigestCalculatorProvider(privateKey, JCP.PROVIDER_NAME)).build(contentSigner, signerCert);

        generator.addSignerInfoGenerator(signerInfoGenerator);
        generator.addCertificates(certStore);

        // Создаем совмещенную подпись PKCS7.
        CMSProcessable content = new CMSProcessableByteArray(dataToSign);
        CMSSignedData signedData = generator.generate((CMSTypedData) content, false);

        // Сформированная подпись.
        byte[] pkcs7 = signedData.getEncoded();


        // Сформированная подпись.
        return pkcs7;
    }


При этом точно также же переключаюсь на старый способ, использующий самоподписанный RSA - все работает.
Все остальные входные данные (способ формирования url, секрета, и тд) такиеже, меняется только способ генерации байт pkcs7 подписи. Которые потом кодируются Base64.getUrlEncoder().encodeToString(resultBytes).

Смотрел глазами результат в asn1 viewer`e - кажется всё окей. Туда кладутся 2 серта - пользовательский и УЦ (корневого не наблюдал, но его наверное и не должно быть). В подписи сформированной старым образом все примерно также (только алгоритмы другие и серты менее жирные чем боевые).
Также уточню что в CSP имортировал сертификаты ЦА и Корневой.
Пробовал на сертификатах/закрытых ключах как тестовых криптопро, так и на боевых от тензора. Пробовал только с тестовым ESIA.

В тех портале тестового загрузил серт. Переключил настройку "Алгоритм шифрования" на гост2012 (которая кажется ни на что не влияет, тк старый способ после этого продолжил работать).
Ошибка такая же как и у автора. И в прошлый раз когда протух тестовый сертификат - была такая же ошибка, которая пропала после перевода на новый серт. Так что дело точно в подписании. esia-2012-pkcs7-failed.zip (6kb) загружен 5 раз(а).

Не понятно что не так.
Мб конечно в ЕСИА косяки с инфраструктурой или просто баги (не подгружены корневые серты, не работает гост2012 и тд), особенно учитывая что это тестовый.
Будем обращаться и к ним.
Но если кто-то сможет помочь - буду благодарен.

Приложу сформированный pkcs7, данные (строка) и серт если вдруг кто возьмется перепроверять.
esia-2012-pkcs7-failed.zip (6kb) загружен 5 раз(а).

Отредактировано пользователем 29 января 2020 г. 14:20:37(UTC)  | Причина: Не указана

Offline vanesrilax  
#5 Оставлено : 30 января 2020 г. 10:34:52(UTC)
vanesrilax

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

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

Поблагодарили: 1 раз в 1 постах
Решил проблему так:
Поднял виртуальную тачку под Ubuntu. На нее накатил КриптоПРО CSP 5, под линукс в составе CSP идет утилита cryptcp.
Далее вставил фшелку в сервер и примонтировал ее, кто не знает как сделать, есть тут
Потом по этой статье копирую контейнер на жесткий диск и ставлю сертификат в хранилище uMy.
Далее пишем программу, алгоритм простой:
записываем строку для подписи в файл "message"
вызываем утилиту cryptcp с параметрами, она считывает строку из файла "message" подписывает ее и записывает данные в другой файл "message.sgn" в формате BASE64.
вот сама команда:
Код:
cryptcp -signf -dir /var/www/html -strict -cert -detached -thumbprint <отпечаток сертификата который Вы импортировали в хранилище uMy> /tmp/message

Если что то не понятно по параметрам, то вот документация
Далее в программе считываем данные из файла "message.sgn", делаем из них base64 url safe. Для тех кто не знает что это такое, то вот алгоритм на PHP:
Код:

$file = file_get_contents("message.sgn"); //считываем данные из файла в переменную
$file_url_safe = str_replace(array('+','/','='),array('-','_',''),$file); // преобразуем в base64 url safe
$file_url_safe = str_replace("\n", "", $file_url_safe); // делаем все в одну строку

Далее подставляем эту строку в client_secret и будем Вам счастье!
P.S.
Важно вызывать утилиту cryptcp от того пользователя от которого вы импортировали сертификат из контейнера.
Решение может далеко не самое удачное, но оно работает.
thanks 1 пользователь поблагодарил vanesrilax за этот пост.
Артём С оставлено 03.02.2020(UTC)
Offline Артём С  
#6 Оставлено : 3 февраля 2020 г. 13:17:34(UTC)
Артём С

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

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

Сказал(а) «Спасибо»: 2 раз
Поблагодарили: 1 раз в 1 постах
Автор: vanesrilax Перейти к цитате
Решил проблему так:
Поднял виртуальную тачку под Ubuntu. На нее накатил КриптоПРО CSP 5, под линукс в составе CSP идет утилита cryptcp.
Далее вставил фшелку в сервер и примонтировал ее, кто не знает как сделать, есть тут
Потом по этой статье копирую контейнер на жесткий диск и ставлю сертификат в хранилище uMy.
Далее пишем программу, алгоритм простой:
записываем строку для подписи в файл "message"
вызываем утилиту cryptcp с параметрами, она считывает строку из файла "message" подписывает ее и записывает данные в другой файл "message.sgn" в формате BASE64.
вот сама команда:
Код:
cryptcp -signf -dir /var/www/html -strict -cert -detached -thumbprint <отпечаток сертификата который Вы импортировали в хранилище uMy> /tmp/message

Если что то не понятно по параметрам, то вот документация
Далее в программе считываем данные из файла "message.sgn", делаем из них base64 url safe. Для тех кто не знает что это такое, то вот алгоритм на PHP:
Код:

$file = file_get_contents("message.sgn"); //считываем данные из файла в переменную
$file_url_safe = str_replace(array('+','/','='),array('-','_',''),$file); // преобразуем в base64 url safe
$file_url_safe = str_replace("\n", "", $file_url_safe); // делаем все в одну строку

Далее подставляем эту строку в client_secret и будем Вам счастье!
P.S.
Важно вызывать утилиту cryptcp от того пользователя от которого вы импортировали сертификат из контейнера.
Решение может далеко не самое удачное, но оно работает.

у меня так тоже заработало !
спасибо большое!!!
вероятно чуть попозже сравню чем отличается подписи которые делает данная утилита от тех что получаются нормально в коде и отпишусь суда если что-то выяснится или получится сделать
Offline vanesrilax  
#7 Оставлено : 3 февраля 2020 г. 14:25:17(UTC)
vanesrilax

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

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

Поблагодарили: 1 раз в 1 постах
Цитата:
у меня так тоже заработало !
спасибо большое!!!
вероятно чуть попозже сравню чем отличается подписи которые делает данная утилита от тех что получаются нормально в коде и отпишусь суда если что-то выяснится или получится сделать

У меня на решение данной задачи было мало времени, пошел по пути меньшего сопротивления.
Хотелось бы узнать мнение экспертов на тему КриптоПРО .net SDK, неужели там нет реализации подобной подписи?

Offline Артём С  
#8 Оставлено : 10 февраля 2020 г. 19:52:21(UTC)
Артём С

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

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

Сказал(а) «Спасибо»: 2 раз
Поблагодарили: 1 раз в 1 постах
Сравнив подписи которые выдает JCP и cryptcp
Я выявил 2 отличия:
1. В рабочее решение с помощью cryptcp вставлен сертификат:
OBJECT IDENTIFIER 1.2.840.113549.1.9.16.2.47 signingCertificateV2 (S/MIME Authenticated Attributes)

Он располагается в конце блока, описывающего параметры подписи, т.е. после элементов содержащих:
OBJECT IDENTIFIER 1.2.840.113549.1.9.3 contentType (PKCS #9)
OBJECT IDENTIFIER 1.2.840.113549.1.9.5 signingTime (PKCS #9)
OBJECT IDENTIFIER 1.2.840.113549.1.9.4 messageDigest (PKCS #9)

2. Отличается OID алгоритма в самом конце (как понял это алгоритм закрытого ключа, но это не точно):
- CLI: szOID_CP_GOST_R3410_12_256 "1.2.643.7.1.1.1.1" Алгоритм ГОСТ Р 34.10-2012 для ключей длины 256 бит, используемый при экспорте/импорте ключей
а также там в SEQUENCE содержащей данный ОИД вставлен NULL
- JCP: szOID_CP_GOST_R3411_12_256_R3410 "1.2.643.7.1.1.3.2" Алгоритм цифровой подписи ГОСТ Р 34.10-2012 для ключей длины 256 бит

Подозреваю что именно п.1 необходим чтобы на стороне ЕСИА всё проверялось норм.
Интересно как его добавить средствами Java/C# библиотек.
Offline two_oceans  
#9 Оставлено : 11 февраля 2020 г. 5:03:11(UTC)
two_oceans

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

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

Сказал(а) «Спасибо»: 75 раз
Поблагодарили: 255 раз в 239 постах
https://tc26.ru/about/do...heskaya-zashchita-1.html
Автор: Артём С Перейти к цитате
2. Отличается OID алгоритма в самом конце (как понял это алгоритм закрытого ключа, но это не точно):
- CLI: szOID_CP_GOST_R3410_12_256 "1.2.643.7.1.1.1.1" Алгоритм ГОСТ Р 34.10-2012 для ключей длины 256 бит, используемый при экспорте/импорте ключей
а также там в SEQUENCE содержащей данный ОИД вставлен NULL
Что-то совсем с другой строки Вы посмотрели, в подписи не может быть закрытого ключа, по документу выше оид означает "алгоритм подписи ГОСТ Р 34.10-2012 с ключом 256", а судя по присутствию NULL далее это открытый ключ ГОСТ Р 34.10-2012 256 и скорее всего это часть сертификата - обычно голый открытый ключ в подписи не лежит. Обратите внимание, что сертификат сам по себе тоже содержит Raw подпись ГОСТ 2012 длины 64 байта (или 128 байт для гост 2012 512) и все что идет от signingCertificateV2 до нее это сертификат, проследите по уровням вложения ASN1. Странно что это в конце. Возможно не весь CLI файл загрузился в ASN1 редактор.
Автор: Артём С Перейти к цитате
- JCP: szOID_CP_GOST_R3411_12_256_R3410 "1.2.643.7.1.1.3.2" Алгоритм цифровой подписи ГОСТ Р 34.10-2012 для ключей длины 256 бит
Вот это как раз похоже на Raw подпись: "алгоритм подписи ГОСТ Р 34.10-2012 с ключом 256 с хэшированием ГОСТ Р 34.11-2012". По идее оид должен быть в конце подписи в обоих случаях.
Итого, различие в наличие сертификата. В конца выше сертификат, насколько понимаю, добавляется. Одна строка должна быть для сертификата, который подписывает (не включается), вторая для включения всей цепочки.
Код:
SignerInfoGenerator signerInfoGenerator = new JcaSignerInfoGeneratorBuilder(
                new GostDigestCalculatorProvider(privateKey, JCP.PROVIDER_NAME)).build(contentSigner, signerCert);
...
generator.addCertificates(certStore);
Offline test.user  
#10 Оставлено : 13 февраля 2020 г. 12:59:50(UTC)
test.user

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

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

Сказал(а) «Спасибо»: 2 раз
Ребята, если все таки справились с проблемой, поделитесь плз решением) Чувствую скоро многие начнут переходить на ГОСТ12 вследствие отключения 2001 в первом квартале 2020.
Вопрос конечно относится к ЕСИА, а не к КриптоПро, но всеже по тепе топика: Я правильно понимаю что при авторизации на ESIA единственное что нужно подписать и перевести в Base64 safe url - это client_secret? Если я правильно понял, все запросы идут без шифрования. Т.е. единственное различие с авторизацией по RSA - это то что подпись client_secret будет осуществляться с помощью сертификатов и ключей GOST2012?
Offline Артём С  
#11 Оставлено : 13 февраля 2020 г. 13:56:42(UTC)
Артём С

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

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

Сказал(а) «Спасибо»: 2 раз
Поблагодарили: 1 раз в 1 постах
Автор: test.user Перейти к цитате
Ребята, если все таки справились с проблемой, поделитесь плз решением) Чувствую скоро многие начнут переходить на ГОСТ12 вследствие отключения 2001 в первом квартале 2020.
Вопрос конечно относится к ЕСИА, а не к КриптоПро, но всеже по тепе топика: Я правильно понимаю что при авторизации на ESIA единственное что нужно подписать и перевести в Base64 safe url - это client_secret? Если я правильно понял, все запросы идут без шифрования. Т.е. единственное различие с авторизацией по RSA - это то что подпись client_secret будет осуществляться с помощью сертификатов и ключей GOST2012?

да, всё верно
отпишусь если доделаю решение на Java

thanks 1 пользователь поблагодарил Артём С за этот пост.
test.user оставлено 13.02.2020(UTC)
Offline test.user  
#12 Оставлено : 18 февраля 2020 г. 12:40:33(UTC)
test.user

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

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

Сказал(а) «Спасибо»: 2 раз
А подскажите, пожалуйста, у меня такая же проблема с unauthorized_client, но в логах вижу более конкретную ошибку:
ERROR ru.gosuslugi.esia.core.api.security.PKCS7SignatureService - Signature validation error: Unknown signature type requested: 1.2.643.7.1.1.6.1WITH1.2.643.7.1.1.6.1.
2020-02-16 21:56:15,697 [tomcat-exec-26] ERROR ru.gosuslugi.esia.core.api.security.oauth2.SignedClientSecret - Error while verifying certificate
2020-02-16 21:56:15,697 [tomcat-exec-26] ERROR ru.atc.esia.aas.oauth2.server.filter.AbstractOAuth2Filter - Request: The signature in client secret parameter was not verified.

Это значит, что ЕСИА не может прочитать подпись, которую я передаю? Может быть они используют более старую версию jcp? Как вообще в таком случае договориться с ЕСИА, какие параметры подписи нужно использовать? Можно ли как то проверить корректность подписи локально?
Благодарен за любую информацию.
Offline test.user  
#13 Оставлено : 18 февраля 2020 г. 15:20:30(UTC)
test.user

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

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

Сказал(а) «Спасибо»: 2 раз
Вроде заработало с кодом из этой темы:
https://www.cryptopro.ru...aspx?g=posts&t=16526
также есть ответ по моему вопросу тут:
https://www.cryptopro.ru...&m=112787#post112787
Offline Юсупов К.И.  
#14 Оставлено : 21 августа 2020 г. 20:01:54(UTC)
Юсупов К.И.

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

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

Здравствуйте! Столкнулись с аналогичной ошибкой (ESIA-007005) при переходе с использования сертификата RSA на ГОСТ-2012.
Вот такой код успешно использовался ранее:

Код:
var content = Encoding.UTF8.GetBytes(dataToSign);
var contentInfo = new ContentInfo(content);
var signed = new SignedCms(contentInfo, true);
var signer = new CmsSigner(cert);
signed.ComputeSignature(signer); 
var secret = signed.Encode().ToBase64().UrlSafeEncode();


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