75

If I use the following

openssl req -x509  -days 365 -newkey rsa:2048 -keyout private.pem -out public.pem -nodes

I get private.pem and public.pem

If I use

ssh-keygen -t rsa -f rsa

I get rsa and rsa.pub

Is it possible to convert from the format of rsa to private.pem and vice-a-versa?

Edit: To be more specific,

a) If I have the private.pem and public.pem generated by the above command, how do I get the equivalent rsa private key and public key?

b) Given the rsa and rsa.pub, how do I get the x509 keys if I do know the additional metadata that the above openssl command takes in?

If I go from the openssh format to x509 and back, I should ideally get the same key file back.

3

6 Answers 6

50

You are missing a bit here.

ssh-keygen can be used to convert public keys from SSH formats in to PEM formats suitable for OpenSSL. Private keys are normally already stored in a PEM format suitable for both.

However, the OpenSSL command you show generates a self-signed certificate. This certificate is not something OpenSSH traditionally uses for anything - and it definitely is not the same thing as a public key only.

OpenSSH does have support for certificates as well, but it is likely that you are not using this support. Also, these certificates are not X.509, so they are incompatible with OpenSSL.

The certificate contains information that is not present anywhere else and each certificate is unique and can not be recreated at will. This means that you need to store the X.509 certificate, in addition to the private key, if you wish use the same key for both OpenSSL and OpenSSH.


If you just want to share the private key, the OpenSSL key generated by your example command is stored in private.pem, and it should already be in PEM format compatible with (recent) OpenSSH. To extract an OpenSSH compatible public key from it, you can just run:

ssh-keygen -f private.pem -y > private.pub

If you want to start from OpenSSH and work your way over to the OpenSSL side, with a self-signed certificate (for whatever reason), here's how:

$ ssh-keygen -f test-user
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in test-user.
Your public key has been saved in test-user.pub.
The key fingerprint is:
ff:36:f1:74:c7:0d:4e:da:79:5c:96:27:2c:2c:4e:b6 naked@tink
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|           . .  .|
|          + o =.+|
|        S+ o * B+|
|         .E o = B|
|          .  + o.|
|           .o .  |
|           ...   |
+-----------------+
$ openssl req -x509 -days 365 -new -key test-user -out test-user-cert.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:
$ ls -l test-user*
-rw------- 1 naked naked 1675 Mar 18 21:52 test-user
-rw-r--r-- 1 naked naked 1229 Mar 18 21:53 test-user-cert.pem
-rw-r--r-- 1 naked naked  392 Mar 18 21:52 test-user.pub

From these, both test-user and test-user-cert.pem files are critical to preserve, where as test-user.pub can always be recreated from test-user as needed.

6
  • Thanks! That helped clarify things quite a bit. Can I use the ssh keys to self sign and generate this cert?
    – anshul
    Commented Mar 18, 2013 at 12:57
  • You can, the private key is already in a compatible format so you can just use that in the OpenSSL command.
    – Nakedible
    Commented Mar 18, 2013 at 13:16
  • Could you please explain how would I use that private key in the openssl command? I tried reading the man but didn't get anywhere.
    – anshul
    Commented Mar 18, 2013 at 15:26
  • I did, although I am beginning to doubt this will actually be useful for you - if you are still wishing for ideal back-and-forth conversion without losing data, that is just not a meaningful goal.
    – Nakedible
    Commented Mar 18, 2013 at 19:58
  • This probably is the most complete answer I could have hoped for. Thanks a lot!
    – anshul
    Commented Mar 18, 2013 at 20:49
42

The ssh-keygen tool from openssh can do this for you.

The following command will convert the .pub file into the pem format for you.

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

The ssh-keygen also supports conversion into various other formats, for more information, see the man page.

3
  • 6
    This only works for rsa keys, not for dsa, ecdsa or ed25519. Commented Oct 29, 2015 at 13:22
  • 6
    When I tried this I found that -m pem did not give an openssl compatible key but -m PKCS8 did. Commented Dec 16, 2015 at 17:34
  • @PeterGreen+ what OpenSSH calls -m pem is supported by OpenSSL library but not by most openssl commandline operations. In 1.0.0 (2010) up commandline rsa -RSAPublicKey_in reads it and can convert to the 'SPKI' (aka PUBKEY) format used by most other operations -- but the wrongly-named ssh-keygen -e -m pkcs8 does that already. Commented Jul 9, 2019 at 4:49
12

Newer versions of OpenSSL (>= 1.0.1 at least) use PKCS#8 format for keys.

So, if you extract publick key from certificate using command

openssl x509 -in certificate.pem -noout -pubkey >pubkey.pem

You need to use following command to convert it to authorized_keys entry

ssh-keygen -i -m PKCS8 -f pubkey.pem

-out option of the req command of OpenSSL produces certificate request rather than public key.

To extract public key in the PKCS#8 format, understandable by import function of ssh-keygen use following command.

openssl req -in public.pem -noout -pubkey
1
  • 4
    What ssh-keygen -m calls PKCS8 is actually the SubjectPublicKeyInfo format from X.509, which OpenSSL has used for public keys forever. The actual PKCS8 standard format is for private keys only, and OpenSSL has long used both PKCS8 and 'legacy' formats for private keys, using the name pkcs8 correctly for PKCS8, although 1.0.0 in 2010 shifted some commandline operations from legacy to PKCS8 thus bringing it to the attention of people who hadn't noticed before. Commented Oct 23, 2016 at 7:47
5

A 2048-bit public RSA key can be converted from X.509 PEM format to OpenSSH format with the following commands (cf. answer). It would not be difficult to write conversion in the other direction given information from the linked answer.

echo -n "ssh-rsa " > rsa2048.pub
grep -v -- ----- rsa2048.pem | base64 -d | dd bs=1 skip=32 count=257 status=none | xxd -p -c257 | sed s/^/00000007\ 7373682d727361\ 00000003\ 010001\ 00000101\ / | xxd -p -r | base64 -w0 >> rsa2048.pub
echo >> rsa2048.pub
4

I couldn't find a tool for the job, so I got my hands dirty and wrote a few by hand by reading through the OpenSSH source code and some online PEM/DER debuggers.

I wrote it to convert between PKCS8, PKCS1 (RSA-only), SEC1 (ECDSA-only) and the "proprietary" OpenSSH format for RSA keys of any size and ECDSA P-256 and P-384.

Install

It's written for node.js (and I'm working on porting that to the browser), so you have to install that first:

And then:

npm install -g rasha eckles ssh-to-jwk jwk-to-ssh

Rasha is for RSA, Eckles is for ECDSA.

PEM to OpenSSH

RSA

rasha privkey.pem > privkey.jwk.json

jwk-to-ssh privkey.jwk.json root@localhost > id_rsa

jwk-to-ssh privkey.jwk.json root@localhost public > id_rsa.pub

ECDSA

eckles privkey.pem > privkey.jwk.json

jwk-to-ssh privkey.jwk.json root@localhost > id_ecdsa

jwk-to-ssh privkey.jwk.json root@localhost public > id_ecdsa.pub

OpenSSH to PEM

RSA

ssh-to-jwk id_rsa > privkey.jwk.json

rasha privkey.jwk.json > privkey.pem

rasha privkey.jwk.json public > pubkey.pem

ECDSA

ssh-to-jwk id_ecdsa > privkey.jwk.json

eckles privkey.jwk.json > privkey.pem

eckles privkey.jwk.json public > pubkey.pem
1
  • Existing RSA OpenSSH can be converted to PEM via serverfault.com/a/950686. I have not tried ECDSA.
    – Andy
    Commented Aug 12, 2019 at 9:16
2

I managed to use windows tool puttygen.exe for this:

enter image description here

So:

  1. Load your private key into puttygen (answer passphrase challenge)
  2. Once loaded, select as in image above Conversions -> Export OpenSSH key give it a name and it should work, it just worked for me.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .