Openssl spki new: примеры (PHP)
openssl_spki_new(OpenSSLAsymmetricKey $private_key, string $challenge, int $digest_algo = OPENSSL_ALGO_MD5): string|falseФункция openssl_spki_new
openssl_spki_new создает подписанный открытый ключ и запрос (SPKAC). Эта функция генерирует новую пару открытого и закрытого ключей, подписывает открытый ключ с использованием закрытого и возвращает закодированную строку в формате SPKAC.
Функция применяется в веб-криптографии, например для генерации ключей непосредственно в браузере через элемент <keygen> (устаревший) или Web Crypto API, с последующей передачей на сервер для обработки и верификации.
- private_key (resource) — ресурс закрытого ключа, созданный с помощью openssl_pkey_new().
- challenge (string) — строка челленджа (обычно случайные данные), используемая для подписи. Может быть пустой строкой.
- digest_algo (int) — алгоритм хеширования. По умолчанию OPENSSL_ALGO_MD5 (устаревший). Рекомендуется использовать OPENSSL_ALGO_SHA256 или другие современные алгоритмы.
Простые примеры использования
<?php
$privateKey = openssl_pkey_new([
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
]);
$spkac = openssl_spki_new($privateKey, 'random_challenge', OPENSSL_ALGO_SHA256);
echo $spkac;
?>SPKAC=MII... (длинная закодированная строка)
<?php
$config = [
'digest_alg' => 'sha512',
'private_key_bits' => 4096,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
$pkey = openssl_pkey_new($config);
$spkac = openssl_spki_new($pkey, '', OPENSSL_ALGO_SHA512);
var_dump(strlen($spkac) > 100);
?>bool(true)
Похожие функции в PHP
Создает запрос на подпись сертификата (CSR). Более сложная структура, предназначенная для инфраструктуры открытых ключей (PKI). Используется для получения сертификатов от центра сертификации.
Генерирует новую пару ключей. Является основой для openssl_spki_new, но не создает подписанный запрос.
openssl_spki_new применяется для простых сценариев веб-аутентификации. openssl_csr_new используется при работе с полными SSL/TLS сертификатами.
Типичные ошибки
<?php
$spkac = openssl_spki_new('not_a_resource', 'test', OPENSSL_ALGO_SHA256);
var_dump($spkac);
?>bool(false) // Также генерируется предупреждение: openssl_spki_new(): supplied key param cannot be coerced into a private key
<?php
$pkey = openssl_pkey_new(['private_key_bits' => 2048]);
$spkac = openssl_spki_new($pkey, 'test', OPENSSL_ALGO_MD5);
// MD5 считается криптографически небезопасным
echo $spkac !== false ? 'Успешно, но небезопасно' : 'Ошибка';
?>Успешно, но небезопасно
<?php
// При отсутствии настроек openssl.cnf может возникнуть ошибка
$pkey = @openssl_pkey_new();
if ($pkey === false) {
echo 'Не удалось сгенерировать ключ. Проверьте конфигурацию OpenSSL.';
}
?>Не удалось сгенерировать ключ. Проверьте конфигурацию OpenSSL.
Изменения в версиях PHP
Тип возвращаемого значения для ошибок изменен с false на null в некоторых случаях, хотя документация указывает false. Рекомендуется строгая проверка на идентичность (===).
Добавлена поддержка алгоритма SHA256 и более новых в качестве рекомендуемых значений по умолчанию вместо MD5.
В PHP 8.0 усилены строгие типы, поэтому передача неверного типа аргумента вызывает TypeError вместо предупреждения.
Расширенные примеры
<?php
// Генерация
$pkey = openssl_pkey_new([
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
]);
$challenge = base64_encode(random_bytes(16));
$spkac = openssl_spki_new($pkey, $challenge, OPENSSL_ALGO_SHA384);
// Проверка
$verify = openssl_spki_verify(preg_replace('/SPKAC=/', '', $spkac));
var_dump($verify);
// Извлечение открытого ключа
$pubKey = openssl_spki_export(preg_replace('/SPKAC=/', '', $spkac));
echo substr($pubKey, 0, 50) . "...\n";
// Извлечение челленджа
$extractedChallenge = openssl_spki_export_challenge(preg_replace('/SPKAC=/', '', $spkac));
echo $extractedChallenge === $challenge ? 'Челлендж совпадает' : 'Не совпадает';
?>bool(true) -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA... Челлендж совпадает
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['spkac'])) {
$spkac = $_POST['spkac'];
if (openssl_spki_verify(preg_replace('/SPKAC=/', '', $spkac))) {
echo '<div class="fw-bold">SPKAC верифицирован успешно</div>';
}
}
?>
<!-- Устаревший элемент keygen -->
<form method="post">
<keygen name="spkac" challenge="random123" keytype="RSA">
<input type="submit">
</form><?php
// Генерация EC-ключа (требует PHP 7.1+)
$ecKey = openssl_pkey_new([
'private_key_type' => OPENSSL_KEYTYPE_EC,
'curve_name' => 'prime256v1',
]);
if ($ecKey) {
$spkacEc = openssl_spki_new($ecKey, 'ec_challenge', OPENSSL_ALGO_SHA256);
var_dump($spkacEc !== false);
}
?>bool(true)
Альтернативы в других языках
// Генерация ключей и экспорт в формате SPKI
window.crypto.subtle.generateKey(
{
name: "RSASSA-PKCS1-v1_5",
modulusLength: 2048,
publicExponent: new Uint8Array([1, 0, 1]),
hash: "SHA-256",
},
true,
["sign", "verify"]
).then(keyPair => {
return window.crypto.subtle.exportKey("spki", keyPair.publicKey);
}).then(spki => {
console.log(btoa(String.fromCharCode(...new Uint8Array(spki))));
});MIIBIjANBgkq... (Base64 SPKI)
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.backends import default_backend
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=default_backend()
)
public_key = private_key.public_key()
spki = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
print(spki.decode())
-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA... -----END PUBLIC KEY-----
Python и JavaScript работают с форматом SPKI, а не SPKAC. SPKAC включает подпись и челлендж, что делает его уникальным форматом для запросов.