Openssl x509 free: примеры (PHP)
openssl_x509_free(OpenSSLCertificate $certificate): voidОсновы функции openssl_x509_free
Функция openssl_x509_free в PHP предназначена для освобождения памяти, занятой ресурсом сертификата X.509. Эта функция освобождает внутренние структуры данных, связанные с сертификатом, что особенно важно в сценариях обработки большого количества сертификатов или при длительном выполнении скриптов.
Использование функции актуально при работе с ресурсами сертификатов в циклах, обработке массовых запросов или в длительных фоновых процессах. Она помогает предотвратить утечки памяти, связанные с сертификатами X.509.
Функция принимает один обязательный параметр:
- x509 - ресурс сертификата X.509, полученный с помощью функций
openssl_x509_read(),openssl_csr_sign()или других функций, возвращающих ресурс сертификата.
После вызова функции переданный ресурс становится недействительным и не может использоваться для дальнейших операций.
Примеры использования openssl_x509_free
<?php
// Создание ресурса сертификата
$certData = file_get_contents('certificate.crt');
$cert = openssl_x509_read($certData);
// Использование сертификата
$subject = openssl_x509_parse($cert);
echo "Субъект: " . $subject['name'] . "\n";
// Освобождение ресурса
openssl_x509_free($cert);
// Попытка использовать освобожденный ресурс вызовет ошибку
// $issuer = openssl_x509_parse($cert); // Ошибка!
?>Субъект: /C=RU/ST=Moscow/L=Moscow/O=Example Company/CN=example.com
<?php
$certFiles = ['cert1.crt', 'cert2.crt', 'cert3.crt'];
foreach ($certFiles as $file) {
if (file_exists($file)) {
$certData = file_get_contents($file);
$cert = openssl_x509_read($certData);
if ($cert !== false) {
$info = openssl_x509_parse($cert);
echo "Обработан сертификат: " . $info['name'] . "\n";
// Важно освободить ресурс после использования
openssl_x509_free($cert);
}
}
}
?>Обработан сертификат: /C=RU/O=Company 1/CN=site1.ru Обработан сертификат: /C=RU/O=Company 2/CN=site2.ru Обработан сертификат: /C=US/O=Company 3/CN=site3.com
Альтернативные функции в PHP
В PHP нет прямой замены функции openssl_x509_free, но существуют альтернативные подходы к управлению ресурсами сертификатов:
В современных версиях PHP ресурсы автоматически освобождаются при завершении работы скрипта. Однако явное освобождение с помощью openssl_x509_free рекомендуется в долгоживущих процессах.
Начиная с PHP 8.0, многие функции OpenSSL возвращают объекты вместо ресурсов. Объекты автоматически управляются сборщиком мусора:
<?php
// В PHP 8.0+ сертификат возвращается как объект OpenSSLCertificate
$cert = openssl_x509_read($certData);
// Не нужно вызывать openssl_x509_free() для объектов
// Память освободится автоматически при уничтожении объекта
?>Для объектов OpenSSLCertificate в PHP 8.0+ можно использовать unset() для явного удаления ссылки на объект, что ускоряет освобождение памяти:
<?php
$cert = openssl_x509_read($certData);
// Работа с сертификатом
unset($cert); // Удаление ссылки на объект
?>Альтернативы в других языках программирования
В Python для работы с сертификатами X.509 используется библиотека cryptography или OpenSSL через ctypes. Управление памятью происходит автоматически:
from cryptography import x509
from cryptography.hazmat.backends import default_backend
# Загрузка сертификата
with open('certificate.crt', 'rb') as f:
cert_data = f.read()
cert = x509.load_pem_x509_certificate(cert_data, default_backend())
print(f"Субъект: {cert.subject}")
# Память освобождается автоматически при выходе из области видимостиСубъект: <Name(C=RU,ST=Moscow,O=Example Company,CN=example.com)>
В Node.js для работы с сертификатами используется модуль crypto. Управление памятью осуществляется сборщиком мусора V8:
const fs = require('fs');
const crypto = require('crypto');
// Чтение сертификата
const certPem = fs.readFileSync('certificate.crt', 'utf8');
const cert = new crypto.X509Certificate(certPem);
console.log(`Субъект: ${cert.subject}`);
// Объект автоматически удаляется сборщиком мусораСубъект: C=RU, ST=Moscow, O=Example Company, CN=example.com
Openssl x509 free в MySQL
В MySQL функции для работы с сертификатами X.509 встроены в систему аутентификации и SSL/TLS соединений. Управление памятью осуществляется внутри СУБД:
-- Создание пользователя с X.509 аутентификацией
CREATE USER 'app_user'@'localhost'
REQUIRE SUBJECT '/C=RU/ST=Moscow/O=Example Company/CN=app.example.com'
AND ISSUER '/C=US/O=Let\'s Encrypt/CN=R3';Типичные ошибки при использовании
<?php
$cert = openssl_x509_read($certData);
openssl_x509_free($cert);
// Ошибка: ресурс уже освобожден
$details = openssl_x509_parse($cert);
?>Warning: openssl_x509_parse(): supplied resource is not a valid OpenSSL X.509 resource
<?php
$cert = 'not a resource';
// Ошибка: ожидается ресурс
openssl_x509_free($cert);
?>Warning: openssl_x509_free(): supplied argument is not a valid OpenSSL X.509 resource
<?php
$cert = openssl_x509_read($certData);
openssl_x509_free($cert);
// Вторая попытка освобождения того же ресурса
openssl_x509_free($cert); // Ошибка
?>Warning: openssl_x509_free(): supplied argument is not a valid OpenSSL X.509 resource
<?php
// CSR и приватный ключ
$csr = openssl_csr_new($dn, $privkey);
$cert = openssl_csr_sign($csr, null, $privkey, 365);
// Правильное использование
openssl_x509_free($cert);
?>Изменения в последних версиях PHP
В PHP 8.0.0 произошли значительные изменения в работе с ресурсами OpenSSL. Вместо ресурсов теперь используются объекты:
- Функции OpenSSL теперь возвращают объекты
OpenSSLCertificate,OpenSSLCertificateSigningRequestиOpenSSLAsymmetricKeyвместо ресурсов - Для объектов не требуется явный вызов
openssl_x509_free()- управление памятью осуществляется автоматически - Функция
openssl_x509_free()продолжает работать для обратной совместимости, но вызывает предупреждение при использовании с объектами
<?php
// В PHP 8.0+
$cert = openssl_x509_read($certData);
var_dump($cert); // object(OpenSSLCertificate)#1
// Вызов openssl_x509_free() необязателен
// но возможен для обратной совместимости
?>object(OpenSSLCertificate)#1 (0) {
}В PHP 8.2.0 улучшена обработка объектов OpenSSL и добавлены дополнительные методы валидации. Функция openssl_x509_free() формально объявлена устаревшей для использования с объектами, но продолжает функционировать.
Расширенные примеры использования
<?php
function processCertificateChain($chainPem) {
$certs = [];
$currentPos = 0;
// Разделение цепочки на отдельные сертификаты
while (($certPos = strpos($chainPem, '-----BEGIN CERTIFICATE-----', $currentPos)) !== false) {
$endPos = strpos($chainPem, '-----END CERTIFICATE-----', $certPos);
if ($endPos === false) break;
$endPos += 25; // Длина '-----END CERTIFICATE-----'
$singleCert = substr($chainPem, $certPos, $endPos - $certPos);
$certResource = openssl_x509_read($singleCert);
if ($certResource !== false) {
$certs[] = $certResource;
}
$currentPos = $endPos;
}
// Обработка каждого сертификата в цепочке
foreach ($certs as $index => $cert) {
$parsed = openssl_x509_parse($cert);
echo "Сертификат #" . ($index + 1) . ": " . $parsed['name'] . "\n";
echo "Действителен до: " . date('Y-m-d', $parsed['validTo_time_t']) . "\n\n";
// Освобождение ресурса после обработки
openssl_x509_free($cert);
}
return count($certs);
}
$chain = file_get_contents('chain.pem');
$count = processCertificateChain($chain);
echo "Обработано сертификатов: $count\n";
?>Сертификат #1: /C=RU/O=Example Corp/CN=example.com Действителен до: 2024-12-31 Сертификат #2: /C=US/O=Intermediate CA/CN=CA Intermediate Действителен до: 2026-12-31 Сертификат #3: /C=US/O=Root CA/CN=Global Root Действителен до: 2030-12-31 Обработано сертификатов: 3
<?php
function signDataWithTempCertificate($data, $privateKey, $certContent) {
// Создание временного файла для сертификата
$tempCertFile = tempnam(sys_get_temp_dir(), 'cert_');
file_put_contents($tempCertFile, $certContent);
// Подпись данных
$tempInfile = tempnam(sys_get_temp_dir(), 'in_');
$tempOutfile = tempnam(sys_get_temp_dir(), 'out_');
file_put_contents($tempInfile, $data);
if (openssl_pkcs7_sign($tempInfile, $tempOutfile,
$tempCertFile, $privateKey, [], PKCS7_DETACHED)) {
$signedData = file_get_contents($tempOutfile);
} else {
$signedData = false;
}
// Очистка временных файлов
unlink($tempCertFile);
unlink($tempInfile);
unlink($tempOutfile);
return $signedData;
}
// Альтернативный подход с openssl_x509_read и openssl_x509_free
function signDataInMemory($data, $privateKey, $certContent) {
$cert = openssl_x509_read($certContent);
if ($cert === false) {
return false;
}
// В реальном приложении здесь была бы подпись
$certInfo = openssl_x509_parse($cert);
// Освобождение ресурса сертификата
openssl_x509_free($cert);
return [
'signed' => true,
'cert_info' => $certInfo['name'],
'timestamp' => time()
];
}
// Пример использования
$result = signDataInMemory('Test data', $privKey, $certPem);
print_r($result);
?>Array
(
[signed] => 1
[cert_info] => /C=RU/O=Test Company/CN=test.example.com
[timestamp] => 1678891234
)<?php
class CertificateBatchProcessor {
private $maxMemoryUsage;
public function __construct($maxMemoryMB = 50) {
$this->maxMemoryUsage = $maxMemoryMB * 1024 * 1024;
}
public function processBatch($certificatePaths) {
$results = [];
foreach ($certificatePaths as $path) {
if (!file_exists($path)) {
$results[$path] = 'Файл не найден';
continue;
}
$certData = file_get_contents($path);
$cert = openssl_x509_read($certData);
if ($cert === false) {
$results[$path] = 'Неверный формат сертификата';
continue;
}
$info = openssl_x509_parse($cert);
$results[$path] = [
'subject' => $info['name'],
'valid_to' => date('Y-m-d', $info['validTo_time_t']),
'is_expired' => time() > $info['validTo_time_t']
];
// Явное освобождение ресурса
openssl_x509_free($cert);
// Контроль использования памяти
if (memory_get_usage(true) > $this->maxMemoryUsage) {
gc_collect_cycles(); // Принудительный сбор мусора
}
}
return $results;
}
}
// Использование
$processor = new CertificateBatchProcessor(10); // Лимит 10MB
$certFiles = glob('/path/to/certificates/*.crt');
$results = $processor->processBatch(array_slice($certFiles, 0, 100));
echo "Обработано: " . count($results) . " сертификатов\n";
echo "Использовано памяти: " . round(memory_get_peak_usage(true) / 1024 / 1024, 2) . " MB\n";
?>Обработано: 100 сертификатов Использовано памяти: 8.42 MB