84

I'm having an issue generating a public key that the openssl PEM_read_bio_RSA_PUBKEY() function can consume. I keep getting errors.

Obviously I cannot simply use the ASCII string in the ssh-keygen <>.pub key file as it is in SSH file format or I perhaps SubjectPublicKeyInfo structure.

Here's the key gen code: ssh-keygen -t rsa -b 1024 -C "Test Key"

I found a converter in php on the web which will convert the contents of the public key into a base64 PEM ASCII string format. However the function still doesn't like it.

The Openssl documentation states:

  1. “RSA_PUBKEY() function which process a public key using an EVP_PKEY structure”
  2. “RSA_PUBKEY functions also process an RSA public key using an RSA structure”

How do I get my OpenSSH public key into either format that the OpenSSL function will consume it?

PeteP
  • 841
  • Figured this out: use the openssl tool only as such: – PeteP Dec 16 '11 at 23:17
  • Create Private key: openssl genrsa -out test.priv.key 2048; Output Public key in same format (PEM?): openssl rsa -in test.priv.key -pubout -out test.pub.key – PeteP Dec 16 '11 at 23:19
  • Cross-related https://security.stackexchange.com/questions/32768/converting-keys-between-openssl-and-openssh – dave_thompson_085 May 31 '19 at 06:08

6 Answers6

89

OK!

So I walked into this thinking "Easy, I got this." Turns out there's a whole lot more to it than even I thought.

The first issue is that (according to the man pages for OpenSSL, man 3 pem), OpenSSL is expecting the RSA key to be in PKCS#1 format. Clearly, this isn't what ssh-keygen is working with. You have two options (from searching around).

If you have OpenSSH v. 5.6 or later (I did not on my laptop), you can run this:

ssh-keygen -f key.pub -e -m pem

The longer method of doing this is to break apart your SSH key into its various components (the blog entry I found some of this in accuses OpenSSH of being "proprietary", I prefer to call it "unique") and then use an ASN1 library to swap things around.

Fortunately for you, someone wrote the code to do this:

https://gist.github.com/1024558

34

Assuming you have the SSH private key id_rsa, you can extract the public key from it like so:

openssl rsa -in id_rsa -pubout -out id_rsa.pub.pem

I realize the OP asked about converting a public key, so this doesn't quite answer the question, however I thought it would be useful to some anyway.

Note also that this command results in a PEM public key format, which is generally what OpenSSL expects. The answer by Brian, on the other hand, results in a file in RSAPublicKey format, which is not the normal format expected by OpenSSL (though later versions can apparently read it via the -RSAPublicKey_in flag). To convert you can do this:

openssl rsa -RSAPublicKey_in -in id_rsa.rsapub.pem -pubout -out id_rsa.pub.pem
shawkinaw
  • 480
  • Thanks, the -pubout from the private key did the trick for me. – Shaun Dewberry Oct 26 '16 at 10:26
  • openssl rsa -in id_rsa.pem -pubout -out id_rsa.pub.pem also work (i.e. input is pem format private key). Good answer. – Johnny Wong Dec 21 '17 at 10:20
  • 1
    Update: Brian's answer has been corrected to -m pkcs8 which in spite of OpenSSH folks using the wrong name does produce X.509 'PUBKEY'. Also, since OpenSSH 6.5 in 2014-01 if the creator specified 'new format' -o for better security, this method won't work, and since 7.8 in 2018-08 'new format' is now the default, ditto. – dave_thompson_085 May 31 '19 at 06:06
  • 1
    One liners: openssl rsa -RSAPublicKey_in -in <(ssh-keygen -e -m pem -f id_rsa.pub) > id_rsa.pub.pem or ssh-keygen -e -m pem -f id_rsa.pub | openssl rsa -RSAPublicKey_in > id_rsa.pub.pem – Bruce Mar 06 '20 at 02:07
30

The format you want is what ssh-keygen calls PKCS8. So the following command will produce the desired output:

ssh-keygen -f key.pub -e -m pkcs8

From the ssh-keygen man page:

-m key_format
         Specify a key format for the -i (import) or -e (export) conversion 
         options.  The supported key formats are: 
         ``RFC4716'' (RFC 4716/SSH2 public or private key), 
         ``PKCS8'' (PEM PKCS8 public key) or 
         ``PEM'' (PEM public key).  
         The default conversion format is ``RFC4716''.
slm
  • 369,824
7

Similar to Amal Chaudhuri's method below, this is what worked for me. I needed to create a pem file from the ssh public key I'd generated for my SFTP client (Cyberduck).

openssl rsa -in ~/.ssh/id_rsa -outform pem > id_rsa.pem
l3e0wu1f
  • 103
0
ssh-keygen -f path/to/id_rsa.pub -e -m pem > path/to/rsa.pem

Here's what each part of the command does:

-f path/to/id_rsa.pub: Specifies the input file, the path to your existing OpenSSH public key file (id_rsa.pub).

-e -m pem: Specifies the format conversion to PEM.

">" path/to/rsa.pem: Redirects the output to a file named rsa.pem in the specified directory (path/to/).

ssh-keygen -f id_rsa.pub -e -m pem > yourfilename.pem 
-2

Another way to do this from another site. Posting this in case you need another method. Works very well. http://www.chatur.com.np/2011/01/convert-openssh-rsa-key-to-pem-format.html

openssl dsa -in ~/.ssh/id_dsa -outform pem > id_dsa.pem
Thor
  • 17,182