Openssl x509 free: примеры (PHP)

Полное руководство по функции openssl_x509_free в PHP
Раздел: Шифрование (OpenSSL)
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() для объектов
// Память освободится автоматически при уничтожении объекта
?>
Функция unset()

Для объектов OpenSSLCertificate в PHP 8.0+ можно использовать unset() для явного удаления ссылки на объект, что ускоряет освобождение памяти:

<?php
$cert = openssl_x509_read($certData);
// Работа с сертификатом
unset($cert); // Удаление ссылки на объект
?>

Альтернативы в других языках программирования

Python

В 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)>
JavaScript (Node.js)

В 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
Освобождение ресурса, возвращенного openssl_csr_sign
<?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

В 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

В PHP 8.2.0 улучшена обработка объектов OpenSSL и добавлены дополнительные методы валидации. Функция openssl_x509_free() формально объявлена устаревшей для использования с объектами, но продолжает функционировать.

Расширенные примеры использования

Обработка цепочки сертификатов
Пример php
<?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
Интеграция с openssl_pkcs7_sign
Пример php
<?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
<?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

PHP openssl_x509_free function comments

En
Openssl x509 free Free certificate resource