Добавляем поддержку КриптоПРО в PHP
Несколько недель назад помогал одной команде интегрировать приложение на PHP с ГИБДД ЕАИСТО. Основная задача: подписывать сертификатом в формате ГОСТ Р 34.10-2012 и отправлять документы с помощью криптографического провайдера КриптоПро CSP. Использовать неконтейнерное окружение на базе 64-битной версии Linux CentOS 7.x. В качестве транспорта до сервера — SSL/TLS с поддержкой RSA.
В PHP поддержка стандарта CAdES в СКЗИ КриптоПРО реализована через загрузку разделяемой библиотеки phpcades, что не входит в список стандартных и поддерживаемых мейнтейнерами дистрибутивов, а потому её нужно собирать самостоятельно.
Несмотря на распространённость задачи, в русскоязычном сегменте нет той инструкции, что не содержала бы неточности или ошибки при эксплуатации. Эта статья призвана обобщить опыт вендоров и сообщества, исправив ошибки и собрав полезные практики воедино.
Важно отметить, задача не подразумевала поддержку E2E-шифрования SSL/TLS с поддержкой ГОСТ, потому сборку криптографической библиотеки (например, OpenSSL) и HTTP-клиента (скажем, libcurl) намеренно оставляю за скобками.
Подготовка
Перед началом зарегистрируйтесь на сайте КриптоПРО CSP. Установочные пакеты и зависимости по прямым ссылкам доступны только авторизованным пользователям.
Создайте рабочую директорию и загрузите в неё:
- КриптоПро CSP 5.0 для Linux (x86_64).
- КриптоПро CSP 5.0 ЭЦП.
- Заголовочные файлы КриптоПРО CSP 5.0.
- Патч для поддержки PHP 7 и выше.
Сборка расширения
Установите зависимости для сборки расширения PHP.
yum install boost-devel php-devel lsb gcc-c++
Установите КриптоПРО CSP.
cd ~
tar zxf linux-amd64.tgz
cd linux-amd64
./install.sh
Убедитесь, что в ОС установлены необходимые пакеты.
cprocsp-curl-64
cprocsp-pki-cades-64
cprocsp-pki-phpcades-64
lsb-cprocsp-base
lsb-cprocsp-ca-certs
lsb-cprocsp-capilite-64
lsb-cprocsp-devel
lsb-cprocsp-kc1-64
lsb-cprocsp-rdr-64
Установите КриптоПРО ЭЦП CSP.
cd ~
tar xzf cades_linux_amd64.tar.gz
cd cades_linux_amd64
yum -y install cprocsp-pki-2.0.0-amd64-cades.rpm \
cprocsp-pki-2.0.0-amd64-phpcades.rpm \
lsb-cprocsp-devel-5.0.11455-5.noarch.rpm
Установите заголовочные файлы для КриптоПРО.
cd ~
tar xzf csp5devel.tgz
cd csp5devel
yum -y install lsb-cprocsp-devel-5.0.11863-5.noarch.rpm
Подключите репозиторий REMI и установите нужную версию PHP.
yum -y install https://rpms.remirepo.net/enterprise/remi-release-7.rpm
yum-config-manager --enable remi-php72
yum -y install php
Загрузите исходные коды PHP для действующей версии.
cd ~
export PHP_VERSION=$(php -r "echo phpversion();")
wget https://www.php.net/distributions/php-${PHP_VERSION}.tar.gz -O php.tar.gz
tar xzf php.tar.gz
mv php-${PHP_VERSION} php
Сконфигурируйте окружение для сборки расширения.
cd php
./configure
Укажите путь до исходных файлов PHP в манифесте сборки.
vi /opt/cprocsp/src/phpcades/Makefile.unix
# * PHPDIR=/root/php
Примените патч к PHP Cades для поддержки PHP 7.
cp ~/php7_support.patch /opt/cprocsp/src/phpcades/
cd /opt/cprocsp/src/phpcades/
patch -p0 < ./php7_support.patch
Соберите расширение.
cd /opt/cprocsp/src/phpcades
eval `/opt/cprocsp/src/doxygen/CSP/../setenv.sh --64`
make -f Makefile.unix
Скопируйте разделяемую библиотеку в директорию с расширениями и добавьте его в список загрузки.
# php -i | grep extension_dir
cp /opt/cprocsp/src/phpcades/libphpcades.so /usr/lib64/php/modules/phpcades.so
# + extension=phpcades.so
vi /etc/php.ini
Готово. Проверьте, что расширение загружено.
php --re php_CPCSP
Используйте исходный код для проверки.
<?php
if (extension_loaded('php_CPCSP')) {
echo "php_CPCSP is loaded";
} else {
echo "php_CPCSP is unavailable";
}
?>
Установка сертификата в криптоконтейнер
Подключите профиль для расширения PATH
(/etc/profile.d/cryptopro.sh
).
#!/usr/bin/env bash
export PATH=$PATH:/opt/cprocsp/bin/amd64/:/opt/cprocsp/sbin/amd64/
vi /etc/profile.d/cryptopro.sh
chmod +x /etc/profile.d/cryptopro.sh
Инициализируйте PATH
.
source /etc/profile.d/cryptopro.sh
Определите имя криптоконтейнера (например, c0197fed.000
) и установите его в рабочую директорию под именем пользователя веб-сервера (nobody
).
sudo chown -R nobody:nobody /var/opt/cprocsp/key/nobody/c0197fed.000
sudo chmod 700 /var/opt/cprocsp/key/nobody/c0197fed.000
sudo chmod -R 600 /var/opt/cprocsp/key/nobody/c0197fed.000/*.key
Проверьте видимость контейнера.
sudo -E -u nobody csptest -keyset -enum_cont -verifycontext -fqcn
Установите сертификат в криптоконтейнер.
sudo -E -u nobody certmgr -inst -store uMy -file /home/nobody/certificate.cer -cont '\\.\HDIMAGE\c0197fed.000'
Проверьте, что сертификат позволяет подписывать документы.
sudo -E -u nobody certmgr --list
Certmgr 1.1 (c) "Crypto-Pro", 2007-2019.
program for managing certificates, CRLs and stores
=============================================================================
[...]
Signature Algorithm : ГОСТ Р 34.11-2012/34.10-2012 256 бит
PublicKey Algorithm : ГОСТ Р 34.10-2012 (512 bits)
[...]
PrivateKey Link : Yes
Container : HDIMAGE\\c0197fed.000\3D0E
[...]
Extended Key Usage : 1.2.643.2.2.34.25
1.2.643.2.2.34.26
1.2.643.2.2.34.6
1.3.6.1.5.5.7.3.2
1.3.6.1.5.5.7.3.4
=============================================================================
[ErrorCode: 0x00000000]
Готово. Для проверки подписи используйте команду.
sudo -u nobody cryptcp -signf -dn E=signer@example.tld document.pdf
cat document.pdf.sgn