Мы опишем установку сертификата электронной подписи и закрытого ключа для ОС семейства Windows. В процессе настройки нам понадобятся права Администратора (поэтому нам может понадобится сисадмин, если он у вас есть).
Если вы еще не разобрались что такое Электронная подпись, то пожалуйста ознакомьтесь вот с этой инструкцией.
Или если еще не получили электронную подпись
, обратитесь в Удостоверяющий центр, рекомендуем СКБ-Контур.
Хорошо, предположим у вас уже есть электронная подпись (токен или флешка), но OpenSRO сообщает что ваш сертификат не установлен, такая ситуация может возникнуть, если вы решили настроить ваш второй или третий компьютер (разумеется подпись не «прирастает» только к одному компьютеру и ее можно использовать на нескольких компьютерах). Обычно первоначальная настройка осуществляется с помощью техподдержки Удостоверяющего центра, но допустим это не наш случай, итак поехали.
- 1. Убедитесь что КриптоПро CSP 4 установлен на вашем компьютере
- 2. Если у вас токен (Рутокен например)
- 3. Если закрытый ключ в виде файлов
- 4. Установка сертификата из закрытого ключа
- 5. Использование электронной подписи без токена или флешки (установка в реестр)
- Как создать ключевой контейнер
- Как установить сертификат ключа проверки ЭП в контейнер – подготовка
- Создаем пароль для контейнера
- Несколько важных замечаний
- Как скопировать контейнер закрытого ключа
- Наш каталог продукции
- Что такое открытый ключ ЭЦП
- Как экспортировать открытый ключ и сертификат
- Экспорт сертификата через свойства обозревателя
- Экспорт сертификата из КриптоПро CSP
- Что такое закрытый ключ ЭП
- Как экспортировать закрытый ключ
- Что такое закрытый ключ ЭП
- Как экспортировать закрытый ключ
- Файл primary. key
- Файл masks. key
- Файл header. key
- Читаем закрытый ключ и конвертируем
- Сборка утилиты конвертирования ключа
- Компиляция OpenSSL библиотеки
- Компиляция privkey.c
- Формирование файла закрытого ключа private.key
- Пользуемся закрытым ключом private.key для подписывания файла file.txt
- Проверяем подпись
1. Убедитесь что КриптоПро CSP 4
установлен на вашем компьютере
Для этого зайдите в меню
Пуск
КРИПТО-ПРО
КриптоПро CSP
запустите его и убедитесь что версия программы не ниже 4-й.

2. Если у вас токен (Рутокен например)
Прежде чем система сможет с ним работать понадобится установить нужный драйвер.
- Драйверы Рутокен:
https://www.rutoken.ru/support/download/drivers-for-windows/ - Драйверы eToken:
https://www.aladdin-rd.ru/support/downloads/etoken - Драйверы JaCarta:
https://www.aladdin-rd.ru/support/downloads/jacarta
Алгоритм такой:
Скачиваем;
Устанавливаем.
Для токена может понадобиться стандартный (заводской) пин-код, здесь есть стандартные пин-коды носителей
.
3. Если закрытый ключ в виде файлов
Закрытый ключ может быть в виде 6 файлов: header.key
, masks.key
, masks2.key
, name.key
, primary.key
, primary2.key
(Если вы не боитесь командной строки, то съемный носитель можно сэмулировать примерно так: subst x: C:\tmp
появится новый диск (X:), в нем будет содержимое папки C:\tmp, он исчезнет после перезагрузки. Такой способ можно использовать если вы планируете установить ключи в реестр)
Нашли файлы, записали на флешку, переходим к следующему шагу.
4. Установка сертификата из закрытого ключа
Теперь нам нужно получить сертификат, сделать это можно следующим образом:
- Открываем КриптоПро CSP
- Заходим на вкладку Сервис
- Нажимаем кнопку Просмотреть сертификаты в контейнере
, нажимаем Обзор
и здесь (если на предыдущих шагах сделали все правильно) у нас появится наш контейнер. Нажимаем кнопку Далее
, появятся сведения о сертификате и тут нажимаем кнопку Установить
(программа может задать вопрос проставить ли ссылку на закрытый ключ, ответьте «Да») - После этого сертификат будет установлен в хранилище и станет возможным подписание документов (при этом, в момент подписания документа, нужно будет чтобы флешка или токен были вставлены в компьютер)
5. Использование электронной подписи без токена или флешки (установка в реестр)
Если скорость и удобство работы для вас стоит чуть выше чем безопасность, то можно установить ваш закрытый ключ в реестр Windows. Для этого нужно сделать несколько простых действий:
- Выполните подготовку закрытого ключа, описанную в пунктах
или
- Далее открываем КриптоПро CSP
- Заходим на вкладку Сервис
- Нажимаем кнопку Скопировать
- С помощью кнопки Обзор
выбираем наш ключ - Нажимаем кнопку Далее
, потом придумаем какое-нибудь имя, например «Пупкин, ООО Ромашка» и нажимаем кнопку Готово - Появится окно, в котором будет предложено выбрать носитель, выбираем Реестр,
жмем Ок - Система попросит Установить пароль
для контейнера, придумываем пароль, жмем Ок
Чтобы для сертификата проставить ссылку на этот закрытый ключ выполните действия из пункта
.
Важное замечание:
портал OpenSRO не «увидит» сертификат, если вышел срок его действия.
Владелец цифрового автографа (далее – ЭЦП, ЭП) может дистанционно запрашивать у удостоверяющего центра (далее – УЦ) сертификат ключа проверки электронной подписи
(далее – СКПЭП) или его обновление. Внеплановая замена производится только при определенных обстоятельствах: требуется коррекция сведений, использованных для оформления текущего документа (сменился руководитель организации, в связи с переездом был перерегистрирован юридический адрес) или до конца периода актуальности СКПЭП остается меньше двух месяцев.
Чтобы получить маркер временного доступа, пользователю нужно зарегистрировать личный кабинет и, скорее всего, понадобится заполнить электронный бланк заказа услуги. Он обязательно оформляется, если существует необходимость расширения области применения ЭП. Например, для подключения компании заявителя к процессу представления цифровой бухотчетности в ПФР, ФСС или Росстат.
Услугу удаленного создания нового или обновления текущего СКПЭП предлагают Федеральная служба по регулированию алкогольного рынка (ФСРАР), МТС-банк, УЦ Такском и другие организации. В следующих разделах мы расскажем, как с помощью КриптоПро CSP
создать хранилище личного сертификата и скопировать контейнер закрытого ключа на подходящий носитель при использовании удаленных сервисов для запроса СКПЭП.
Подскажем, какой программный продукт КриптоПро из нашего каталога подходит под ваш бизнес.
Оставьте заявку и получите консультацию в течение 5 минут.
Как создать ключевой контейнер
Ключевой контейнер – это «запароленный» каталог в хранилище (реестре) или системной библиотеке «операционки» (далее – ОС) или на защищенном ключевом USB-носителе: токене, смарт-карте. Он считается одним из инструментов защиты криптографических средств генерации и верификации ЭП, лицензий, сертификатов, паролей и другой личной информации.
Криптометод организации и иерархии персональных данных предусматривает обязательное использование защищенного каталога как части комплекса гарантий сохранности и конфиденциальности сведений, необходимых для активации ЭП. Фактически, создавая новую папку для хранения СКПЭП, доступ к которой обеспечивается путем ввода пароля, пользователь формирует новое хранилище.
Помимо выполнения основных функций – генерации и верификации ЭП – КриптоПро CSP «умеет» функционировать как зависимая компонента: приложение можно вызывать из сторонних программ. Например, через веб-интерфейс сайта УЦ, в который заявитель обратился за услугой обновления СКПЭП. КриптоПро CSP бывает необходим и для того, чтобы создать ключевой контейнер и установить в него сертификат ключа проверки ЭЦП, в том числе с обращением к службе сертификации ОС Microsoft (далее – MS) Windows Server.
Испытать работу генератора ключей и ознакомиться с процедурой запроса СКПЭП можно на странице тестового удостоверяющего центра разработчика программного модуля. Ниже мы пошагово опишем этот процесс.
Внимание!
Если вы запрашиваете СКПЭП, который планируете использовать при работе с электронной почтой, указывайте «Область применения ключа». Также учитывайте: вы не получите доступа к криптофункциям для e-mail, если указанный адрес электронной почты не совпадает с зарегистрированным в MS Outlook Express.
Чтобы получить возможность применять выданный по удаленному запросу СКПЭП при обмене данными по протоколу TLS, перейдите к разделу «Область применения ключа» и укажите его тип: «Сертификат аутентификации клиента».
Как установить сертификат ключа проверки ЭП в контейнер – подготовка
Первый шаг – это заполнение электронного формуляра данными, необходимыми для формирования запроса на создание СКПЭП. Указать потребуется Ф. И. О. заявителя и действительный адрес его электронной почты.
Для примера рассмотрим, как организована процедура в одном из самых популярных центров сертификации – УЦ Такском. Пользователям предоставляется возможность удаленно получить совершенно новый или проапдейтить имеющийся СКПЭП:
- по карточке (маркеру) временного доступа – если заявитель запрашивает документ впервые;
- по текущему сертификату – на основании уже имеющихся сведений с целью их обновления или при условии, что до окончания периода действия СКПЭП остается меньше двух месяцев и/или требуется коррекция юридического адреса и/или краткого наименования организации.
При заполнении формуляра на сайте УЦ Такском потребуется указать паспортные данные руководителя или уполномоченного сотрудника организации:
- Ф. И. О.;
- пол;
- дату и место рождения;
- гражданство;
- наименование основного документа (паспорт гражданина РФ), его серию, номер, дату выдачи;
- полное наименование выдавшего его госоргана;
- код подразделения.
После завершение ввода данных пользователю нужно нажать желтую кнопку «Продолжить». Он перенаправляется на страницу настройки уведомлений и указывает номер контактного телефона. Спустя несколько секунд приходит СМС-сообщение, содержащее код подтверждения – его нужно ввести в строку новой формы.
Решим любые проблемы с вашим оборудованием!
Оставьте заявку и получите консультацию в течение 5 минут.
Второй шаг – выбор ключевого носителя:
- Криптомодуль откроет новое интерактивное окно в случае, если пользователь подключил к рабочей машине несколько токенов (или смарт-карт). Учтите: при подсоединении всего одного считывателя, последний выбирается программой автоматически – никаких оповещений программа не отсылает.
- Укажите нужное устройство или выделите параметр «Реестр», если хотите с помощью КриптоПро CSP установить сертификат сразу в контейнер хранилища ОС.
- Нажмите «Ok».
- Приложение запустит «Биологический датчик случайных чисел» (далее – БДСЧ) – работа с опцией будет доступна в новом окошке. Следуйте интерактивным подсказкам. Б ДСЧ генерирует первоначальную последовательность датчика случайных чисел (далее – ДСЧ).
Для успешного завершения процесса нужно нажимать кнопки клавиатуры или перемещать мышку в произвольном порядке.
Мы готовы помочь!
Задайте свой вопрос специалисту в конце статьи. Отвечаем быстро и по существу. К комментариям
Создаем пароль для контейнера
Третий шаг – ввод пин-кода для контейнера, создаваемого средствами КриптоПро CSP
. Сохраните его в надежном месте: если вы его потеряете или забудете, пользоваться СКПЭП станет невозможно. Придется оформлять новый документ.
Примечание.
При желании повысить уровень защиты личной информации вызовите опцию «Подробнее». В КриптоПро CSP откроется форма с перечнем способов охраны доступа к закрытому ключу (далее – ЗК) создаваемого контейнера – вы сможете выбрать одно из следующих действий:
- установить новый pin-код;
- задать мастер-ключ (закодировать текущий ЗК и преобразовать его в новый);
- сегментировать пароль и разместить его по частям на нескольких носителях.
В токенах и смарт-картах реализована функция поддержки аппаратного pin-кода – если вы используете одного из подобных устройств для создания нового контейнера, скорее всего, КриптоПро CSP «попросит» ввести пароль, который задается по умолчанию:
- 1234567890 – для eToken/JaCarta;
- 12345678 – для Рутокен/ESMART.
Чтобы защитить создаваемый каталог, укажите в поле «Новый пароль» определенную комбинацию символов, которая известна только вам. Повторите ее в строке «Подтверждение» и кликните «Ok».
Вы можете пропустить этот шаг и не задавать пин-код.
Несколько важных замечаний
Первое.
При переводе строки в состояние «Установить новый пароль» криптопровайдер защитит доступ к контейнеру паролем, который вы будете вводить с клавиатуры. Если вы установите переключатель на поле «Установить мастер-ключ», приложение закодирует для каталога его текущий ЗК.
Для этого выполните следующие действия:
- Введите название контейнера или выделите его из предложенного программой перечня и нажмите кнопку «Выбрать». На нем будет сохранен новый ЗК в закодированном виде.
- Жмите «Ok».
- Если вы отметите галкой строку «Создать новый контейнер», после совершения этой операции в только что сформированном защищенном каталоге будет сохранен его ЗК в закодированном виде.
Второе.
Воспользовавшись опцией «Разделить ключ на несколько носителей», вы сможете защитить каталог, обеспечив доступ к нему только с нескольких устройств одновременно. Каждое из них станет носителем обособленного контейнера с собственным пин-кодом. Заполните формуляр, указав необходимые данные:
- количество загрузочных носителей, необходимых для доступа к формируемому ЗК ключевого контейнера;
- общее число устройств – между ними будут распределены части ключа.
КриптоПро CSP
запустит процесс формирования новых контейнеров, участвующих в разделении исходного ключа:
- для каждого формируемого каталога открывается окошко выбора ключевого носителя – укажите нужные;
- по окончании упомянутой операции появится окно ДСЧ;
- сгенерировав числовую последовательность, дождитесь формы ввода пин-кодов к ЗК для каждого созданного контейнера.
По очереди введите их все или выберите другой метод защиты доступа к личным данным, щелкнув кнопку «Подробнее».
Как скопировать контейнер закрытого ключа
Используя функции криптомодуля, можно репродуцировать каталог, содержащий личный ЗК, предназначенный для генерации цифровой подписи. Как скопировать контейнер закрытого ключа с помощью КриптоПро CSP
? Пошаговый алгоритм действий будет следующим:
- Запустите криптопровайдер.
- Перейдите ко вкладке «Сервис».
- Жмите «Скопировать».
- В новом окне щелкните кнопку «Обзор».
- Из ниспадающего перечня контейнеров выберите нужный.
- Щелкайте «Ok» –> «Далее».
- Введите название контейнера – в него будет перенесен ваш закрытый ключ. Допускается использование кириллицы и пробелов.
- Щелкайте «Готово».
- Появится новое окошко выбора ключевого носителя. Укажите подключенный к рабочей машине считыватель или выделите параметр «Реестр», если хотите репродуцировать данные в хранилище ОС.
- Криптомодуль предложит установить пароль (для каталога, скопированного в реестр ОС) или пин-код (для защищенной папки, продублированной на считыватель). Вы можете этого не делать: оставьте строку пустой и кликайте «Ok».
После завершения операции криптопровайдер перенаправит вас на вкладку «Сервис».
За 30 минут настроим вашу версию КриптоПро CSP для работы «под ключ»!
Оставьте заявку и получите консультацию.

Стратегический консультант в области оптимизации бизнес-процессов с 2005 года, специализируется на складской логистике и розничной торговле.
Оцените, насколько полезна была информация в статье?
Наш каталог продукции
У нас Вы найдете широкий ассортимент товаров в сегментах
кассового, торгового, весового, банковского и офисного оборудования.
Посмотреть весь каталог
Для формирования контейнера с помощью СКЗИ VipNet CSP, после нажатия кнопки Создать закрытый ключ
, укажите место хранения контейнера закрытого ключа. По умолчанию контейнер сохраняется в скрытую системную папку на локальном диске компьютера:

В окне для ввода пароля контейнера ключа задайте пароль и подтвердите его. Пароль должен содержать в себе не менее 6 символов:

Обязательно запомните либо запишите пароль. Если пароль будет утерян, вы не сможете пользоваться электронной подписью.
Появится окно электронной рулетки. Передвигайте указатель мыши в пределах окна либо нажимайте любые клавиши на клавиатуре. В результате этих действий будет инициализирован генератор случайных чисел:

Для формирования контейнера с помощью СКЗИ КриптоПро CSP, после нажатия кнопки Создать закрытый ключ
, укажите место хранения контейнера закрытого ключа и нажмите кнопку
ОК
:

Для работы в системе электронных торгов контейнер закрытого ключа обязательно должен быть сохранен на защищенный носитель. В случае утраты контейнера закрытого ключа восстановить его невозможно.
Откроется окно биологического датчика случайных чисел. Для создания ключа перемещайте указатель мыши в пределах окна или нажимайте различные клавиши на клавиатуре:

На следующем этапе введите пароль для ограничения доступа к контейнеру. Пароль должен содержать не менее 6 символов, при необходимости можете установить флажок
Сохранить пароль
. Для продолжения работы нажмите кнопку
ОК
:

Обязательно запомните либо запишите пароль. Если пароль будет утерян, вы не сможете пользоваться электронной подписью.
Контейнер ключей электронной подписи состоит из открытого, закрытого ключа и сертификата. Все его составляющие создаются с помощью криптографических алгоритмов. Для работы с квалифицированной электронной подписью (КЭП) нужно использовать оба ключа — каждый из них выполняет свою функцию.
Рассмотрим, как экспортировать закрытый и открытый ключ электронной подписи при помощи Windows или криптопровайдера КриптоПро CSP.
Важно! Ключи, полученные в аккредитованных удостоверяющих центрах, можно хранить на токене или в компьютере. Удостоверяющий центр ФНС записывает контейнеры ключей только на токены и ставит ограничения на их копирование. Ключи, полученные в налоговой, экспортировать на другие носители запрещено.
Что такое открытый ключ ЭЦП
Открытая часть ключевой пары ЭЦП представляется в виде электронного сертификата или бумажного документа
. Сертификат выдаётся только удостоверяющим центром и содержит информацию, которая используется для проверки подписи владельца и шифрования данных.
ЭЦП — это устаревшее понятие. Расшифровывается как электронная цифровая подпись. В настоящее время используется более ёмкое название ЭП, которое расшифровывается как электронная подпись.
Открытый ключ можно использовать для работы с партнёрами, в отличие от закрытого, который хранится в защищённом месте. Контрагенты могут использовать открытый ключ владельца для шифрования данных, которые ему посылают. Это означает, что после отправки этих данных получить доступ к ним сможет только владелец закрытой части ключа.
Сертификат содержит в себе следующие данные:
<img src="https://astral.ru/upload/iblock/442/xnan46lh1h4c2i6syb9jkzif6k7w5p0x/%D0%B8%D0%BD%D1%84%D0%BE%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D0%BA%D0%B0%20_%D0%9A%D0%B0%D0%BA%20%D1%8D%D0%BA%D1%81%D0%BF%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%20%D0%B7%D0%B0%D0%BA%D1%80%D1%8B%D1%82%D1%83%D1%8E%20%D0%B8%20%D0%BE%D1%82%D0%BA%D1%80%D1%8B%D1%82%D1%83%D1%8E%20%D1%87%D0%B0%D1%81%D1%82%D1%8C%20%D0%BA%D0%BB%D1%8E%D1%87%D0%B0%20%D1%8D%D0%BB%D0%B5%D0%BA%D1%82%D1%80%D0%BE%D0%BD%D0%BD%D0%BE%D0%B9%20%D0%BF%D0%BE%D0%B4%D0%BF%D0%B8%D1%81%D0%B8_%20
.png» alt=»
Сертификат»>
Электронный сертификат виден на обычных носителях в виде файла с расширением .cer, а на защищённых картах Рутокен, eToken и JaCarta его можно посмотреть с помощью криптопровайдера или драйвера носителя.
Открытый ключ позволяет проверить электронную подпись под документом, в отличие от закрытого ключа, который нужен для создания электронной подписи. Доступ к закрытому ключу имеет только владелец, а открытый ключ доступен всем участникам электронного взаимодействия. Сертификат ЭП даёт возможность идентифицировать владельца.
Как экспортировать открытый ключ и сертификат
В программном обеспечении компьютера нет отдельного функционала экспорта открытого ключа. Но значение открытого ключа содержатся в сертификате. Поэтому пользователю достаточно экспортировать только сертификат. Делается это через свойства обозревателя либо из криптопровайдера КриптоПро CSP. При этом носитель с ключом должен быть подключён к компьютеру.
Экспортировать открытый ключ электронной подписи можно только вместе с закрытым ключом.
Экспорт сертификата через свойства обозревателя
- В системе Windows перейдите в «Пуск» → «Панель управления» → «Свойства обозревателя (Свойства браузера)».
- Перейдите на вкладку «Содержание» и нажмите на кнопку «Сертификаты».
- В списке выберите нужный сертификат, щёлкнув по его названию, и нажмите кнопку «Экспорт».
- В окне «Мастер экспорта сертификатов» нажмите кнопку «Далее», затем «Нет, не экспортировать закрытый ключ» и снова «Далее».
- В окне «Формат экспортируемого файла» выберите «Файлы X.509 (. CER) в кодировке DER» или «Файлы X.509 (. CER) в кодировке Base-64» и нажмите кнопку «Далее».
- Выберите место сохранения сертификата, нажав кнопку «Обзор», затем нажмите на кнопку «Сохранить» → «Далее» → «Готово».






Экспорт сертификата из КриптоПро CSP
- В системе Windows перейдите в «Пуск» → «Панель управления» → «КриптоПро CSP».
- Перейдите на вкладку «Сервис» и нажмите кнопку «Просмотреть сертификаты в контейнере».
- Нажмите кнопку «Обзор», выберите нужный контейнер и нажмите «Ок» → «Далее».
- В окне «Сертификат для просмотра» нажмите кнопку «Свойства».
- Перейдите на вкладку «Состав» и нажмите кнопку «Копировать в файл».
- В окне «Мастер экспорта сертификатов» нажмите кнопку «Далее», затем «Нет, не экспортировать закрытый ключ» и снова «Далее».
- В окне «Формат экспортируемого файла» выберите «Файлы X.509 (. CER) в кодировке DER» или «Файлы X.509 (. CER) в кодировке Base-64» и нажмите кнопку «Далее».
- Выберите место сохранения сертификата, нажав кнопку «Обзор», затем нажмите на кнопку «Сохранить» → «Далее» → «Готово».







Что такое закрытый ключ ЭП
Закрытый ключ представлен в виде уникального набора символов, которые используются криптографическим алгоритмом для создания электронной подписи в электронном документе.
Владелец электронной подписи использует именно закрытую часть для подписания электронных документов. Любой, кто получает доступ к закрытому ключу электронной подписи, может им воспользоваться. Поэтому его хранят на защищённых носителях: смарт-карте, токене, USB-носителе или дискете.
Хранить закрытый ключ можно на компьютере, однако это небезопасно — воспользоваться им сможет любой, кто имеет доступ к компьютеру. Самым защищённым носителем считается смарт-карта, так как на ней используется двухфакторная аутентификация.
Закрытый ключ хранится в контейнере. В формате КриптоПро контейнер представлен в виде папки, которая содержит несколько файлов с расширением .key. Випнет имеет другой формат, в нём контейнер представлен в виде единственного файла без расширения.
Как экспортировать закрытый ключ
Отдельно, закрытый ключ практически никогда не экспортируется. Копируется сразу ключевая пара — открытый ключ вместе с закрытым.
Выполнять экспорт закрытого и открытого ключа электронной подписи можно из криптопровайдера КриптоПро CSP.
Важно! Если закрытый ключ сделан с использованием другого криптопровайдера, то экспортировать его через КриптоПро не получится.
- В системе Windows перейдите в «Пуск» → «Панель управления» → «КриптоПро CSP».
- Перейдите на вкладку «Сервис» и нажмите на кнопку «Скопировать контейнер».
- В окне «Копирование контейнера закрытого ключа» нажмите на кнопку «Обзор», выберите нужный контейнер и нажмите «Ок» → «Далее».
- Если вы копируете закрытый ключ с защищённого носителя, введите pin-код этого носителя. Также может потребоваться ввести пин-код контейнера ключей, если он установлен.
- Введите название копии закрытого ключа и нажмите «Готово».




Что такое закрытый ключ ЭП
Закрытый ключ представлен в виде уникального набора символов, которые используются криптографическим алгоритмом для создания электронной подписи в электронном документе.
Владелец электронной подписи использует именно закрытую часть для подписания электронных документов. Любой, кто получает доступ к закрытому ключу электронной подписи, может им воспользоваться. Поэтому его хранят на защищённых носителях: смарт-карте, токене, USB-носителе или дискете.
Хранить закрытый ключ можно на компьютере, однако это небезопасно — воспользоваться им сможет любой, кто имеет доступ к компьютеру. Самым защищённым носителем считается смарт-карта, так как на ней используется двухфакторная аутентификация.
Закрытый ключ хранится в контейнере. В формате КриптоПро контейнер представлен в виде папки, которая содержит несколько файлов с расширением .key. Випнет имеет другой формат, в нём контейнер представлен в виде единственного файла без расширения.
Как экспортировать закрытый ключ
Отдельно, закрытый ключ практически никогда не экспортируется. Копируется сразу ключевая пара — открытый ключ вместе с закрытым.
Выполнять экспорт закрытого и открытого ключа электронной подписи можно из криптопровайдера КриптоПро CSP.
Важно! Если закрытый ключ сделан с использованием другого криптопровайдера, то экспортировать его через КриптоПро не получится.
- В системе Windows перейдите в «Пуск» → «Панель управления» → «КриптоПро CSP».
- Перейдите на вкладку «Сервис» и нажмите на кнопку «Скопировать контейнер».
Речь пойдет о файлах primary.key, masks.key и header.key, которые лежат в директории ххххх.000 на флешке. Данные файлы входят в состав криптоконтейнера закрытого ключа электронной подписи криптопровайдера КриптоПро, формат которого нигде не опубликован. Целью данной статьи является чтение контейнера и преобразование закрытого ключа в формат, который может быть прочитан в библиотеке OpenSSL. Долгое время было распространено ошибочное суждение, что достаточно сделать нечто вида (primary_key XOR masks_key) и мы получим закрытый ключ в чистом (raw) виде, однако забегая вперед, можно утверждать, что в КриптоПро было применено более сложное преобразование, в худшем случае состоящее из более чем 2000 (двух тысяч) операций хеширования.
Стоит упомянуть о существовании утилиты P12FromGostCSP
которая позволяет конвертировать ключ в формат P12, доступный для работы с OpenSSL, но утилита имеет следующие существенные недостатки:
- Читает контейнер не напрямую, а через криптопровайдер, поэтому там, где кроме OpenSSL ничего нет, не работает.
- Если в свойствах ключа не отмечено, что ключ «экспортируемый», то конвертировать его невозможно.
- В демо версии не формирует файл с ключом, эта возможность присутствует только в платной версии.
Файл primary. key
Содержит 32 байта ключа в формате Asn1. Это только половина ключа, полный ключ получается при делении этого числа по модулю Q на маску. Поле, хранящее модуль Q в библиотеке OpenSSL имеет название order. Маска лежит в файле masks.key:

Файл masks. key
Содержит 32 байта маски ключа в формате Asn1, зашифрованного на ключе хранения pwd_key. Далее 12 байт «затравочной» информации для генерации ключа хранения pwd_key, если криптоконтейнер защищен паролем, то пароль также участвует в генерации ключа хранения.
Далее контрольная сумма (имитозащита) 4 байта. Контрольной информацией для простоты мы пользоваться не будем, общий контроль будет осуществляться путем генерации открытого ключа и сравнения первых 8 байт полученного ключа с соответствующим полем из файла header.key:

Файл header. key
Из этого файла нам потребуется параметры электронной подписи CryptoProParamSet (подчеркнуто красным).
- GostR3410_2001_CryptoPro_A_ParamSet — 1.2.643.2.2.35.1
- GostR3410_2001_CryptoPro_B_ParamSet — 1.2.643.2.2.35.2
- GostR3410_2001_CryptoPro_C_ParamSet — 1.2.643.2.2.35.3
- GostR3410_2001_CryptoPro_XchA_ParamSet — 1.2.643.2.2.36.0
- GostR3410_2001_CryptoPro_XchB_ParamSet — 1.2.643.2.2.36.1
А также первые 8 байт открытого ключа (подчеркнуто) для контроля правильности чтения закрытого.

Читаем закрытый ключ и конвертируем
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/pem.h>
#include <openssl/cms.h>
#include <openssl/err.h>
#include "gost_lcl.h"
/* Convert little-endian byte array into bignum */
BIGNUM *reverse32bn(char *b, BN_CTX *ctx)
{
BIGNUM *res;
char buf[32];
BUF_reverse(buf, b, 32);
res = BN_bin2bn(buf, 32, BN_CTX_get(ctx));
OPENSSL_cleanse(buf, sizeof(buf));
return res;
}
void xor_material(char *buf36, char *buf5C, char *src)
{
int i;
for(i = 0; i < 32; i++)
{
buf36[i] = src[i] ^ 0x36;
buf5C[i] = src[i] ^ 0x5C;
}
}
int make_pwd_key(char *result_key, char *start12, int start12_len, char *passw)
{
int result;
int i;
char pincode4[1024];
int pin_len;
char current[32];
char material36[32];
char material5C[32];
char hash_result[32];
gost_hash_ctx ctx;
init_gost_hash_ctx(&ctx, &GostR3411_94_CryptoProParamSet);
memset(pincode4, 0, sizeof(pincode4));
pin_len = strlen(passw);
if (pin_len*4 > sizeof(pincode4)) { result = 1; goto err; }
for(i = 0; i < pin_len; i++)
pincode4[i*4] = passw[i];
start_hash(&ctx);
hash_block(&ctx, start12, start12_len);
if (pin_len)
hash_block(&ctx, pincode4, pin_len * 4);
finish_hash(&ctx, hash_result);
memcpy(current, (char*)"DENEFH028.760246785.IUEFHWUIO.EF", 32);
for(i = 0; i < (pin_len?2000:2); i++)
{
xor_material(material36, material5C, current);
start_hash(&ctx);
hash_block(&ctx, material36, 32);
hash_block(&ctx, hash_result, 32);
hash_block(&ctx, material5C, 32);
hash_block(&ctx, hash_result, 32);
finish_hash(&ctx, current);
}
xor_material(material36, material5C, current);
start_hash(&ctx);
hash_block(&ctx, material36, 32);
hash_block(&ctx, start12, start12_len);
hash_block(&ctx, material5C, 32);
if (pin_len)
hash_block(&ctx, pincode4, pin_len * 4);
finish_hash(&ctx, current);
start_hash(&ctx);
hash_block(&ctx, current, 32);
finish_hash(&ctx, result_key);
result = 0; //ok
err:
return result;
}
BIGNUM *decode_primary_key(char *pwd_key, char *primary_key, BN_CTX *bn_ctx)
{
BIGNUM *res;
char buf[32];
gost_ctx ctx;
gost_init(&ctx, gost_cipher_list->sblock);
gost_key(&ctx, pwd_key);
gost_dec(&ctx, primary_key, buf, 4);
res = reverse32bn(buf, bn_ctx);
OPENSSL_cleanse(buf, sizeof(buf));
return res;
}
BIGNUM *remove_mask_and_check_public(char *oid_param_set8, BIGNUM *key_with_mask, BIGNUM *mask, char *public8, BN_CTX *ctx)
{
int result;
EC_KEY *eckey = NULL;
const EC_POINT *pubkey;
const EC_GROUP *group;
BIGNUM *X, *Y, *order, *raw_secret, *mask_inv;
char outbuf[32], public_X[32];
ASN1_OBJECT *obj;
int nid;
order = BN_CTX_get(ctx);
mask_inv = BN_CTX_get(ctx);
raw_secret = BN_CTX_get(ctx);
X = BN_CTX_get(ctx);
Y = BN_CTX_get(ctx);
if (!order || !mask_inv || !raw_secret || !X || !Y) { result = 1; goto err; }
obj = ASN1_OBJECT_create(0, oid_param_set8+1, *oid_param_set8, NULL, NULL);
nid = OBJ_obj2nid(obj);
ASN1_OBJECT_free(obj);
if (!(eckey = EC_KEY_new())) { result = 1; goto err; }
if (!fill_GOST2001_params(eckey, nid)) { result = 1; goto err; }
if (!(group = EC_KEY_get0_group(eckey))) { result = 1; goto err; }
if (!EC_GROUP_get_order(group, order, ctx)) { result = 1; goto err; }
if (!BN_mod_inverse(mask_inv, mask, order, ctx)) { result = 1; goto err; }
if (!BN_mod_mul(raw_secret, key_with_mask, mask_inv, order, ctx)) { result = 1; goto err; }
if (!EC_KEY_set_private_key(eckey, raw_secret)) { result = 1; goto err; }
if (!gost2001_compute_public(eckey)) { result = 1; goto err; }
if (!(pubkey = EC_KEY_get0_public_key(eckey))) { result = 1; goto err; }
if (!EC_POINT_get_affine_coordinates_GFp(group, pubkey, X, Y, ctx)) { result = 1; goto err; }
store_bignum(X, outbuf, sizeof(outbuf));
BUF_reverse(public_X, outbuf, sizeof(outbuf));
if (memcmp(public_X, public8, 8) != 0) { result = 1; goto err; }
result = 0; //ok
err:
if (eckey) EC_KEY_free(eckey);
if (result == 0) return raw_secret;
return NULL;
}
int file_length(char *fname)
{
int len;
FILE *f = fopen(fname, "rb");
if (f == NULL) return -1;
fseek(f, 0, SEEK_END);
len = ftell(f);
fclose(f);
return len;
}
int read_file(char *fname, int start_pos, char *buf, int len)
{
int read_len;
FILE *f = fopen(fname, "rb");
if (f == NULL) return 1;
if (start_pos) fseek(f, start_pos, SEEK_SET);
read_len = fread(buf, 1, len, f);
fclose(f);
if (read_len != len) return 1;
return 0; //ok
}
int get_asn1_len(unsigned char *buf, int *size_hdr)
{
int n, i, res;
int pos = 0;
if ((buf[pos]&0x80) == 0) {
*size_hdr = 1;
return buf[pos];
}
n = buf[pos++]&0x7f;
res = 0;
for(i = 0; i < n; i++) {
res = res*256 + buf[pos++];
}
*size_hdr = n+1;
return res;
}
#define MAX_HEADER 20000
int read_container(char *fpath, int flag2, char *salt12, char *primary_key, char *masks_key, char *public8, char *oid_param_set8)
{
int result;
char primary_path[1024+30];
char masks_path[1024+30];
char header_path[1024+30];
char header_buf[MAX_HEADER];
int header_len;
int i, len, pos, size_hdr;
if (strlen(fpath)>1024) { result = 1; goto err; }
sprintf(header_path, "%s/header.key", fpath);
if (flag2 == 0)
{
sprintf(primary_path, "%s/primary.key", fpath);
sprintf(masks_path, "%s/masks.key", fpath);
}
else
{
sprintf(primary_path, "%s/primary2.key", fpath);
sprintf(masks_path, "%s/masks2.key", fpath);
}
if (read_file(primary_path, 4, primary_key, 32)) { result = 1; goto err; }
if (read_file(masks_path, 4, masks_key, 32)) { result = 1; goto err; }
if (read_file(masks_path, 0x26, salt12, 12)) { result = 1; goto err; }
header_len = file_length(header_path);
if (header_len < 0x42 || header_len > MAX_HEADER) { result = 1; goto err; }
if (read_file(header_path, 0, header_buf, header_len)) { result = 1; goto err; }
//------------- skip certificate ---------------------------
pos = 0;
for(i = 0; i < 2; i++)
{
get_asn1_len(header_buf+pos+1, &size_hdr);
pos += size_hdr+1;
if (pos > header_len-8) { result = 2; goto err; }
}
//------------------ get oid_param_set8 -----------------------
#define PARAM_SET_POS 34
if (memcmp(header_buf+pos+PARAM_SET_POS, "\x6\x7", 2) != 0) { result = 2; goto err; }
memcpy(oid_param_set8, header_buf+pos+PARAM_SET_POS+1, 8);
//------------------ get public8 -----------------------
result = 2; //not found
pos += 52;
for(i = 0; i < 3; i++)
{
len = get_asn1_len(header_buf+pos+1, &size_hdr);
if (len == 8 && memcmp(header_buf+pos, "\x8a\x8", 2) == 0)
{
memcpy(public8,header_buf+pos+2,8);
result = 0; //ok
break;
}
pos += len+size_hdr+1;
if (pos > header_len-8) { result = 2; goto err; }
}
err:
OPENSSL_cleanse(header_buf, sizeof(header_buf));
return result;
}
#define START_OID 0x12
#define START_KEY 0x28
unsigned char asn1_private_key[72] = {
0x30,0x46,2,1,0,0x30,0x1c,6,6,0x2a,0x85,3,2,2,0x13,0x30,0x12,6,7,0x11,
0x11,0x11,0x11,0x11,0x11,0x11,6,7,0x2a,0x85,3,2,2,0x1e,1,4,0x23,2,0x21,0
};
int main(int argc, char **argv)
{
int result;
char *container_path;
char *passw;
char salt12[12];
char primary_key[32];
char masks_key[32];
char public8[8];
char oid_param_set8[8];
BN_CTX *ctx;
BIGNUM *key_with_mask;
BIGNUM *mask;
BIGNUM *raw_key;
char pwd_key[32];
char outbuf[32];
ctx = BN_CTX_new();
if (argc == 2)
{
container_path = argv[1];
passw = "";
}
else
if (argc == 3)
{
container_path = argv[1];
passw = argv[2];
}
else
{
printf("get_private container_path [passw]\n");
result = 1;
goto err;
}
if (read_container(container_path, 0, salt12, primary_key, masks_key, public8, oid_param_set8) != 0 &&
read_container(container_path, 1, salt12, primary_key, masks_key, public8, oid_param_set8) != 0)
{
printf("can not read container from %s\n", container_path);
result = 2;
goto err;
}
make_pwd_key(pwd_key, salt12, 12, passw);
key_with_mask = decode_primary_key(pwd_key, primary_key, ctx);
OPENSSL_cleanse(pwd_key, sizeof(pwd_key));
mask = reverse32bn(masks_key, ctx);
raw_key = remove_mask_and_check_public(oid_param_set8, key_with_mask, mask, public8, ctx);
if (raw_key)
{
BIO *bio;
store_bignum(raw_key, outbuf, sizeof(outbuf));
memcpy(asn1_private_key+START_OID, oid_param_set8, 8);
memcpy(asn1_private_key+START_KEY, outbuf, 32);
//bio = BIO_new_file("private.key", "w");
bio = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT);
PEM_write_bio(bio, "PRIVATE KEY", "", asn1_private_key, sizeof(asn1_private_key));
BIO_free(bio);
OPENSSL_cleanse(outbuf, sizeof(outbuf));
OPENSSL_cleanse(asn1_private_key, sizeof(asn1_private_key));
result = 0; //ok
}
else
{
printf("Error check public key\n");
result = 3;
}
err:
BN_CTX_free(ctx);
OPENSSL_cleanse(salt12, sizeof(salt12));
OPENSSL_cleanse(primary_key, sizeof(primary_key));
OPENSSL_cleanse(masks_key, sizeof(masks_key));
return result;
}
Основную работу выполняют следующие 3 функции:
1. Создаем ключ хранения исходя из 12-ти байтовой «соли» и пароля.
make_pwd_key(pwd_key, salt12, 12, passw);
2. Расшифровываем основной ключ на ключе хранения.
key_with_mask = decode_primary_key(pwd_key, primary_key, ctx);
3. Делим ключ с маской на маску.
raw_key = remove_mask_and_check_public(oid_param_set8, key_with_mask, mask, public8, ctx);
Но так как в библиотеке OpenSSL операция деления по модулю традиционно отсутствует, пользуемся операцией взятия обратного числа и умножением.
if (!BN_mod_inverse(mask_inv, mask, order, ctx)) { result = 1; goto err; }
if (!BN_mod_mul(raw_secret, key_with_mask, mask_inv, order, ctx)) { result = 1; goto err; }
Сборка утилиты конвертирования ключа
Далее сборка исходников описана для Linux версии.
Компиляция OpenSSL библиотеки
После скачивания
и распаковки исходных текстов openssl в целевой директории выполняем команды:
./config
make
Получаем готовую библиотеку libcrypto.a в текущей директории.
Также потребуются заголовочные файлы из директорий engines/ccgost и include.
Компиляция privkey.c
gcc -o privkey -Iengines/ccgost -Iinclude privkey.c libcrypto.a -pthread -ldl
Формирование файла закрытого ключа private.key
./privkey /mnt/usbflash/lp-9a0fe.000
Тестовый закрытый ключ в криптоконтейнере lp-9a0fe.000, сертификат открытого ключа signer.cer и другие файлы для тестирования можно взять отсюда
Получаем результат работы:
-----BEGIN PRIVATE KEY-----
MEYCAQAwHAYGKoUDAgITMBIGByqFAwICJAAGByqFAwICHgEEIwIhAKzsrv/l1Uwk
uzph/LQN9mux0Jz0yaW21kOYEFv0Xyut
-----END PRIVATE KEY-----
Cохраняем в private.key
Пользуемся закрытым ключом private.key для подписывания файла file.txt
openssl cms -sign -inkey private.key -in file.txt -CAfile CA.cer -signer signer.cer -engine gost -out test.sign -outform DER -noattr -binary
Проверяем подпись
openssl cms -verify -content file.txt -in test.sign -CAfile CA.cer -signer signer.cer -engine gost -inform DER -noattr -binary
Все работает просто замечательно!
Спасибо за внимание. Это была моя первая статья на хабре.
