Openssl csr get public key: примеры (PHP)

Функция openssl_csr_get_public_key: примеры и применение
Раздел: Шифрование (OpenSSL)
openssl_csr_get_public_key(OpenSSLCertificateSigningRequest|string $csr, bool $short_names = true): OpenSSLAsymmetricKey|false

Функция openssl_csr_get_public_key

Функция openssl_csr_get_public_key извлекает открытый ключ из запроса на подпись сертификата (CSR). Она используется в процессах генерации и проверки SSL/TLS сертификатов, когда необходимо получить публичную часть ключа для последующих операций, таких как проверка подписи или создание самоподписанного сертификата.

Аргументы функции
  • csr - принимает строку в формате PEM или ресурс, сгенерированный функциями openssl_csr_new() или openssl_csr_sign(). Это обязательный параметр.
  • short_names - необязательный булевый параметр, который управляет форматом возвращаемого идентификатора ключа. При значении true используются короткие имена, при false - длинные. По умолчанию true.

Функция возвращает ресурс (resource) типа OpenSSL key, содержащий открытый ключ, или false в случае ошибки.

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

Извлечение ключа из CSR в виде строки
$csr = '-----BEGIN CERTIFICATE REQUEST-----
MIIC0zCCAbsCAQAwgYUxCzAJBgNVBAYTAlJVMRMwEQYDVQQIEwpTb21lLVN0YXRl
...
-----END CERTIFICATE REQUEST-----';
$publicKey = openssl_csr_get_public_key($csr);
var_dump($publicKey);
resource(5) of type (OpenSSL key)
Использование ресурса CSR
$privkey = openssl_pkey_new(['private_key_bits' => 2048]);
$csrResource = openssl_csr_new(['CN' => 'example.com'], $privkey);
$publicKey = openssl_csr_get_public_key($csrResource);
var_dump($publicKey);
resource(7) of type (OpenSSL key)
С параметром short_names
$csr = '-----BEGIN CERTIFICATE REQUEST-----...';
$publicKey = openssl_csr_get_public_key($csr, false);
$details = openssl_pkey_get_details($publicKey);
print_r($details['key']);
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw...
-----END PUBLIC KEY-----

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

В PHP существуют несколько функций для работы с ключами и сертификатами:

  • openssl_csr_get_subject() - извлекает субъект из CSR, возвращая массив с информацией о владельце.
  • openssl_pkey_get_public() - получает ресурс открытого ключа из строки PEM или файла. Используется, когда ключ уже извлечен из CSR или получен из другого источника.
  • openssl_csr_new() - генерирует новый CSR на основе переданных данных и приватного ключа.
  • openssl_csr_sign() - подписывает CSR, создавая сертификат X.509.

Функцию openssl_csr_get_public_key используют, когда необходим именно открытый ключ из существующего CSR. Для получения информации о субъекте CSR применяют openssl_csr_get_subject. Если требуется работать с отдельно хранящимся публичным ключом, подходит openssl_pkey_get_public.

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

Некорректный формат CSR
$invalidCSR = 'invalid data';
$result = openssl_csr_get_public_key($invalidCSR);
var_dump($result);
bool(false)
Использование неподдерживаемого типа данных
$array = ['data' => 'test'];
$result = openssl_csr_get_public_key($array);
var_dump($result);
Warning: openssl_csr_get_public_key() expects parameter 1 to be string or OpenSSLCertificateSigningRequest, array given
Попытка извлечь ключ из уже освобожденного ресурса
$privkey = openssl_pkey_new(['private_key_bits' => 2048]);
$csr = openssl_csr_new(['CN' => 'test'], $privkey);
unset($csr);
$publicKey = openssl_csr_get_public_key($csr);
Warning: openssl_csr_get_public_key() expects parameter 1 to be string or OpenSSLCertificateSigningRequest, null given

Изменения в версиях PHP

В PHP 8.0 изменен тип параметра csr. Теперь вместо ресурса (resource) принимается объект OpenSSLCertificateSigningRequest. Также функция теперь выбрасывает исключение Error при неудаче, вместо возврата false и генерации предупреждения.

В PHP 8.1 добавлена поддержка объекта OpenSSLCertificateSigningRequest в качестве возвращаемого значения для функций, генерирующих CSR.

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

Валидация подписи CSR
Пример php
$privkey = openssl_pkey_new(['private_key_bits' => 2048]);
$csr = openssl_csr_new(['CN' => 'example.com'], $privkey);
$publicKey = openssl_csr_get_public_key($csr);
$csrDetails = openssl_csr_get_subject($csr);
$newCsr = openssl_csr_new($csrDetails, $privkey);
$newPublicKey = openssl_csr_get_public_key($newCsr);
$details1 = openssl_pkey_get_details($publicKey);
$details2 = openssl_pkey_get_details($newPublicKey);
echo 'Ключи совпадают: ' . ($details1['key'] === $details2['key'] ? 'Да' : 'Нет');
Ключи совпадают: Да
Экспорт ключа в разные форматы
Пример php
$csr = '-----BEGIN CERTIFICATE REQUEST-----...';
$publicKey = openssl_csr_get_public_key($csr);
$details = openssl_pkey_get_details($publicKey);
echo 'PEM формат:\n' . $details['key'];
echo '\nМодуль RSA (hex):\n' . bin2hex($details['rsa']['n']);
echo '\nЭкспонента (hex):\n' . bin2hex($details['rsa']['e']);
PEM формат:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----
Модуль RSA (hex):
00a123b4...
Экспонента (hex):
010001
Создание самоподписанного сертификата из CSR
Пример php
$privkey = openssl_pkey_new(['private_key_bits' => 2048]);
$csr = openssl_csr_new(['CN' => 'myhost.local'], $privkey);
$publicKey = openssl_csr_get_public_key($csr);
$cert = openssl_csr_sign($csr, null, $privkey, 365);
openssl_x509_export($cert, $certPEM);
echo substr($certPEM, 0, 100) . '...';
-----BEGIN CERTIFICATE-----
MIIDUTCCAjmgAwIBAgIUFtKQsD8Kf9n2Q3J5Q2k4Q3k4Q3kwDQYJKoZIhvcNAQEL...
-----END CERTIFICATE-----
Извлечение ключа из CSR, хранящегося в файле
Пример php
$csrContent = file_get_contents('request.csr');
$publicKey = openssl_csr_get_public_key($csrContent);
if ($publicKey === false) {
    echo 'Ошибка чтения CSR';
} else {
    $details = openssl_pkey_get_details($publicKey);
    file_put_contents('public_key.pem', $details['key']);
    echo 'Публичный ключ сохранен';
}
Публичный ключ сохранен

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

Python (cryptography)
from cryptography import x509
from cryptography.hazmat.primitives import serialization

csr_pem = """-----BEGIN CERTIFICATE REQUEST-----..."""
csr = x509.load_pem_x509_csr(csr_pem.encode())
public_key = csr.public_key()
print(public_key.public_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PublicFormat.SubjectPublicKeyInfo
).decode())
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----
Node.js (crypto module)
const crypto = require('crypto');
const csr = `-----BEGIN CERTIFICATE REQUEST-----...`;
const publicKey = crypto.createPublicKey({
    key: csr,
    format: 'pem',
    type: 'spki'
});
console.log(publicKey.export({ format: 'pem', type: 'spki' }));
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----
OpenSSL CLI
openssl req -in request.csr -pubkey -noout
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
-----END PUBLIC KEY-----

В отличие от PHP, где функция возвращает ресурс, в Python и Node.js объекты ключей являются полноценными объектами со своими методами. OpenSSL CLI предоставляет консольную альтернативу.

PHP openssl_csr_get_public_key function comments

En
Openssl csr get public key Returns the public key of a CSR