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

Проверка назначения сертификата с помощью openssl_x509_checkpurpose
Раздел: Шифрование (OpenSSL)
openssl_x509_checkpurpose(OpenSSLCertificate|string $certificate, int $purpose, array $ca_info = [], ?string $untrusted_certificates_file = null): bool|int

Функция openssl_x509_checkpurpose

Назначение

Функция openssl_x509_checkpurpose анализирует сертификат X.509 для определения его пригодности для конкретных целей, например, для проверки подписи кода или защиты электронной почты. Она используется при построении цепочек доверия и валидации сертификатов в системах безопасности.

Аргументы функции
openssl_x509_checkpurpose(
    mixed $certificate,
    int $purpose,
    array $ca_info = [],
    ?string $untrusted_certificates_file = null
): bool|int
  • $certificate - сертификат X.509. Может быть строкой с PEM-данными, путем к файлу или ресурсом типа OpenSSLCertificate.
  • $purpose - цель проверки. Используются константы:
    OPENSSL_X509_PURPOSE_SSL_CLIENT (1)
    OPENSSL_X509_PURPOSE_SSL_SERVER (2)
    OPENSSL_X509_PURPOSE_NS_SSL_SERVER (3)
    OPENSSL_X509_PURPOSE_SMIME_SIGN (4)
    OPENSSL_X509_PURPOSE_SMIME_ENCRYPT (5)
    OPENSSL_X509_PURPOSE_CRL_SIGN (6)
    OPENSSL_X509_PURPOSE_ANY (7)
  • $ca_info - массив с доверенными корневыми и промежуточными сертификатами.
  • $untrusted_certificates_file - путь к файлу, содержащему дополнительные непроверенные сертификаты для построения цепочки.

Функция возвращает true при успешной проверке, false - при неудаче, и -1 в случае возникновения ошибки.

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

Проверка сертификата для SSL-сервера
<?php
$cert = file_get_contents('server.crt');
$ca = [file_get_contents('ca.crt')];
$result = openssl_x509_checkpurpose($cert, OPENSSL_X509_PURPOSE_SSL_SERVER, $ca);
var_dump($result);
bool(true)
Проверка для подписи S/MIME без указания CA
<?php
$cert = '-----BEGIN CERTIFICATE-----...';
$result = openssl_x509_checkpurpose($cert, OPENSSL_X509_PURPOSE_SMIME_SIGN);
var_dump($result);
bool(false)
Использование файла с непроверенными сертификатами
<?php
$result = openssl_x509_checkpurpose(
    'client.crt',
    OPENSSL_X509_PURPOSE_SSL_CLIENT,
    [],
    'untrusted.pem'
);
echo $result ? 'Valid' : 'Invalid';
Invalid

Похожие функции в PHP

  • openssl_x509_verify() - проверяет цифровую подпись сертификата с помощью публичного ключа. Используется для проверки подлинности, а не назначения.
  • openssl_x509_parse() - извлекает данные из сертификата. Позволяет вручную анализировать поля расширений, такие как keyUsage и extendedKeyUsage.
  • openssl_pkcs7_verify() - проверяет подпись S/MIME. Более узкоспециализированная функция для конкретного формата.

Выбор зависит от задачи: openssl_x509_checkpurpose удобна для быстрой проверки соответствия стандартным целям, а openssl_x509_parse дает больше контроля для кастомной логики.

Типичные ошибки

Некорректный формат сертификата
<?php
$result = openssl_x509_checkpurpose('not_a_cert', OPENSSL_X509_PURPOSE_ANY);
var_dump($result);
int(-1)
Отсутствие необходимых расширений в сертификате
<?php
// Сертификат без keyUsage для SSL сервера
$result = openssl_x509_checkpurpose($cert, OPENSSL_X509_PURPOSE_SSL_SERVER);
var_dump($result);
bool(false)
Передача неверного типа в $ca_info
<?php
$result = openssl_x509_checkpurpose($cert, OPENSSL_X509_PURPOSE_SMIME_SIGN, 'not_an_array');
var_dump($result);
Warning: openssl_x509_checkpurpose() expects parameter 3 to be array, string given

Изменения в PHP

  • PHP 8.0: параметр $certificate теперь принимает объект OpenSSLCertificate. Тип возвращаемого значения теперь bool|int (ранее int).
  • PHP 8.1: параметр $untrusted_certificates_file стал nullable (может быть null).

Расширенные примеры

Проверка нескольких целей
Пример php
<?php
$cert = file_get_contents('multipurpose.crt');
$purposes = [
    'SSL Client' => OPENSSL_X509_PURPOSE_SSL_CLIENT,
    'SSL Server' => OPENSSL_X509_PURPOSE_SSL_SERVER,
    'S/MIME Sign' => OPENSSL_X509_PURPOSE_SMIME_SIGN,
];
foreach ($purposes as $name => $purpose) {
    $result = openssl_x509_checkpurpose($cert, $purpose);
    echo "$name: " . ($result ? 'Yes' : 'No') . "\n";
}
SSL Client: No
SSL Server: Yes
S/MIME Sign: No
Построение цепочки с массивом CA
Пример php
<?php
$caBundle = [
    file_get_contents('root-ca.crt'),
    file_get_contents('intermediate-ca.crt')
];
$result = openssl_x509_checkpurpose(
    'end-entity.crt',
    OPENSSL_X509_PURPOSE_SSL_SERVER,
    $caBundle
);
var_dump($result);
bool(true)
Обработка результата с кодом ошибки
Пример php
<?php
$result = openssl_x509_checkpurpose('invalid_data', 2);
if ($result === -1) {
    echo 'Произошла ошибка при обработке сертификата';
    // Можно получить детали через openssl_error_string()
    while ($msg = openssl_error_string()) {
        echo $msg . "\n";
    }
}
Произошла ошибка при обработке сертификата
error:0909006C:PEM routines:get_name:no start line
Использование с ресурсом сертификата
Пример php
<?php
$certResource = openssl_x509_read(file_get_contents('cert.pem'));
$result = openssl_x509_checkpurpose($certResource, OPENSSL_X509_PURPOSE_CRL_SIGN);
openssl_x509_free($certResource);
var_dump($result);
bool(false)

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

Python (cryptography)
from cryptography import x509
from cryptography.hazmat.backends import default_backend

with open("cert.pem", "rb") as f:
    cert = x509.load_pem_x509_certificate(f.read(), default_backend())
# Проверка расширений вручную
key_usage = cert.extensions.get_extension_for_class(x509.KeyUsage)
print(key_usage.value.digital_signature)
True
JavaScript (Node.js с модулем crypto)
const crypto = require('crypto');
const cert = `-----BEGIN CERTIFICATE-----...`;
const x509 = new crypto.X509Certificate(cert);
console.log(x509.checkPurpose('sslCA')); // Аналог проверки цели
true
MySQL

Прямого аналога нет. MySQL использует SSL-контекст для соединений, но не предоставляет функций для детального анализа сертификатов.

PHP openssl_x509_checkpurpose function comments

En
Openssl x509 checkpurpose Verifies if a certificate can be used for a particular purpose