Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin ЭЦП
Содержание
  1. Введение
  2. . Получили ЭЦП, что делать дальше? Как зарегистрироваться на торговой площадке?
  3. . Чтобы проверить, какая операционная система установлена на Вашем компьютере
  4. . Чтобы узнать, какая версия обозревателя Internet Explorer, установлена на Вашем компьютере
  5. . КриптоПро не видит контейнер на флешке. Предлагает выбрать другой носитель.
  6. Как настроить электронную почту.
  7. Как подписать документ.
  8. Срок действия КриптоПро заканчивается.
  9. Почта не видит сертификат.
  10. Где найти открытый ключ подписи ЭЦП?
  11. Flash-накопитель
  12. Выбрать контейнер закрытого ключа (через «обзор» выбрать сертификат на считывателе — флешке/дискете)
  13. Дискета
  14. Как должно работать
  15. Как установить криптопро эцп browser plug-in
  16. Как установить личный сертификат?
  17. Компиляция openssl библиотеки
  18. Компиляция privkey.c
  19. Компьютер не видит сертификат эцп: первые шаги
  20. Криптопро csp ошибка 0x80090010 отказано в доступе
  21. Массовый перенос ключей и сертификатов cryptopro с компьютера на компьютер
  22. Пользуемся закрытым ключом private.key для подписывания файла file.txt
  23. Помогла статья? подписывайся на telegram канал автора
  24. Проверяем подпись
  25. Реестр
  26. Сборка утилиты конвертирования ключа
  27. Файл header.key
  28. Файл masks.key
  29. Файл primary.key
  30. Формирование файла закрытого ключа private.key
  31. Часто задаваемые вопросы по теме статьи (faq)
  32. Читаем закрытый ключ и конвертируем

Введение

Мне постоянно приходится иметь дело с сертификатами, токенами, закрытыми ключами, криптопровайдерами и прочим. Сейчас все завязано на это — банкинг, сдача отчетности в разные гос органы, обращения опять же в эти органы, в том числе и физ лиц. В общем, с этой темой рано или поздно придется познакомиться многим.

  1. Перенести или скопировать контейнер закрытого ключа через стандартную оснастку CryptoPro в панели управления. Это самый простой и быстрый способ, если у вас не много сертификатов и ключей. Если же их несколько десятков, а это не такая уж и редкость, то такой путь вам не подходит.
  2. Скопировать сертификаты и ключи непосредственно через перенос самих исходных файлов и данных, где все это хранится. Объем работы одинаков и для 5 и для 50-ти сертификатов, но требуется больше усилий и знаний.

Я опишу оба этих способа, но подробно остановлюсь именно на втором способе. В некоторых ситуациях он является единственно возможным.

Важное замечание. Я буду переносить контейнеры закрытого ключа, которые хранятся в реестре. Если вы храните их только на токене, то переносить контейнеры вам не надо, только сертификаты.

. Получили ЭЦП, что делать дальше? Как зарегистрироваться на торговой площадке?

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

. Чтобы проверить, какая операционная система установлена на Вашем компьютере

— Зайти в проводнике в Мой компьютер.

— Нажмите правой кнопкой мыши на дисплее и выберите из появившегося меню пункт «Свойства».

— В отобразившемся окне содержаться сведения о Вашей системе.

. Чтобы узнать, какая версия обозревателя Internet Explorer, установлена на Вашем компьютере

— Запустите Internet Explorer.

— Выберите из горизонтального меню в верхней части обозревателя пункт «Справка».

— В появившемся окне содержатся сведения о текущей версии обозревателя.

— Возможен вариант

. КриптоПро не видит контейнер на флешке. Предлагает выбрать другой носитель.

В зависимости от того, какой тип носителя вы используете пути решения разные. Если вы используете смарт-карты типа Рутокен, МсКей, Етокен, то, скорее всего у вас не установлены драйвера для корректной работы с ключом.

Если ваш ключ находится на флешке USB 2.0, то надо смотреть версию ядра КриптоПро. Если вы используете КриптоПро 3.0, то у вас сбился путь. Для того чтобы его настроить необходимо:

При включенном в системный блок носителе Через программу КриптоПро Пуск à Панель управления à КриптоПро àОборудование Настроить считыватели Добавить. В появившемся окне Мастера установки считывателей выбираете в правой части экрана Дисковод (так как в КриптоПро все USB носители определяются как дискеты). В следующем окне выбираете правильное имя флешки, то есть то имя под которым определилась флешка в «Мой компьютер».

Если вы используете КриптоПро 3.6 и контейнер не виден, то значит носитель поврежден. Его следует предоставить в офис для выяснения состояния ключа.

Как настроить электронную почту.

Настройка параметров безопасности Outlook Express проводится по следующей схеме:

1. Выберите пункт меню Сервис/ Tools -> Учетные записи / Accounts и откройте закладку Почта/ Mail.

2. В отображаемом списке учетных записей выберите ту, которую необходимо настроить, и нажмите на кнопку Свойства/ Properties.

3. В отображаемом диалоге выберите закладку Безопасность/ Security, позволяющую пользователю указать свои личные сертификаты, которые будут использоваться при выборе личных ключей пользователя для формирования электронной цифровой подписи и расшифрования входящих сообщений.

5. В отображаемом диалоге выберите закладку Безопасность/ Security:

6. В отображаемом диалоге установите следующие режимы:

a. Включать пользователя при отправке шифрованной почты/ Always encrypt messages when sending encrypted mail . Установка режима включения дает возможность отправителю расшифровывать отправленные им сообщения.

b. Включать цифровое удостоверение при отправке сообщений с подписью/ Include my digital ID when sending singed messages. Установка этого режима автоматически будет добавлять сертификат отправителя ко всем сообщениям. Этот режим позволяет производить обмен сертификатами с использованием подписанного сообщения, а затем использовать полученные сертификаты для последующего шифрования сообщений между адресатами.

c. Отправлять сообщения с непрозрачной подписью/ Encode message before signing. При включенном режиме сообщения все вложения будут объединены в единое вложение с включенной в него цифровой подписью. Если режим выключен, подпись формируется в виде одного отдельного вложения для всех вложений.

d. Автоматически добавлять сертификат отправителя в адресную книгу/ Add senders certificates to my address book. При включенном режиме сертификаты, передаваемые в составе подписанного сообщения, будут автоматически добавляться в адресную книгу.

e. Проверять отмену цифровых подписей/ Check for revoked Digital Ds:

i. только при нахождении в сети/ Only when online. Установка маркера проверки приводит к тому, что каждая операция формирования или проверки электронной цифровой подписи будет сопровождаться проверкой на отзыв сертификата. Для проверки на отзыв используется Cписок Отозванных Сертификатов (CRL), информация о нахождении которого записывается в виде дополнения в сертификате каждого пользователя. По умолчанию данная опция не включена, и «Outlook Express» не отслеживает факта компрометации ключей пользователей.

ii. Никогда/ Never.

Проверка на отзыв не выполняется.

Как подписать документ.

Существует 2 вида отправки документа в подписанном виде.

Первый способ — подписание самого документа и второй — подписание всего письма целиком.

Для создания и отправки подписанного сообщения:

1. Нажмите на кнопку Создать сообщение/ Create Mail или выберите пункт меню Файл/ File — > Создать/ New -> Сообщение/ Mail message.

3. Для отправки сообщения в подписанном виде проверьте состояние кнопки Подписать/ Sign. Она должна быть нажата, и должен быть виден знак подписанного сообщения в правой части экрана.

4. После того, как сообщение подготовлено к отправке, нажмите на кнопку Отправить/ Send:

Второй способ, когда подписывается сам файл. Пакет Microsoft Office позволяет прикреплять цифровые подписи к конкретному документу. Для этого необходимо:

1. В меню Сервис выберите команду Параметры, а затем откройте вкладку Безопасность.

2. Нажмите кнопку Цифровые подписи.

3. Нажмите кнопку Добавить.

4. Выберите нужный сертификат, а затем нажмите кнопку OK.

Для остальных форматов данных необходимо использовать программу КриптоАрм.

Срок действия КриптоПро заканчивается.

При установке не был введен серийный номер продукта согласно приобретенной вами лицензии.

Почта не видит сертификат.

При настройки электронной почты, на стадии подписания документа почта не находит нужный сертификат. Такое случается, когда адрес электронной почты, которая указывается при изготовлении ЭЦП, не совпадает с действующим электронным ящиком.

Где найти открытый ключ подписи ЭЦП?

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

При включенном в системный блок носителе Через программу КриптоПро Пуск à Панель управления à КриптоПро àСервис à Просмотреть сертификаты в контейнере. В появившемся диалоговом окне через обзор выбираете необходимый контейнер à Далее. В окне просмотра данных открытого ключа ЭЦП выбираете свойства à вкладка «Состав» à Копировать в файл и указываете путь сохранения сертификата.

Flash-накопитель

Если в качестве ключевого носителя используется flash-накопитель, необходимо выполнить следующие шаги:

1.
Убедиться, что в что в корне носителя находится папка, содержащая файлы: header, masks, masks2, name, primary, primary2.
Файлы должны иметь расширение.key
, а формат названия папки должен быть следующим: xxxxxx.000.

Если каких-либо файлов не хватает или их формат неверен, то, возможно, контейнер закрытого ключа был поврежден или удален . Также необходимо проверить, не содержится ли данная папка с шестью файлами на других носителях.

2.
Убедиться, что в КриптоПро CSP настроен считыватель Дисковод X
(для КриптоПро CSP 3.6 — Все съемные диски
), где X
— буква диска. Для этого:

  • Выбрать меню Пуск / Панель управления / КриптоПро CSP
    ;
  • Перейти на вкладку Оборудование
    и нажать на кнопку Настроить считыватели
    .

Если считыватель отсутствует, его необходимо добавить (см. Как настроить считыватели в КриптоПро CSP ?).

3.
В окне Выбор ключевого контейнера
установить переключатель Уникальные имена
.

4.
Удалить запомненные пароли. Для этого:

Рис. 3. Окно «Удалить запомненные пароли»

5.
Сделать копию ключевого контейнера и использовать ее для работы (см. Как скопировать контейнер с сертификатом на другой носитель ?).

6.
Если на рабочем месте установлено КриптоПро CSP версии2.0
или 3.0
, а в списке ключевых носителей присутствует Дисковод А (B), то его необходимо удалить. Для этого:

  • Выбрать меню Пуск / Панель управления / КриптоПро CSP
    ;
  • Перейти на вкладку Оборудование
    и нажать на кнопку Настроить считыватели
    ;
  • Выбрать считыватель Дисковод А
    или Дисковод B
    и нажать на кнопку Удалить
    .

После удаления данного считывателя работа с дискетой будет невозможна.

Выбрать контейнер закрытого ключа (через «обзор» выбрать сертификат на считывателе — флешке/дискете)

Если когда-то были неправильно установлены предыдущие ключи и новый носитель не устанавливается, то нужно очистить реестр (Windows). Для этого в панели CSP есть кнопка «Удалить запомненные пароли».

Если в событиях приложений ошибок не было, а в системе евент-логи их показали, необходимо проверить файлы Sfc/scannow, а после перерегистрировать компоненты MSIExec/unregister, потом — MSIExec/regserver.

Дискета

Если в качестве ключевого контейнера используется дискета, необходимо выполнить следующие шаги:

1.
Убедиться, что в корне дискеты находится папка, содержащая файлы: header, masks, masks2, name, primary, primary2
. Файлы должны иметь расширение.key
xxxxxx.000
.

контейнер закрытого ключа был поврежден или удален

2.
Дисковод X
(для КриптоПро CSP 3.6 — Все съемные диски), где X
— буква диска. Для этого:

  • Выбрать меню ;
  • Перейти на вкладку Оборудование
    и нажать на кнопку Настроить считыватели
    .

?).

3.
В окне Выбор ключевого контейнера
установить переключатель Уникальные имена
(см. рис. 1).

Рис. 1. Выбор ключевого контейнера

  • Выбрать меню Пуск / Панель управления / КриптоПро CSP
    ;
  • Перейти на вкладку Сервис
    и нажать на кнопку Удалить запомненные пароли
    ;
  • Отметить пункт Пользователя
    и нажать на кнопку ОК
    (см. рис. 2).

Рис. 2. Окно «Удалить запомненные пароли»

5.
Как скопировать контейнер с сертификатом на другой носитель?).

Как должно работать

Почему не видит ЭЦП компьютер? Вроде и ключ в виде флешки есть (тот же RuToken), и утилита «Крипто-Про» установлена, а проверка ЭП не выполняется. Основная причина — ПК изначально не видит флешку ЭЦП. Это возникает обычно, потому что ключ пытаются запустить на устройстве с неподдерживаемой ОС.

Когда установка криптопровайдера выполнена на поддерживаемом аппарате, по инструкции, но всё равно компьютер не видит ЭЦП, проблема может быть и в самом ключе. Чтобы разобраться, свяжитесь с поддержкой. Там у вас запросят скриншоты:

  • версии/сборки CSP (вкладка «Общие»);
  • ошибок при подключении контейнера ЭЦП.

Кроме того, укажите специалистам, где получали ЭЦП, на каком носителе у вас установлен контейнер (рутокен, етокен, флешка или реестр) и какая используется ОС (разрядность, сборка).

Как установить криптопро эцп browser plug-in

Плагин используется при создании и верификации электронной подписи, при работе на веб-страницах, когда используется ПО КриптоПро. Легко встраиваемый ЭЦП Browser plug-in поддерживает возможность работать с любым из браузеров, которые поддерживает сценарии JavaScript. Подпись может создаваться для разных типов данных: веб-страницы, текстовые сообщения, электронные документы. Если вам необходимо установить КриптоПро ЭЦП Browser plug-in, воспользуйтесь рекомендациями, приведенными ниже.

Для того чтобы установить КриптоПро ЭЦП Browser plug-in потребуется один из современных браузеров, который должен быть установлен на компьютере. Необходимо найти установочный файл и запустить его. Следуя указания Мастера Установки выполнить все этапы установки. После этого необходимо будет перезайти в веб-браузер. При новом запуске браузера должна появиться информация, что плагин загружен. Если требуется установить плагин для UNIX-платформ, обязательно потребуется установка пакета cprocsp-rdr-gui-gtk.

Как установить личный сертификат?

1. Откройте меню Пуск — Панель управления — КриптоПро CSP.

2. В окне программы КриптоПро CSP перейдите на вкладку Сервис и нажмите кнопку Просмотреть сертификаты в контейнере:

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

3. В следующем окне нажмите кнопку Обзор, чтобы выбрать контейнер для просмотра (в нашем примере контейнер находится на смарт-карте JaCarta):

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

4. После выбора контейнера нажмите кнопку Ок, затем Далее.

* Если после нажатия на кнопку Далее Вы видите такое сообщение:

«В контейнере закрытого ключа отсутствует открытый ключ шифрования», следует установить сертификат по рекомендациям, описанным в разделе Вариант 2.

5. В окне Сертификат для просмотра нажмите кнопку Установить:

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

6. Если откроется сообщение «Этот сертификат уже присутствует в хранилище сертификатов. Заменить существующий сертификат новым, с проставленной ссылкой на закрытый ключ?», нажмите Да:

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

7. Дождитесь сообщения об успешной установке:

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

8. Сертификат установлен. Можно закрыть все открытые окна КриптоПро.

Вариант 2. Установка через меню «Установить личный сертификат».

Для установки сертификата этим способом Вам понадобится файл сертификата (файл с расширением.cer). Он может находиться, например, на съемном носителе или на жёстком диске компьютера (если Вы делали копию сертификата или Вам присылали его по электронной почте).

В случае, если файл сертификата отсутствует, напишите письмо с описанием проблемы в техническую поддержку по адресу pu@skbkontur.ru.

1. Откройте меню Пуск — Панель управления — КриптоПро CSP.

2. В окне программы КриптоПро CSP перейдите на вкладку Сервис и нажмите кнопку Установить личный сертификат:
Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

3. В следующем окне нажмите кнопку Обзор, чтобы выбрать файл сертификата:

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

4. Укажите путь к файлу сертификата и нажмите кнопку Открыть (в нашем примере файл сертификата находится на Рабочем столе):

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

5. В следующем окне нажмите кнопку Далее; в окне Сертификат для установки нажмите Далее.

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

6. Поставьте галку в окне Найти контейнер автоматически (в нашем примере контейнер находится на смарт-карте JaCarta) и нажмите Далее:
Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

7. В следующем окне отметьте пункт Установить сертификат (цепочку сертификатов) в контейнер и нажмите Далее:

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

8. В окне Завершение мастера установки личного сертификата нажмите Готово:

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin
9. Если КриптоПро CSP запрашивает pin-код от контейнера, введите нужный код или попробуйте стандартные pin-коды носителей:

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

10. Если откроется сообщение «Этот сертификат уже присутствует в хранилище сертификатов. Заменить существующий сертификат новым, с проставленной ссылкой на закрытый ключ?», нажмите Да:

Правильная установка ключа в КриптоПро и установка плагина КриптоПро ЭЦП Browser plug-in | Softmagazin

11. Сертификат установлен. Можно закрыть все открытые окна КриптоПро.

Компиляция openssl библиотеки

После

и распаковки исходных текстов openssl в целевой директории выполняем команды:

./config
make


Получаем готовую библиотеку libcrypto.a в текущей директории.

Также потребуются заголовочные файлы из директорий engines/ccgost и include.

Компиляция privkey.c

gcc -o privkey -Iengines/ccgost -Iinclude privkey.c libcrypto.a -pthread -ldl

Компьютер не видит сертификат эцп: первые шаги

Если компьютер не видит сертификат электронной подписи, то в операционной системе Windows нужно пройти по адресу:

Пуск — Панель управления — КриптоПРО CSP — Сервис — Протестировать — По сертификату.

Так можно понять, установлен ли сертификат в Личное хранилище пользователя с привязкой к RuToken-у.

Криптопро csp ошибка 0x80090010 отказано в доступе

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

Ошибка обращения к контейнеру закрытого ключа. Ошибка 0x80090010: Отказано в доступе. Связано это с тем, что у текущего пользователя, под которым вы хотите получить доступ к контейнеру, нет полных прав на ветку реестра с хранящимися ключами. Исправить это просто. Переходите в редактор реестра и выставляйте полные права к ветке Keys для текущего пользователя.

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

Массовый перенос ключей и сертификатов cryptopro с компьютера на компьютер

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

Пользуемся закрытым ключом 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

Помогла статья? подписывайся на telegram канал автора

Анонсы всех статей, плюс много другой полезной и интересной информации, которая не попадает на сайт.

Проверяем подпись

openssl cms -verify -content file.txt -in test.sign -CAfile CA.cer -signer signer.cer -engine gost -inform DER -noattr -binary

Все работает просто замечательно!

Спасибо за внимание. Это была моя первая статья на хабре.

Реестр

Если в качестве ключевого носителя используется считыватель Реестр, необходимо выполнить следующие шаги:

1.
Убедиться, что в КриптоПро CSP настроен считыватель Реестр
. Для этого:

  • Выбрать меню Пуск / Панель управления / КриптоПро CSP
    ;
  • Перейти на вкладку Оборудование
    и нажать на кнопку Настроить считыватели
    .

Если считыватель отсутствует, его необходимо добавить (см. Как настроить считыватели в КриптоПро CSP ?).

2.
В окне Выбор ключевого контейнера
установить переключатель Уникальные имена
.

3.
Удалить запомненные пароли. Для этого:

  • Выбрать меню Пуск / Панель управления / КриптоПро CSP
    ;
  • Перейти на вкладку Серви
    с и нажать на кнопку Удалить запомненные пароли
    ;
  • Отметить пункт Пользователя
    и нажать на кнопку ОК
    (см. рис. 5).

Рис. 5. Окно «Удалить запомненные пароли»

Трудности валидации на сайте «РТС-Тендер» возникают из-за того, что ЭЦП browser Plug-In не видит ключ RuToken или только сертификат на подпись. Узнать, почему ПК не видит ключ электронной подписи, помогут инструкция от поставщика специализированного ПО, тематический форум на сайте ФНС или ресурсах, посвящённых ЭЦП, а также специалисты из службы технической поддержки производителя крипто-ПО.

Сборка утилиты конвертирования ключа

Далее сборка исходников описана для Linux версии.

Файл header.key

Из этого файла нам потребуется параметры электронной подписи CryptoProParamSet (подчеркнуто красным).


А также первые 8 байт открытого ключа (подчеркнуто) для контроля правильности чтения закрытого.

Файл masks.key

Содержит 32 байта маски ключа в формате Asn1, зашифрованного на ключе хранения pwd_key. Далее 12 байт «затравочной» информации для генерации ключа хранения pwd_key, если криптоконтейнер защищен паролем, то пароль также участвует в генерации ключа хранения.

Далее контрольная сумма (имитозащита) 4 байта. Контрольной информацией для простоты мы пользоваться не будем, общий контроль будет осуществляться путем генерации открытого ключа и сравнения первых 8 байт полученного ключа с соответствующим полем из файла header.key:

Файл primary.key


Содержит 32 байта ключа в формате Asn1. Это только половина ключа, полный ключ получается при делении этого числа по модулю Q на маску. Поле, хранящее модуль Q в библиотеке OpenSSL имеет название order. Маска лежит в файле masks.key:

Формирование файла закрытого ключа 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

Часто задаваемые вопросы по теме статьи (faq)

Читаем закрытый ключ и конвертируем

Файл privkey.c
#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, "x6x7", 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, "x8ax8", 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 %sn", 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 keyn");
		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;
}

Оцените статью
ЭЦП64
Добавить комментарий