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

Шифрование приватным ключом в PHP: функция openssl_private_encrypt
Раздел: Шифрование (OpenSSL)
openssl_private_encrypt(string $data, string &$encrypted_data, OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key, int $padding = OPENSSL_PKCS1_PADDING): bool
Функция openssl_private_encrypt

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

Аргументы функции
  • $data - строка данных для шифрования.
  • &$encrypted_data - переменная, в которую будет помещен результат шифрования.
  • $private_key - приватный ключ в формате строки или ресурса.
  • $padding - опциональный аргумент, определяющий режим дополнения (по умолчанию OPENSSL_PKCS1_PADDING). Альтернативный вариант - OPENSSL_NO_PADDING.
Базовые примеры использования
Простое шифрование
$privateKey = openssl_pkey_get_private('file://private.pem');
$data = 'Секретные данные';
$encrypted = '';

if (openssl_private_encrypt($data, $encrypted, $privateKey)) {
    echo 'Успешно зашифровано';
} else {
    echo 'Ошибка шифрования';
}
Успешно зашифровано
С разными режимами дополнения
// С PKCS1 padding (по умолчанию)
openssl_private_encrypt($data, $encrypted1, $privateKey, OPENSSL_PKCS1_PADDING);

// Без дополнения
openssl_private_encrypt($data, $encrypted2, $privateKey, OPENSSL_NO_PADDING);
Альтернативы в PHP

Создает цифровую подпись, а не шифрует данные. Предпочтительнее для верификации авторства.

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

Sodium библиотека

В современных версиях PHP рекомендуется использовать функции sodium_crypto_box для асимметричного шифрования.

Типичные ошибки
Некорректный ключ
$privateKey = 'неверный ключ';
$result = openssl_private_encrypt('test', $encrypted, $privateKey);
var_dump($result); // bool(false)
bool(false)
Превышение размера данных
// Для 2048-битного ключа максимальный размер данных при PKCS1_PADDING: 256 - 11 = 245 байт
$largeData = str_repeat('a', 300);
$result = openssl_private_encrypt($largeData, $encrypted, $privateKey);
if (!$result) {
    echo openssl_error_string();
}
error:0406C06E:rsa routines:RSA_padding_add_PKCS1_type_1:data too large for key size
Изменения в PHP 8.x

В PHP 8.0 изменен тип возвращаемого значения с ресурса на объект OpenSSLAsymmetricKey для ключей. Функция продолжает работать со старыми ресурсами, но возвращает объекты.

С PHP 8.0 многие функции OpenSSL выбрасывают исключения при ошибках вместо возврата false.

// PHP 8.x
$key = openssl_pkey_get_private('file://private.pem');
echo gettype($key); // object
echo get_class($key); // OpenSSLAsymmetricKey
Расширенные примеры
Создание цифровой подписи документа
Пример php
function createSignature($data, $privateKeyPath) {
    $privateKey = openssl_pkey_get_private(
        file_get_contents($privateKeyPath),
        'пароль_ключа'
    );
    
    $signature = '';
    openssl_private_encrypt(
        hash('sha256', $data, true),
        $signature,
        $privateKey
    );
    
    openssl_free_key($privateKey);
    return base64_encode($signature);
}

$document = 'Важный документ';
$signature = createSignature($document, 'private.pem');
echo 'Подпись: ' . $signature;
Гибридное шифрование
Пример php
// Шифрование сессионного ключа
$sessionKey = random_bytes(32);
$encryptedKey = '';

openssl_private_encrypt(
    $sessionKey,
    $encryptedKey,
    $privateKey,
    OPENSSL_PKCS1_OAEP_PADDING
);

// Далее $sessionKey используется для симметричного шифрования данных
Работа с различными форматами ключей
Пример php
// PEM строкой
$pemKey = "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANB...\n-----END PRIVATE KEY-----";

// Из файла
$fileKey = openssl_pkey_get_private('file://path/to/key.pem');

// Генерация нового ключа
$newKey = openssl_pkey_new([
    'private_key_bits' => 2048,
    'private_key_type' => OPENSSL_KEYTYPE_RSA
]);

openssl_private_encrypt($data, $encrypted, $newKey);
Аналоги в других языках

Openssl private encrypt в Python

from Crypto.PublicKey import RSA
from Crypto.Signature import pkcs1_15
from Crypto.Hash import SHA256

key = RSA.import_key(open('private.pem').read())
h = SHA256.new(b'data')
signature = pkcs1_15.new(key).sign(h)
JavaScript (Node.js)
const crypto = require('crypto');
const privateKey = `-----BEGIN PRIVATE KEY-----...`;
const sign = crypto.createSign('SHA256');
sign.update('data');
const signature = sign.sign(privateKey, 'base64');

Openssl private encrypt в MySQL

Функция ASYMMETRIC_ENCRYPT() поддерживает шифрование публичным ключом, но не приватным.

PHP openssl_private_encrypt function comments

En
Openssl private encrypt Encrypts data with private key