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

Удостоверяющий Центр выдал нам ключ и сертификат в одном PKCS#12 файле auth.p12
Я исхожу из того, что у нас в наличии есть linux и docker. Можно даже не локально - вполне можно закинуть наш документ куда-нибудь на хостинг и подключиться по SSH. Подробности установки docker и работы с докер-образами оставим за пределами этой заметки. Перейдём сразу к делу:

Прямо из папки, где лежит наш документ на подпись (document.pdf) и PKCS#12 файл (auth.p12) запускаем замечательный docker образ OpenSSL с поддержкой ГОСТ и заходим в контейнер:

sudo docker run --rm -i -t -v `pwd`:`pwd` -w `pwd` rnix/openssl-gost bash

Вытаскиваем из PKCS#12 файла приватный ключ и сохраняем его в pem-формате. Может потребоваться ввести ваш пароль от PKCS#12 файла.

openssl pkcs12 -in auth.p12 -out key.pem -engine gost -nodes -clcerts

Аналогично вытаскиваем из PKCS#12 файла и сертификат.

openssl pkcs12 -in auth.p12 -clcerts -nokeys -out pub.crt

Подписываем документ. Подпись будет отсоединенная, в формате PKCS#7 в отдельном файле (document.pdf.sig)

openssl smime -sign -signer pub.crt -inkey key.pem -engine gost -binary -noattr -outform DER -in document.pdf -out document.pdf.sig

Проверить подпись можно много где, как локально так и на сайте госуслуг, например.
Всё. Можно отправлять контрагенту документ и соответствующий sig файл.

Если вдруг у вас сертификат в формате DER (в Windows часто это файл с расширением .cer), то можно конвертировать такой сертификат в pem-формат:

openssl x509 -inform DER -in pub.cer -out pub.crt

Файлы в примерах команд выше:

auth.p12 - бинарный PFX-файл, содержащий сертификат и закрытый ключ
pub.crt - сертификат (содержащий открытый ключ) в текстовом формате PEM
pub.cer - сертификат (содержащий открытый ключ) в бинарном формате DER
key.pem - закрытый ключ
document.pdf - pdf-документ, который необходимо подписать
document.pdf.sig - файл куда будет сохранена отсоединённая подпись к документу

Источники вдохновения:

Работаем с реестром запрещенных ресурсов
Не ждем, а готовимся к переходу на новые стандарты криптографической защиты информации
Docker-образы с поддержкой ГОСТ-сертификатов в openssl, curl, php, nginx
OpenSSL: простое шифрование с открытым ключом
https://stackoverflow.com/questions/52980370/how-to-convert-p12-to-crt-file
https://www.emaro-ssl.ru/blog/convert-ssl-certificate-formats/
https://qna.habr.com/q/213942
http://rodji.net/blog/2013/12/27/openssl-по-гост-подписывание-шифрование-пр/
https://polikarpoff.ru/all/eksport-ecp-v-formate-pkcs-12/