Harikrishnan
Harikrishnan

Reputation: 9979

How can I convert DSA public key from OpenSSL to OpenSSH format in PHP?

I have been using RSA keys with in my application. I have used the following code to convert RSA key from OpenSSL to OpenSSH format. It worked perfectly for RSA key. Now I want to support DSA keys. But my conversion code doesn't work for DSA keys. What modification do I need to make it to work with DSA keys?

$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);
}

Upvotes: 3

Views: 1284

Answers (1)

tillz
tillz

Reputation: 2108

The definition of a dsa key is fundamentally different from that of rsa keys. There ist no 'exponent' (the number you're accessing with $keyInfo['rsa']['e'] and no n. Because your code parses the key and reencodes it, this won't succeed with dsa keys. Instead, openssl_pkey_get_details gives you a completely different array of elements, as specified in the manual.

To convert this, use the following code:

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);
}

Of course, your code should decide which type of key it is, but I think i can leave this to you.

Please also note that PHP has the function openssl_pkey_get_public, which is more suitable. I used this to test the above code (I simply replaced your first 4 lines with $public_key = sshEncodePublicKey(openssl_pkey_get_public('file://ssl.pub'));

Upvotes: 2

Related Questions