НСПК: Выпуск туннельного и сертификата для подписи

Для работы с НСПК необходимо два сертификата: один для установки зашифрованного туннеля (например при помощи stunnel), а второй непосредственно для подписи сообщений передаваемых по этому туннелю. Сам процесс выпуска заключается в следующих шагах:

  1. В лк https://mircerts.nspk.ru создается заявка на сертификат
  2. Каким-то образом создается файл заявки на выпуск сертификата и подгружается в лк. В момент создания заявки создаётся закрытый ключ
  3. После выпуска сертификата появляется возможность его скачать в лк и установить

Первоначально п.2 я сделал при помощи утилиты Linux xca, еще и радуясь при этом, что закрытый ключ остался в виде файла, и не нужно его специальными утилитами вытаскивать с токена. Но радость была не долгой — выпущеный в конечном итоге таким образом сертификат отлично работал, подписывать сообщения можно было без проблем. Одно но: только при помощи утилиты openssl. А Крипто-про с таким сертификатом не дружит от слова совсем. Т.е. не реализовать подписание в 1С и не поднять туннель при помощи stunnel. Пришлось таки воспользоваться утилитами windows. Для этого создается регистрационный inf файл вида:

Для туннельного сертификата:

[NewRequest]
Subject = "CN=ROGA, O=ROGA, C=RU, OU = SP12345, ST=Vologda Lenina 1, L=Vologda"
Exportable = TRUE
KeyLength = 512
ProviderType=80
ProviderName = "Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider"
KeySpec = 1
KeyUsage = 0xf0
MachineKeySet = FALSE

Для сертификата для подписи:

[NewRequest]
Subject = "CN=SignRTP, O=ROGA, C=RU, OU = SP12345, ST=Vologda Lenina 1, L=Vologda"
Exportable = TRUE
KeyLength = 512
ProviderType=80
ProviderName = "Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider"
KeySpec = 1
KeyUsage = 0xf0
MachineKeySet = FALSE

Далее создаем контейнер и закрытый ключ, отдельно для каждого сертификата:

certreq -new req.inf request_cp.req

Полученный файл загружаем в ЛК и ждём выпуска сертификата. После чего скачиваем его и устанавливаем. Тем самым создавая пару закрытый ключ-сертификат на токене. А дальше уже стандартные пляски с выгрузкой с токена в файл при помощи P12FromGostCSP

1C: Подпись произвольного текста в 1С

Задача: получить и выполнить подпись произвольного текста.

Решение: воспользуемся стандартным функционалом 1С. Предварительно на сервер необходимо установить в контейнер собственно сам сертификат. Так-же должен соответственно быть установлен крипто про.

&НаСервере
Функция ВыполнитьПодписьНаСервере(СтрокаДляПодписи,ИдентификаторПОдписи)
	answer = Новый Структура("error,result,", Истина, "Не удалось подписать строку");
		
	МенеджерКриптографии = Новый МенеджерКриптографии("Crypto-Pro GOST R 34.10-2012 Cryptographic Service Provider", "", 80);
	Хранилище = МенеджерКриптографии.ПолучитьХранилищеСертификатов(ТипХранилищаСертификатовКриптографии.ПерсональныеСертификаты);
	СертификатыВХранилище = Хранилище.ПолучитьВсе();

	для каждого сертификат из СертификатыВХранилище цикл
		если сертификат.субъект.CN=ИдентификаторПОдписи тогда		
			ИмяВремФайла = ПолучитьИмяВременногоФайла();
		    Текст = Новый ЗаписьТекста(ИмяВремФайла, "CESU-8");
		    Текст.Записать(СтрокаДляПодписи);
		    Текст.Закрыть();					
			Попытка
		        Результат =  МенеджерКриптографии.Подписать(ИмяВремФайла,неопределено,Сертификат);
				answer.error=false;
				answer.result=Результат;
				возврат answer;
			Исключение
				answer.result=ОписаниеОшибки();
		        сообщить(answer.result);
				УдалитьФайлы(ИмяВремФайла);
				возврат answer;
		    КонецПопытки;	
			
	        УдалитьФайлы(ИмяВремФайла);
			
		конецесли;
	конеццикла;	
	
	answer.result="Не найден сертификат для подписи";	
	возврат answer;
	
КонецФункции

&НаКлиенте
Процедура ВыполнитьПодпись(Команда)
	ВыполнитьПодписьНаСервере("SignRTP","!!!");
КонецПроцедуры

Преобразование сертификата для подписи ГИС ЖКХ

Дано: флешка с сертификатом для подписи сообщений для ГИС ЖКХ,

Задача: выдернуть с рутокена контейнер в формате p12 и расчленить его на сертификат+открытый ключ+закрытый ключ. Задачу уже подобную год назад решал, но как оказалось мануал который сам для себя тогда делал немножко не точный. Потому обновлю.

Решение:

  1. Для получения файла с токена необходимо воспользоваться P12FromGostCSP
  2. Сертификат: openssl pkcs12 -in p12.pfx -clcerts -nokeys -out public.crt
  3. Публичный ключ: openssl x509 -in public.crt -out public.pem -outform PEM
  4. Закрытый ключ без пароля: openssl pkcs12 -in p12.pfx -nocerts -out key.pem -nodes

PHP: Использование CURL с сертифкатом

Задача: Некий удаленный ресурс проверяет сертификат пользователя, при попытке получить с него данные. В наличии только стандартные сертификаты выданные LetEncrypt.

Решение:

Сертификаты необходимо сконвертировать. В наличии:

  • sert.crt — сертификат домена в PEM формате
  • sert.key — приватный ключ PEM формате

Конвертируем используя промежуточную конвертацию в формат p12:

openssl pkcs12 -export -in sert.crt -inkey sert.key -out sert.p12
openssl pkcs12 -in sert.p12 -nodes -out result.pem

По итогу получили файл result.pem. Далее его и будем использовать при работе с curl:

$ch = curl_init();
                curl_setopt($ch, CURLOPT_URL, "https://некий ресурс");    
                curl_setopt($ch, CURLOPT_SSLCERT, WUO_ROOT."result.pem" );
                curl_setopt($ch,CURLOPT_SSLCERTTYPE,"PEM");
                curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
                curl_setopt($ch, CURLOPT_RETURNTRANSFER, True);
                curl_setopt($ch, CURLOPT_POST, True);
                curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
                $post=http_build_query($post, '', '&');
                curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
                curl_setopt($ch, CURLOPT_VERBOSE, true);
                $result = curl_exec($ch);
                curl_close($ch);   

Запрос выбора SSL сертификата в компоненте WebView

Задача: при открытии страницы https необходимо позволить пользователю выбрать необходимый сертификат ssl из установленых в хранилище.

Решение: