Openssl pkcs7 sign: примеры (PHP)
openssl_pkcs7_sign(string $input_filename, string $output_filename, OpenSSLCertificate|string $certificate, OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key, array|null $headers, int $flags = PKCS7_DETACHED, ?string $untrusted_certificates_filename = null): boolОсновные сведения о функции
Функция openssl_pkcs7_sign создает цифровую подпись в формате PKCS#7 (S/MIME) для указанного файла. Она применяется для обеспечения целостности и аутентичности электронных документов, сообщений email или любых данных, представленных в виде файла. Типичные сценарии использования включают подпись юридических документов, защищённую почтовую переписку и верификацию источников данных.
input_filename (string) — путь к исходному файлу, который требуется подписать.
output_filename (string) — путь к файлу, в который будет сохранен результат с подписью.
certificate (OpenSSLCertificate|string) — сертификат X.509, используемый для подписи. Может быть путём к файлу, строкой PEM или объектом OpenSSLCertificate.
private_key (OpenSSLAsymmetricKey|OpenSSLCertificate|array|string) — закрытый ключ, соответствующий сертификату. Может быть путём к файлу, строкой PEM, массивом с паролем или объектом ключа.
headers (array|null) — массив заголовков, которые добавляются перед данными в подписанном файле. Часто используется для email-заголовков.
flags (int) — комбинация констант, изменяющих поведение подписи. Основные флаги: PKCS7_DETACHED, PKCS7_BINARY, PKCS7_NOATTR, PKCS7_NOCERTS, PKCS7_NOCHAIN, PKCS7_NOSIGS, PKCS7_TEXT.
untrusted_certificates_filename (string|null) — путь к файлу с дополнительными сертификатами (например, промежуточными), которые включаются в подпись.
Примеры использования
// Конфигурация путей и данных
$inputFile = 'document.txt';
$outputFile = 'document_signed.p7s';
$certificate = 'cert.pem';
$privateKey = 'private.key';
// Создание подписи
$success = openssl_pkcs7_sign(
$inputFile,
$outputFile,
$certificate,
$privateKey,
[],
PKCS7_DETACHED
);
if ($success) {
echo 'Файл подписан.';
} else {
echo 'Ошибка подписи.';
}Файл подписан.
$success = openssl_pkcs7_sign(
'data.pdf',
'data_signed.p7m',
'cert.pem',
['private.key', 'password123'],
['From' => 'sender@example.com'],
PKCS7_NOATTR,
'chain.pem'
);
var_dump($success);bool(true)
Похожие функции в PHP
openssl_sign генерирует цифровую подпись для строки данных, но не создаёт контейнер PKCS#7. Её применяют для низкоуровневой подписи произвольных данных.
openssl_cms_sign — более современная функция для подписи в формате CMS (Cryptographic Message Syntax). Она поддерживает актуальные стандарты и рекомендуется для новых проектов вместо openssl_pkcs7_sign.
openssl_pkcs7_encrypt предназначена для шифрования, а не подписи. Её используют совместно с подписью для комплексной защиты данных.
Типичные ошибки
$result = openssl_pkcs7_sign(
'missing.txt', // файл не существует
'output.p7s',
'cert.pem',
'private.key'
);
var_dump($result);bool(false)
// Передача неправильного пароля для ключа
$result = openssl_pkcs7_sign(
'file.txt',
'output.p7s',
'cert.pem',
['private.key', 'wrong_password'] // неверный пароль
);
var_dump($result);bool(false)
Изменения в версиях PHP
В PHP 8.0 типы параметров certificate и private_key стали строже: вместо ресурсов теперь ожидаются объекты OpenSSLCertificate и OpenSSLAsymmetricKey. Это повышает безопасность и ясность кода.
В PHP 8.1 улучшены сообщения об ошибках, связанных с некорректными аргументами.
Расширенные примеры
Для добавления метки времени требуется внешний сервис (TSA). Пример показывает подготовку данных для TSA.
// Подпись с флагом PKCS7_NOCERTS и последующее добавление метки
$flags = PKCS7_DETACHED | PKCS7_NOCERTS;
$success = openssl_pkcs7_sign(
'invoice.xml',
'invoice_tmp.p7s',
'cert.pem',
'private.key',
[],
$flags
);
if ($success) {
// Здесь обычно отправляется запрос к TSA
echo 'Подпись создана, можно добавить метку времени.';
}// Использование флага PKCS7_BINARY
$success = openssl_pkcs7_sign(
'image.jpg',
'image_signed.p7m',
'cert.pem',
'private.key',
[],
PKCS7_BINARY
);
if ($success) {
echo 'Бинарная подпись создана.';
}// Файл chain.pem содержит несколько сертификатов
$success = openssl_pkcs7_sign(
'report.pdf',
'report_signed.p7s',
'cert.pem',
'private.key',
[
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'attachment'
],
PKCS7_DETACHED,
'chain.pem' // несколько сертификатов
);
var_dump($success);bool(true)
Альтернативы в других языках
Модуль cryptography или M2Crypto предоставляет функции для работы с PKCS#7. Пример с cryptography:
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography import x509
# Загрузка ключа и сертификата
with open('private.key', 'rb') as f:
private_key = load_pem_private_key(f.read(), password=None)
with open('cert.pem', 'rb') as f:
cert = x509.load_pem_x509_certificate(f.read())
# Подпись данных (упрощённый пример)
data = b'data to sign'
signature = private_key.sign(data, padding.PKCS1v15(), hashes.SHA256())Модуль crypto или библиотека pkcs7 могут использоваться для подобных задач.
const crypto = require('crypto');
const fs = require('fs');
// Чтение ключа и сертификата
const privateKey = fs.readFileSync('private.key', 'utf8');
const cert = fs.readFileSync('cert.pem', 'utf8');
// Создание подписи (пример для данных)
const sign = crypto.createSign('SHA256');
sign.update('data to sign');
const signature = sign.sign(privateKey, 'base64');Прямых аналогов в MySQL нет, так как СУБД обычно не предназначены для создания подписей PKCS#7. Для хранения и проверки подписей можно использовать BLOB-поля.