Как я могу конвертировать открытый ключ DSA из формата OpenSSL в формат OpenSSH в PHP?


Я использовал ключи RSA в своем приложении. Я использовал следующий код для преобразования ключа RSA из формата OpenSSL в формат OpenSSH. Это отлично работало для ключа RSA. Теперь я хочу поддерживать ключи DSA. Но мой код преобразования не работает для ключей DSA. Какая модификация мне нужна, чтобы заставить его работать с ключами DSA?

$private_key = openssl_pkey_get_private($rsaKey);
$public_key  = sshEncodePublicKey($private_key);

echo "RSA public key in OpenSSH format:\n$pubKey\n\n";

function sshEncodePublicKey($privKey)
{
    $keyInfo = openssl_pkey_get_details($privKey);

    $buffer  = pack("N", 7) . "ssh-rsa" . 
               sshEncodeBuffer($keyInfo['rsa']['e']) . 
               sshEncodeBuffer($keyInfo['rsa']['n']);

    return "ssh-rsa " . base64_encode($buffer); 
}

function sshEncodeBuffer($buffer)
{
    $len = strlen($buffer);
    if (ord($buffer[0]) & 0x80) {
        $len++;
        $buffer = "\x00" . $buffer;
    }

    return pack("Na*", $len, $buffer);
}
Author: Harikrishnan, 2016-06-03

1 answers

Определение ключа dsa принципиально отличается от определения ключей rsa. Там нет "экспоненты" (числа, к которому вы обращаетесь с помощью $keyInfo['rsa']['e'] и нет n. Поскольку ваш код анализирует ключ и повторно кодирует его, это не удастся с ключами dsa. Вместо этого openssl_pkey_get_details предоставляет вам совершенно другой массив элементов, как указано в руководстве.

Чтобы преобразовать это, используйте следующий код:

function sshEncodePublicKey($privKey)
{
    $keyInfo = openssl_pkey_get_details($privKey);

    $buffer  = pack("N", 7) . "ssh-dss" .
               sshEncodeBuffer($keyInfo['dsa']['p']) .
               sshEncodeBuffer($keyInfo['dsa']['q']) .
               sshEncodeBuffer($keyInfo['dsa']['g']) .
               sshEncodeBuffer($keyInfo['dsa']['pub_key']);

    return "ssh-dss " . base64_encode($buffer);
}

Конечно, ваш код должен решить, какой это тип ключа, но я думаю, я могу оставить это тебе.

Пожалуйста, также обратите внимание, что PHP имеет функцию openssl_pkey_get_public, которая более подходит. Я использовал это для тестирования приведенного выше кода (я просто заменил ваши первые 4 строки на $public_key = sshEncodePublicKey(openssl_pkey_get_public('file://ssl.pub'));

 2
Author: tillz, 2016-06-03 09:20:44