Openssl private decrypt: примеры (PHP)

Использование openssl_private_decrypt для асимметричной расшифровки
Раздел: Шифрование (OpenSSL)
openssl_private_decrypt(string $data, string &$decrypted_data, OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key, int $padding = OPENSSL_PKCS1_PADDING): bool

Описание функции openssl_private_decrypt

Назначение и применение

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

Аргументы функции

Функция принимает четыре параметра:

  • $data (string) — строка с зашифрованными данными для расшифровки.
  • &$decrypted (string) — переменная, передаваемая по ссылке, в которую будет помещён результат расшифровки.
  • $private_key (mixed) — закрытый ключ. Может быть строкой в формате PEM, ресурсом типа OpenSSL key или объектом OpenSSLAsymmetricKey/OpenSSLCertificate (начиная с PHP 8.0).
  • $padding (int) — опциональный аргумент, определяющий режим дополнения (padding). Возможные значения: OPENSSL_PKCS1_PADDING (по умолчанию), OPENSSL_PKCS1_OAEP_PADDING, OPENSSL_SSLV23_PADDING, OPENSSL_NO_PADDING.

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

Базовый пример расшифровки

Использование с ключом в формате PEM и стандартным заполнением:

$privateKey = openssl_pkey_get_private('file://path/to/private.pem');
$encryptedData = base64_decode('... зашифрованная строка в base64 ...');
$success = openssl_private_decrypt($encryptedData, $decrypted, $privateKey);
if ($success) {
    echo $decrypted;
}
Расшифрованный текст
Пример с OPENSSL_PKCS1_OAEP_PADDING

Использование более безопасного метода заполнения OAEP:

$success = openssl_private_decrypt(
    $encryptedData,
    $decrypted,
    $privateKey,
    OPENSSL_PKCS1_OAEP_PADDING
);
Данные, расшифрованные с OAEP
Расшифровка с возвратом false

Случай, когда функция возвращает false из-за ошибки:

$result = openssl_private_decrypt('invalid_data', $decrypted, $privateKey);
var_dump($result); // false
bool(false)

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

Функция для шифрования данных открытым ключом. Применяется в паре с openssl_private_decrypt.

Обратная операция — расшифровка данных закрытым ключом после шифрования открытым.

Шифрование с использованием закрытого ключа. Используется для создания цифровых подписей.

Sodium library

Библиотека Sodium предоставляет современные криптографические примитивы. Функции crypto_box_seal_open и crypto_box_seal являются асимметричными аналогами. Рекомендуется для новых проектов из-за более простого API и устойчивости к типичным ошибкам.

Распространённые ошибки

Некорректный закрытый ключ

Использование ключа в неправильном формате или повреждённого ключа:

$wrongKey = 'not a valid key';
$result = openssl_private_decrypt($data, $decrypted, $wrongKey);
if ($result === false) {
    echo openssl_error_string();
}
error:0909006C:PEM routines:get_name:no start line
Несоответствие метода заполнения

Использование другого padding при расшифровке, отличного от применённого при шифровании:

// Зашифровано с OPENSSL_PKCS1_OAEP_PADDING
// Попытка расшифровать с OPENSSL_PKCS1_PADDING (по умолчанию)
openssl_private_decrypt($data, $decrypted, $key); // Вернёт false
bool(false)
Превышение размера данных

Попытка расшифровать данные, размер которых превышает возможности ключа:

// Ключ RSA 2048 бит может шифровать блоки до 245 байт (с PKCS1_PADDING)
$largeData = random_bytes(300);
// ... шифрование и попытка расшифровки ...
Функция может завершиться неудачей или вернуть мусор

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

PHP 8.0

Тип параметра $private_key был расширен. Теперь, помимо строки и ресурса, функция принимает объекты классов OpenSSLAsymmetricKey и OpenSSLCertificate. Устаревший ресурсный тип (resource) был заменён на эти объекты.

PHP 7.2

Было добавлено предупреждение при использовании устаревшего ресурса вместо объекта. Рекомендуется использовать функции openssl_pkey_get_private для получения корректного объекта ключа.

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

Расшифровка данных, зашифрованных на клиенте (JavaScript)

Сценарий, где данные шифруются на стороне браузера с помощью JS библиотеки (например, forge) и расшифровываются на сервере.

Пример php
// PHP серверная часть
$encryptedBase64 = $_POST['encrypted_data'];
$encrypted = base64_decode($encryptedBase64);

$privateKey = openssl_pkey_get_private('file://private.pem');
$success = openssl_private_decrypt(
    $encrypted,
    $decrypted,
    $privateKey,
    OPENSSL_PKCS1_OAEP_PADDING
);
// $decrypted содержит данные, отправленные клиентом
Использование ключа с паролем
Пример php
$privateKey = openssl_pkey_get_private(
    'file://private_protected.pem',
    'strong_password'
);
// Далее стандартная расшифровка
Обработка сериализованных данных

Расшифровка данных, которые после шифрования были сериализованы или упакованы.

Пример php
openssl_private_decrypt($encrypted, $serialized, $privateKey);
$data = unserialize($serialized); // Восстановление массива или объекта
Цикличная обработка нескольких зашифрованных блоков

Пример, когда большие данные разбиты на блоки и зашифрованы по отдельности.

Пример php
$fullDecrypted = '';
foreach ($encryptedChunks as $chunk) {
    openssl_private_decrypt($chunk, $decryptedChunk, $privateKey);
    $fullDecrypted .= $decryptedChunk;
}
Работа с результатом как с файловым потоком

Расшифрованные данные могут быть сразу записаны в файл или переданы дальше.

Пример php
if (openssl_private_decrypt($encrypted, $decrypted, $privateKey)) {
    file_put_contents('decrypted.txt', $decrypted);
}

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

Python (cryptography)
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding

with open("private.pem", "rb") as key_file:
    private_key = serialization.load_pem_private_key(
        key_file.read(),
        password=None
    )

decrypted = private_key.decrypt(
    ciphertext,
    padding.OAEP(
        mgf=padding.MGF1(algorithm=hashes.SHA256()),
        algorithm=hashes.SHA256(),
        label=None
    )
)
b'decrypted data'
JavaScript (Node.js, Web Crypto API)

Node.js пример с crypto.privateDecrypt:

const crypto = require('crypto');
const privateKey = crypto.createPrivateKey(fs.readFileSync('private.pem'));
const decrypted = crypto.privateDecrypt(
    {
        key: privateKey,
        padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
    },
    Buffer.from(encryptedData, 'base64')
);

Openssl private decrypt в MySQL

Прямого аналога асимметричного расшифрования закрытым ключом нет. MySQL предлагает функции для симметричного шифрования (AES_DECRYPT).

PHP openssl_private_decrypt function comments

En
Openssl private decrypt Decrypts data with private key