Создание RSA ключей, подпись и шифрование данных

Как создать ключ с помощью php?

// генерируем ключ
$keyResource = openssl_pkey_new([
    'private_key_bits' => 2048,
    'private_key_type' => OPENSSL_KEYTYPE_RSA,
]);

echo gettype($keyResource) . PHP_EOL; // resource

// получаем приватный ключ
openssl_pkey_export(
    $keyResource,
    $privateKey
);

echo $privateKey;
// -----BEGIN PRIVATE KEY-----
// MIIEvgIBADANBgkqhkiG9w0BAQEF...
// ...
// -----END PRIVATE KEY-----

// сохраняем приватный ключ в файл
file_put_contents(
    'php-private-key.pem', 
    $privateKey
);

// получаем публичный ключ
$publicKey = openssl_pkey_get_details($keyResource);

echo $publicKey['key'];
// -----BEGIN PUBLIC KEY-----
// MIIBIjANBgkqhkiG9w0BAQEFAAO...
// ...
// -----END PUBLIC KEY-----

// сохраняем публичный ключ в файл
file_put_contents(
    'php-public-key.pem',
    $publicKey['key']
);

Для использования ключа php-private-key.pem в PUTTYGEN понадобится преобразовать приватный ключ в traditional формат:

openssl rsa -in php-private-key.pem -outform PEM -out php-private-key-traditional.pem

Как создать ключ из командной строки с помощью ssh-keygen?

ssh-keygen -t rsa -b 2048 -f ssh-keygen-private-key.pem -m pem
openssl rsa -in ssh-keygen-private-key.pem -outform PEM -pubout -out ssh-keygen-public-key.pem

Если при запуске возникает ошибка: ssh-keygen: illegal option -- m, то воспользуйтесь генерацией из командной строки с помощью openssl.

Как создать ключ из командной строки с помощью openssl?

openssl genrsa -out openssl-private-key.pem 2048
openssl rsa -in openssl-private-key.pem -outform PEM -pubout -out openssl-public-key.pem

Как из приватного ключа создать публичный однострочный ключ для вставки в файл authorized_keys?

ssh-keygen -f openssl-private-key.pem -y > openssl-private-key.pem.pub
# или
ssh-keygen -f php-private-key-traditional.pem -y > php-private-key-traditional.pem.pub

Как подписать данные приватным ключом и проверить подпись публичным ключом?

Создаём подпись:

// данные
$data = 'My important data!';

// загружаем приватный ключ
$privateKey = openssl_pkey_get_private(
    sprintf(
        'file://%s/%s',
        dirname(__FILE__),
        'php-private-key.pem'
    )
);

// подписываем данные приватным ключом
openssl_sign(
    $data,
    $signature, // подпись сохранится в эту переменную
    $privateKey
);

// высвобождаем приватный ключ
openssl_free_key($privateKey);

Проверяем подпись:

// данные
$data = 'My important data!';

// загружаем публичный ключ 
$publicKey = openssl_pkey_get_public(
    sprintf(
        'file://%s/%s',
        dirname(__FILE__),
        'php-public-key.pem'
    )
);

// проверяем подпись публичным ключом
$result = openssl_verify(
    $data,
    $signature,
    $publicKey
);

// высвобождаем публичный ключ
openssl_free_key($publicKey);

// выводим результат проверки
if ($result === 1) {
    echo 'Verified';
} elseif ($result === 0) {
    echo 'Not verified';
} else {
    echo openssl_error_string();
}

Как зашифровать данные приватным ключом и расшифровать публичным?

Шифруем данные приватным ключом:

// данные
$data = 'My important data!';

// загружаем приватный ключ
$privateKey = openssl_pkey_get_private(
    sprintf(
        'file://%s/%s',
        dirname(__FILE__),
        'php-private-key.pem'
    )
);

// шифруем данные приватным ключом
openssl_private_encrypt(
    $data,
    $encrypted,
    $privateKey
);

// высвобождаем приватный ключ
openssl_free_key($privateKey);

$encrypted = base64_encode($encrypted);

Расшифровываем публичным ключом:

$encrypted = base64_decode($encrypted);

// загружаем публичный ключ
$publicKey = openssl_pkey_get_public(
    sprintf(
        'file://%s/%s',
        dirname(__FILE__),
        'php-public-key.pem'
    )
);

// расшифровываем данные публичным ключом
openssl_public_decrypt(
    $encrypted,
    $decrypted, // 'My important data!'
    $publicKey
);

// высвобождаем публичный ключ
openssl_free_key($publicKey);

echo '<pre>';
var_export($decrypted);
echo '</pre>';

Как зашифровать данные публичным ключом и расшифровать приватным?

Шифруем данные публичным ключом:

// данные
$data = 'My important data!';

// загружаем публичный ключ
$publicKey = openssl_pkey_get_public(
    sprintf(
        'file://%s/%s',
        dirname(__FILE__),
        'php-public-key.pem'
    )
);

// шифруем данные публичным ключом
openssl_public_encrypt(
    $data,
    $encrypted,
    $publicKey
);

// высвобождаем публичный ключ
openssl_free_key($publicKey);

$encrypted = base64_encode($encrypted);

Расшифровываем приватным:

// загружаем приватный ключ
$privateKey = openssl_pkey_get_private(
    sprintf(
        'file://%s/%s',
        dirname(__FILE__),
        'php-private-key.pem'
    )
);

$encrypted = base64_decode($encrypted);

// расшифровываем данные приватным ключом
openssl_private_decrypt(
    $encrypted,
    $decrypted, // 'My important data!'
    $privateKey
);

// высвобождаем приватный ключ
openssl_free_key($privateKey);

echo '<pre>';
var_export($decrypted);
echo '</pre>';