Openssl pkcs7 decrypt: примеры (PHP)
openssl_pkcs7_decrypt(string $input_filename, string $output_filename, OpenSSLCertificate|string $certificate, OpenSSLAsymmetricKey|OpenSSLCertificate|array|string|null $private_key = null): boolФункция openssl_pkcs7_decrypt
Функция openssl_pkcs7_decrypt() предназначена для расшифровки сообщения, которое было зашифровано по стандарту S/MIME (PKCS#7). Она применяется в задачах обработки защищенной электронной почты, расшифровки данных, подписанных цифровыми сертификатами, и в системах, где требуется работа с криптографическими контейнерами формата PKCS7.
Функция принимает четыре аргумента:
- $input_filename (string) – путь к файлу, содержащему зашифрованное сообщение в формате PKCS7.
- $output_filename (string) – путь к файлу, в который будет записан результат расшифровки.
- $certificate (mixed) – сертификат X.509 (может быть строкой с данными или путем к файлу), соответствующий закрытому ключу, который использовался для шифрования.
- $private_key (mixed) – закрытый ключ, соответствующий сертификату. Может быть строкой, ресурсом или массивом, содержащим ключ и пароль.
В версиях PHP до 8.0 функция имела пятый необязательный параметр $encoding, который указывал кодировку входных данных (например, OPENSSL_ENCODING_SMIME, OPENSSL_ENCODING_DER, OPENSSL_ENCODING_PEM). Начиная с PHP 8.0.0, этот параметр удален, а функция автоматически определяет кодировку.
Примеры использования
<?php
// Пути к файлам
$encryptedFile = 'encrypted.p7m';
$decryptedFile = 'decrypted.txt';
$certificate = 'cert.pem';
$privateKey = 'private.pem';
// Расшифровка
$result = openssl_pkcs7_decrypt($encryptedFile, $decryptedFile, $certificate, $privateKey);
if ($result) {
echo 'Файл успешно расшифрован.';
} else {
echo 'Ошибка при расшифровке.';
}
?>Файл успешно расшифрован.
<?php
$encryptedData = file_get_contents('encrypted.p7m');
$tempInput = tempnam(sys_get_temp_dir(), 'enc');
file_put_contents($tempInput, $encryptedData);
$cert = '-----BEGIN CERTIFICATE-----...';
$key = '-----BEGIN PRIVATE KEY-----...';
$result = openssl_pkcs7_decrypt($tempInput, 'output.txt', $cert, $key);
if ($result) {
echo 'Успешно';
}
unlink($tempInput);
?>Успешно
Похожие функции в PHP
Функция для шифрования данных в формат PKCS7. Она является парной к openssl_pkcs7_decrypt и используется на этапе подготовки зашифрованных сообщений.
Эти функции предназначены для создания и проверки цифровых подписей в формате PKCS7. Их используют в случаях, когда требуется обеспечить целостность и аутентификацию данных, а не конфиденциальность.
Функция для расшифровки данных, зашифрованных открытым ключом. Она работает с сырыми данными, а не с контейнерами PKCS7, и подходит для простых сценариев шифрования небольших блоков данных.
Выбор функции зависит от формата данных. Для работы с S/MIME сообщениями и готовыми PKCS7 контейнерами используют openssl_pkcs7_decrypt, а для низкоуровневых операций – openssl_private_decrypt.
Типичные ошибки
<?php
$result = openssl_pkcs7_decrypt('nonexistent.p7m', 'out.txt', 'cert.pem', 'key.pem');
if (!$result) {
echo 'Ошибка: не удается открыть файл для чтения';
}
?>Ошибка: не удается открыть файл для чтения
<?php
// Использование ключа, не соответствующего сертификату
$result = openssl_pkcs7_decrypt('encrypted.p7m', 'out.txt', 'correct_cert.pem', 'wrong_key.pem');
var_dump($result); // false
?>bool(false)
<?php
// Передача обычного текстового файла вместо PKCS7
file_put_contents('plain.txt', 'Not encrypted data');
$result = openssl_pkcs7_decrypt('plain.txt', 'out.txt', 'cert.pem', 'key.pem');
var_dump($result);
?>bool(false)
Для диагностики ошибок можно использовать функцию openssl_error_string() для получения подробного сообщения от библиотеки OpenSSL.
Изменения в версиях PHP
Удален параметр $encoding. Функция теперь автоматически определяет кодировку входных данных. Это изменение упрощает использование функции, но требует обновления кода, который явно передавал этот параметр в более ранних версиях PHP.
В PHP 7.2 была улучшена обработка ошибок, связанных с некорректными сертификатами. Начиная с PHP 5.0, функция стабильно присутствует в расширении OpenSSL.
Расширенные примеры
<?php
// Закрытый ключ защищен паролем
$privateKey = ['file://private.pem', 'my_password'];
$result = openssl_pkcs7_decrypt('encrypted.p7m', 'decrypted.txt', 'cert.pem', $privateKey);
var_dump($result);
?>bool(true)
<?php
// Если PKCS7 контейнер содержит вложенные структуры
$tempDir = sys_get_temp_dir();
$encryptedFile = 'nested.p7m';
$outputFile = $tempDir . '/decrypted_part.txt';
if (openssl_pkcs7_decrypt($encryptedFile, $outputFile, 'cert.pem', 'key.pem')) {
$content = file_get_contents($outputFile);
// Проверка, является ли результат новым PKCS7 контейнером
if (strpos($content, '-----BEGIN PKCS7-----') !== false) {
// Повторная расшифровка
$secondStage = $tempDir . '/final.txt';
$tempInput = $tempDir . '/intermediate.p7m';
file_put_contents($tempInput, $content);
openssl_pkcs7_decrypt($tempInput, $secondStage, 'cert.pem', 'key.pem');
}
}
?>// Результат зависит от структуры исходного файла
<?php
// Использование временного файла для получения данных
$tempOutput = tempnam(sys_get_temp_dir(), 'dec');
if (openssl_pkcs7_decrypt('message.p7m', $tempOutput, $cert, $key)) {
$decryptedContent = file_get_contents($tempOutput);
echo $decryptedContent;
}
unlink($tempOutput);
?>Содержимое расшифрованного сообщения...
<?php
// Через php://memory
$encrypted = file_get_contents('data.p7m');
file_put_contents('php://memory', $encrypted);
// Требуется использование временного файла, так как функция ожидает путь к файлу
// Прямая работа с памятью не поддерживается функцией.
?>// Этот подход демонстрирует ограничение функции
Альтернативы в других языках
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.primitives import serialization
from cryptography import x509
import base64
# Загрузка ключа и сертификата
with open('private.pem', '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())
# В Python для PKCS7 часто используют внешние библиотеки, например, pyOpenSSL или asn1crypto
# Пример с pyOpenSSL:
# from OpenSSL.crypto import FILETYPE_PEM, load_pkcs7_data
# ...
print('Аналогичные операции требуют дополнительных библиотек')Аналогичные операции требуют дополнительных библиотек
const fs = require('fs');
const forge = require('node-forge');
// Чтение данных
const p7msg = fs.readFileSync('encrypted.p7m', 'binary');
const p7 = forge.pkcs7.messageFromPem(p7msg);
// Загрузка сертификата и ключа (упрощенный пример)
// p7.decrypt(...);
console.log('В JS требуется ручной разбор структуры PKCS7 или использование специфичных библиотек.');В JS требуется ручной разбор структуры PKCS7 или использование специфичных библиотек.
В PHP функция openssl_pkcs7_decrypt является встроенной и предоставляет простой интерфейс для расшифровки PKCS7. В Python и JavaScript часто требуется устанавливать дополнительные библиотеки и вручную работать с форматом контейнера. Кроме того, в этих языках может потребоваться больше шагов для извлечения данных из S/MIME сообщений.