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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline V Т  
#1 Оставлено : 19 сентября 2023 г. 17:40:18(UTC)
V Т

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

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

Сказал(а) «Спасибо»: 3 раз
Поблагодарили: 2 раз в 2 постах
Здравствуйте.

Передо мной стоит задача разобраться с аутентификацией на сайте с помощью Госуслуг.

Немного о нашей ситуации: для работы с криптографией мы используем КриптоПро версии 5.0.12600 в отдельном контейнере в кластере k8s. Для начала я выгружаю сертификаты (пользовательский и корневой):

Код:
certmgr -export -store uMy -dest uMy.cer
certmgr -export -store root -dest root.cer


Скачиваю их к себе на машину и загружаю на тестовый стенд ЕСИА.

Затем, следуя методическим указаниям с сайта Госуслуг https://digital.gov.ru/u...spolzovaniyuesiav336.pdf формирую запрос на эндпойнт https://esia-portal1.tes...lugi.ru/aas/oauth2/v2/ac для запроса авторизационного кода. Формирую параметр client_secret (client_id + scope + timestamp + state + redirect_uri)

Вариант 1:
У нас написано небольшое внутреннее АПИ вокруг CSP. В нём мы берём строку, которую надо подписать, загружаем в контейнер, подписываем командой:
Код:
cryptcp -signf -strict -der -detached -cert -fext sig -thumbprint configThumbprint -pin somePin pathToFileToSign

Затем, подписанный файл вычитываем, содержимое кодируем в base64 функцией base64.RawURLEncoding.EncodeToString (дело происходит в Golang) и отдаём наружу.

Вариант 2:
Получив ошибку ESIA-007053 - clientSecretWrong и найдя вот эту тему https://www.cryptopro.ru...aspx?g=posts&t=20870 с во этим сообщением https://www.cryptopro.ru...&m=141522#post141522 от пользователя MESHOK решил попробовать его схему подписи строки для client_secret.

В контейнере с КриптоПро выполняю:
Код:
csptest -keys -enum_cont -verifycontext -fqcn


Создаю в нём же вот такой скрипт create_sig_for_esia.sh, куда прописываю имя ключа из команды выше (вместо \\.\<хранилище>\<имя _контейнера>):
Код:
#!/bin/bash
set -ex

csptest -keys -cont '\\.\<хранилище>\<имя _контейнера>' -sign GOST12_256 -in /tmp/to_sign.txt -out /tmp/to_sign.sig -keytype exchange


Затем загружаю строку, которую нужно подписать в файл /tmp/to_sign.txt, вызываю мой скрипт create_sig_for_esia.sh, и выкачиваю к себе получившуюся подпись из /tmp/to_sign.sig. Затем вычиваю её содержимое как байты, разворачиваю байтовый массив зеркально (Так как в рекомендациях написано "Некоторые алгоритмы требуют развернуть зеркально, побайтово, полученную подпись", и пользователь MESHOK также советовал подпись развернуть). Затем получившийся байтовый массив кодирую в base64 и использую как client_secret.

Но и с таким вариантом получаю ошибку ESIA-007053 - clientSecretWrong (Client_secret сформирован некорректно. Client_secret не соответствует строке-сертификату, информационной системе или используемый сертификат не активен).

Загруженные на тестовый стенд сертификаты активны - Госуслуги не дают загрузить просроченные. Пробовал в запросе на получение токена два варианта параметра client_certificate_hash (от рутового и пользовательского сертификата) - оба были вычислены с помощью утилиты вот так (для пользовательского):
Код:
cpverify ~/uMy.cer -mk -alg GR3411_2012_256 -inverted_halfbytes 0

Но ошибка остаётся той же - ESIA-007053.

Правильно ли я формирую client_secret? Если нет, то укажите, пожалуйста, на мою ошибку. Пока такое ощущение, что рецепт из этого сообщения https://www.cryptopro.ru...&m=141522#post141522 не работает.
thanks 1 пользователь поблагодарил V Т за этот пост.
Arf2014 оставлено 08.12.2023(UTC)
Offline EgorKenk  
#2 Оставлено : 16 ноября 2023 г. 10:11:04(UTC)
EgorKenk

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

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

Сказал(а) «Спасибо»: 4 раз
Поблагодарили: 1 раз в 1 постах
Здравствуйте! Столкнулся с такой же проблемой. Подскажите, вам удалось решить этот вопрос? И если удалось, то как?
Offline V Т  
#3 Оставлено : 16 ноября 2023 г. 11:15:54(UTC)
V Т

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

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

Сказал(а) «Спасибо»: 3 раз
Поблагодарили: 2 раз в 2 постах
Дело в том, что у нашей компании несколько тестовых стендов в Госуслугах, и конкретно тот, который использует наш проект, как-то криво настроен. До сих пор разбираемся с их техподдержкой что с нашим стендом не так (дело это весьма бюрократичное). Я обязательно напишу сюда итог как (если) всё решится.
Offline Arf2014  
#4 Оставлено : 8 декабря 2023 г. 9:27:55(UTC)
Arf2014

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

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

Сказал(а) «Спасибо»: 1 раз
Поблагодарили: 2 раз в 1 постах
Не знаю, может кому поможет мой опыт решения подобной проблемы. Я пошел по второму варианту описанному пользователем MESHOK:
1) Получил полное название контейнера
2) Подставил в подпись
3) Отзеркалил побайтово.

И мне удалось правильно сформировать ссылку на запрос кода с Госуслуг. Однако я столкнулся с проблемой, ESIA-007053 - clientSecretWrong, на этапе получения токена доступа. То есть было совсем непонятно почему формируется ссылка правильно, а потом все валится. Подписываю одной функцией подписи. d'oh!

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

PS В моем случае была проблема с redirect_uri , в запросе был redirect_uri = no в параметрах на подпись redirect_uri = *ваш урл*. Юзал : КриптоПро CSP 5.0.12000
PSS Поделюсь болью.. об этом мало где написано, но проблема ESIA-007019: no_grants. - это проблема несоответствия запрашиваемых скоупов и скоупов, которые были в заявке при запросе сертификатов.

Отредактировано пользователем 8 декабря 2023 г. 9:34:21(UTC)  | Причина: Не указана

thanks 2 пользователей поблагодарили Arf2014 за этот пост.
V Т оставлено 08.12.2023(UTC), Ilya_Nino оставлено 24.12.2024(UTC)
Offline V Т  
#5 Оставлено : 8 декабря 2023 г. 11:31:18(UTC)
V Т

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

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

Сказал(а) «Спасибо»: 3 раз
Поблагодарили: 2 раз в 2 постах
Автор: Arf2014 Перейти к цитате
Не знаю, может кому поможет мой опыт решения подобной проблемы. Я пошел по второму варианту описанному пользователем MESHOK:
1) Получил полное название контейнера
2) Подставил в подпись
3) Отзеркалил побайтово.

И мне удалось правильно сформировать ссылку на запрос кода с Госуслуг. Однако я столкнулся с проблемой, ESIA-007053 - clientSecretWrong, на этапе получения токена доступа. То есть было совсем непонятно почему формируется ссылка правильно, а потом все валится. Подписываю одной функцией подписи. d'oh!

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

PS В моем случае была проблема с redirect_uri , в запросе был redirect_uri = no в параметрах на подпись redirect_uri = *ваш урл*. Юзал : КриптоПро CSP 5.0.12000
PSS Поделюсь болью.. об этом мало где написано, но проблема ESIA-007019: no_grants. - это проблема несоответствия запрашиваемых скоупов и скоупов, которые были в заявке при запросе сертификатов.


А можете сказать, насколько длинной у вас получается подпись через "csptest -keys -cont 'cont-name' -sign GOST12_256 -in /tmp/to_sign -out /tmp/to_sign.sig -keytype exchange"? У нас получается весьма короткая. После кодирования в base64 всего 86 символов. И проверку в ЕСИА она не проходит, что в прямом порядке байт, что в зеркальном. Всё время ESIA-007053.

При этом, если формировать отсоединённую подпись через команду "cryptcp -signf -strict -detached -cert -der -thumbprint 12345678 /tmp/to_sign -dir /tmp", то истоговая строка после base64 выходит гораздо длиннее - 4343 символа.

Вообщем, получаются совершенно разные подписи.

Параметр redirect_uri менял и так и этак. В описании тестовой системы уже добавлено всё, что можно: и с localhost, и с 127.0.0.1, и сами хосты, и полный url. В методических рекомендациях к aas/oauth2/v2/ac в примере указан обычный полный урл возврата для тестового сервера.
thanks 1 пользователь поблагодарил V Т за этот пост.
Ilya_Nino оставлено 24.12.2024(UTC)
Offline Arf2014  
#6 Оставлено : 8 декабря 2023 г. 13:25:43(UTC)
Arf2014

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

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

Сказал(а) «Спасибо»: 1 раз
Поблагодарили: 2 раз в 1 постах
Цитата:

А можете сказать, насколько длинной у вас получается подпись через "csptest -keys -cont 'cont-name' -sign GOST12_256 -in /tmp/to_sign -out /tmp/to_sign.sig -keytype exchange"? У нас получается весьма короткая. После кодирования в base64 всего 86 символов. И проверку в ЕСИА она не проходит, что в прямом порядке байт, что в зеркальном. Всё время ESIA-007053.

При этом, если формировать отсоединённую подпись через команду "cryptcp -signf -strict -detached -cert -der -thumbprint 12345678 /tmp/to_sign -dir /tmp", то истоговая строка после base64 выходит гораздо длиннее - 4343 символа.


К сожалению, пока не возможности посчитать точное кол-во символов. Я использую вариант без отсоединенной подписи, кол-во примерно такое же как у вас.

Для лучшего понимания выкачу суть реализации. У нас была на php + микросервис на typeScript :

PHP

Цитата:

public function getAuthLink(): string
{
$state = Str::uuid()->toString();
$params = $this->signParams([
'response_type' => 'code',
'access_type' => 'offline',
'redirect_uri' => $this->redirectUrl
],$state);
$authQuery = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
$authURL = $this->esiaHost . 'aas/oauth2/v2/ac';

return $authURL . '?' . $authQuery;
}

private function signParams($params, $state): array
{
$time = Carbon::now()->format('Y.m.d H:i:s O');
$clientId = $this->clientId;
$scope = implode(' ', $this->scope);
$text = empty($this->code)
? implode('', [$clientId, $scope, $time, $state, $this->redirectUrl])
: implode('', [$clientId, $scope, $time, $state, $this->redirectUrl, $this->code]);
$client = new Client();
$certificateHash = $this->esiaCertHash;
$response = $client->post($this->cryptoProServiceAddress . '/sign', [
'json' => ['text' => $text],
]);

$clientSecret = json_decode($response->getBody()->getContents())->result;

return array_merge([
'client_secret' => $clientSecret,
'client_id' => $clientId,
'scope' => $scope,
'timestamp' => $time,
'state' => $state,
'client_certificate_hash' => $certificateHash,
], $params);
}


TS

Цитата:
const getContainerPath = async () => {

const response = await execute('csptest -keys -enum_cont -verifycontext -fqcn')
const match = response.match(/\\\\\.\\HDIMAGE\\([^\s]+)/);
if (!match) {
throw new InternalException('Cannot get container. It seems that service is not correctly configured')
}
return match[1]
}

export const cryptoProSign = async (str: string): Promise<string> => {
const containerPath = await getContainerPath();
const tempFile = tempy.file({ extension: 'unsigned' })
const signedFile = tempFile + '.sgn'
await writeFile(tempFile, str)
const dirName = dirname(tempFile)
try {
const cmd = `csptest -keys -cont '${containerPath}' -sign GOST12_256 -in ${tempFile} -out ${signedFile} -keytype exchange -password "${CERTIFICATE_PIN}"`
await execute(cmd)
const result = await readFile(signedFile)
await unlink(signedFile)
await unlink(tempFile)
const reversedContent = Buffer.from(result).reverse();
return reversedContent.toString('base64');
} catch (e) {
logError(`sign error ${e}`, '', 'СryptoProSign')
throw new InternalException('Failed to create sign. It seems that service is not correctly configured' )
}
}


Цитата:
Параметр redirect_uri менял и так и этак. В описании тестовой системы уже добавлено всё, что можно: и с localhost, и с 127.0.0.1, и сами хосты, и полный url. В методических рекомендациях к aas/oauth2/v2/ac в примере указан обычный полный урл возврата для тестового сервера.


Ну в ЕСИА мы же передаем не только 1 redirect_uri, как минимум на получение кода, в подпись мы отправлем еще 4 параметра(порядок, кстати, важен!): 'client_id','scope','timestamp','state' - возможно там есть какое-то расхождение?! Так же по сертификату, вы тестируете на боевом или тестовом, который был выдан?

Цитата:

Загруженные на тестовый стенд сертификаты активны - Госуслуги не дают загрузить просроченные. Пробовал в запросе на получение токена два варианта параметра client_certificate_hash (от рутового и пользовательского сертификата) - оба были вычислены с помощью утилиты вот так (для пользовательского):


Кстати, я юзал пользовательский.

Отредактировано пользователем 8 декабря 2023 г. 13:36:31(UTC)  | Причина: Не указана

Offline V Т  
#7 Оставлено : 29 декабря 2023 г. 18:35:41(UTC)
V Т

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

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

Сказал(а) «Спасибо»: 3 раз
Поблагодарили: 2 раз в 2 постах
Моя проблема была в том, что при создании файла, через который я делал отсоединённую подпись, в конец всегда попадал символ перевода строки. Это штатная особенность команды echo. Т.е. если писать в файл вот так "echo \"{clientSecretHere}\" > /tmp/client_secret", то в конце у файла всегда будет символ \n. Обходится вызовом echo с флагом -n. Удалось заметить только скачав файл и включив в редакторе режим отображения спецсимволов. Естественно, что подписи у нас в ЕСИА не сходились, поэтому и был постоянно ответ ESIA-007053.
Offline Leximist  
#8 Оставлено : 14 февраля 2024 г. 0:57:26(UTC)
Leximist

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

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

Поблагодарили: 3 раз в 1 постах
Я пропарился с этой второй версией (v2/ac) почти неделю. В итоге добился от поддержки правильного работающего примера.
Сразу скажу, что использую Крипто Про JCP на Java, т.к. использование несертифицированных криптосредств запрещено. AuthV2JCPTest.java (11kb) загружен 64 раз(а). AuthV2JCPTest.java.zip (4kb) загружен 59 раз(а).
Также могу сказать, что пример из документации у нас не получилось запустить, и специальная утилита для подсчета хэша ключа, выдавала неправильный хэш. В новом примере (который я приложил) хэш подсчитывается на лету и сравнивается с константой на всякий случай. Думаю специалист по Java быстро разберется что к чему. Также обращаю внимание, что время на компьютере, где вы это будете запускать, должно быть точно выставлено. И переход по URL на адрес, который заканчивается на v2/ac, нужно осуществить в течение минуты после создания ссылки. То есть сразу - создали ссылку, открывайте в браузере. Если прошло больше минуты - уже работать не будет.

Надеюсь мое сообщение поможет многим в этой ветке, т.к. я был в этих условиях неделю назад.
thanks 3 пользователей поблагодарили Leximist за этот пост.
eparst оставлено 23.09.2024(UTC), Rarog1985 оставлено 27.11.2024(UTC), sbroid оставлено 27.03.2025(UTC)
Offline Ilya_Nino  
#9 Оставлено : 24 декабря 2024 г. 18:28:15(UTC)
Ilya_Nino

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

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

Сказал(а) «Спасибо»: 2 раз
PSS Поделюсь болью.. об этом мало где написано, но проблема ESIA-007019: no_grants. - это проблема несоответствия запрашиваемых скоупов и скоупов, которые были в заявке при запросе сертификатов.


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