I’ve posted a followup to this article that discusses ssh-agent.
For reasons best left to another post, I wanted to convert an SSH public key into a PKCS#1 PEM-encoded public key. That is, I wanted to go from this:
Traditionally SSH uses RSA for keys (as seen above), which is what you'll likely see on your Macbook. However, it's quite likely that when you're connecting to a Linux server running a newer version of OpenSSH you'll get a message about an ECDSA fingerprint the first time you connect. SSH keys provide the same level of access as user names and passwords, and typically to privileged accounts with operating system access. It is common that there are 10 times as many SSH keys as there are passwords. Yet SSH keys have been ignored in most identity and access management projects. Assuming you have the SSH private key idrsa, you can extract the public key from it like so. Openssl rsa -in idrsa -pubout -out idrsa.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.
To this:
So you just a have to rename your OpenSSL key: cp myid.key idrsa. In OpenSSL, there is no specific file for public key (public keys are generally embeded in certificates). However, you extract public key from private key file: ssh-keygen -y -f myid.key idrsa.pub. GnuPG to OpenSSH. 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.
If you have a recent version of OpenSSH (where recent means 5.6 or later), you can just do this:
If you don’t have that, read on.
The OpenSSH public key format is fully documented RFC 4253. Briefly, an OpenSSH public key consists of three fields:
- The key type
- A chunk of PEM-encoded data
- A comment
What, you may ask, is PEM encoding? Privacy Enhanced Mail (PEM) is a specific type of Base64 encoding…which is to say it is a way of representing binary data using only printable ASCII characters.
For an ssh-rsa key, the PEM-encoded data is a series of (length, data) pairs. The length is encoded as four octets (in big-endian order). The values encoded are:
- algorithm name (one of (ssh-rsa, ssh-dsa)). This duplicates the key type in the first field of the public key.
- RSA exponent
- RSA modulus
For more information on how RSA works and what the exponent and modulus are used for, read the Wikipedia article on RSA.
We can read this in with the following Python code:
This leaves us with an array that, for an RSA key, will look like:
We need to convert the character buffers currently holding e (the exponent) and n (the modulus) into numeric types. There may be better ways to do this, but this works:
We now have the RSA public key. The next step is to produce the appropriate output format.
Our target format is a PEM-encoded PKCS#1 public key.
PKCS#1 is “the first of a family of standards called Public-Key Cryptography Standards (PKCS), published by RSA Laboratories.” (Wikipedia). You can identify a PKCS#1 PEM-encoded public key by the markers used to delimit the base64 encoded data:
This is different from an x.509 public key, which looks like this:
The x.509 format may be used to store keys generated using algorithms other than RSA.
The data in a PKCS#1 key is encoded using DER, which is a set of rules for serializing ASN.1 data. For more information see:
- The WikiPedia entry for Distinguished Encoding Rules
Basically, ASN.1 is a standard for describing abstract data types, and DER is a set of rules for transforming an ASN.1 data type into a series of octets.
According to the ASN module for PKCS#1, a PKCS#1 public key looks like this:
We can generate this from our key data using Python’s PyASN1 module:
Now that we have the DER encoded key, generating the output is easy:
Whereas the OpenSSH public key format is effectively “proprietary” (that is, the format is used only by OpenSSH), the private key is already stored as a PKCS#1 private key. This means that the private key can be manipulated using the OpenSSL command line tools.
The clever folks among you may be wondering if, assuming we have the private key available, we could have skipped this whole exercise and simply extracted the public key in the correct format using the openssl command. We can come very close…the following demonstrates how to extract the public key from the private key using openssl:
So close! But this is in x.509 format, and even though the OpenSSL library supports PKCS#1 encoding, there is no mechanism to make the command line tools cough up this format.
Additionally, I am trying for a solution that does not require the private key to be available, which means that in any case I will still have to parse the OpenSSH public key format.
This article is (probably too much of) an overview of the subject matter, but take heart:it will lead you down the right path, or so we hope. :)
My goal here is to provide a space to disambiguate and provide some vocabularythat will increase your understanding and make your googling easier.
The files that we're talking about are the ones that look like this:
- SSH
id_rsa
id_ecdsa
*.pub
- OpenSSL (has lots of different names for the same thing)
priv.key
pubkey.pem
key.der
example.com.crt
cert.pem
If you're looking specifically for info on SSH Public Keys, zoom ahead to this:
Private Keys (Both)
Update: OpenSSH has now added it's own 'proprietary' key format,which is described in the next section. This section is about the standard keyformats, which do work for OpenSSH.
Both
ssh-keygen
(OpenSSH) and openssl
(OpenSSL, duh) can generate private keysin standard DER/ASN.1 (x.509) formats.Typically (as in every case as far as I'm aware), it's one of the following:
- PKCS#1 (for RSA only, supported in OpenSSH and OpenSSL)
- RSA Only
- OpenSSH & OpenSSL
- SEC1
- EC (ECDSA) Only
- OpenSSH & OpenSSL
- PKCS#8 (for RSA, EC(DSA), and others, supported in OpenSSL.. not new standard for either)
- RSA, EC (ECDSA), and others
- OpenSSL (not sure about OpenSSH)
That's true for WebCrypto (and node crypto) as well - except that WebCryptoalso supports JWK.
There are also various libraries likeRasha.js (RSA tools for JavaScript) andEckles.js (ECDSA tools for JavaScript),both of which I worte, that support JWK as well.
Anyway, the PEM files look like this for both:
For formats that don't embed the key type in the actual data you'll alsosee headers like
-----BEGIN RSA PRIVATE KEY-----
and -----BEGIN EC PRIVATE KEY-----
(and the corresponding footers).ECDSA keys are often referred to simply as
EC
(it's one of those 'PIN number' /'DVD video' type things where the 'DSA' descriptior is redundant much of the time).OpenSSH Private Keys
Traditionally OpenSSH supports PKCS#1 for RSA and SEC1 for EC,which have
RSA PRIVATE KEY
and EC PRIVATE KEY
, respectively,in their PEM type string.Now it its own 'proprietary' (open source, but non-standard) formatfor storing private keys (
id_rsa
, id_ecdsa
), which compliment theRFC-standardized ssh public key format.Qualifications include basic reading, writing and math skills. Knowledge of liquor brands, beer, wine, champagne, non-alcoholic beverages, designated glassware, preparation methods and garnishments. Formal bartending training preferred. You must meet state legal age requirements. Speakeasy Bartenders/Mixologist (Formally Nightingales Bartenders) is a mobile event staffing company. We specialize in Mixology and Event Services. Speakeasy provides quality bartenders, servers to private and public events around the Metro D.C. Area, Northern VA, and Maryland. About Us Original and awesome since 2009 the Black Market Bar + Grill started out off the beaten path of 280 and never looked back. Proudly backing our motto of 'Fantastic Food, Cold Drinks & Evil Bartenders' our selections for dinner, lunch and brunch on Sunday are nothing short of amazing. All set in our eclectic atmosphere of comic book, b-movie and punk rock decor. Hecate's familiar, though only appears in human form. Wears black sleeve band on both arms. The bartender appears many times in the street opposite the red witch, he holds up a picture of her then runs into the alley leaving confused townspeople to rush to look at the picture. A bit before the. Speakeasy bartender in action.
Although still PEM-encoded, you can tell when a key is in the custom OpenSSHformat by the
OPENSSH PRIVATE KEY
indicator.The new key files looks like this:
Despite looking like it they don't actually contain DER-encoded x.509/ASN.1keys and they're not OpenSSL compatible.
Note that they begin with
b3BlbnNzaC1rZXktdjE
which, when base64-decoded,reads openssh-key-v1
.If you'd like to learn the specifics of the format,take a look at this:
I wasn't able to find any documentation on the format whatsoever,so I think the above documentation I made from reading the sourceand reverse engineering valid keys is the best the web has to offer at present.
Public Keys (Both)
The one thing that you should know about public keys is that, in many casesthey can be derived from the private parts of the private key (but not theother way around, obviously) and the private key typically contains the publicparts embedded into it.
Thus a 'private' key is actually a full key pair.
This is nice because it keeps code complexity down for applications that don't implementcrypto themselves, but use libraries that just need the right parts. For example, myVanillaJS libs that convert between keypair formats don't need to depend onBig Intlibraries, so they remain small and manageable.
SSH naming conventions
SSH doesn't use extensions for its private keys, but they're always PEM (as shown above).
By default they're named either
id_rsa
or id_ecdsa
,depending on the suite of the cryptography used (RSA or EC).There are some other suffixes for outdated crypto standards(and perhaps newer ones if this article is really old by the time you read it),but we won't go into those here.
Public keys end in
.pub
and they're their own special format.SSH Public keys (.pub
)
SSH Public keys have their own special format. In short, they look like this:
If you'd like to learn more about that (
id_rsa.pub
, id_ecdsa.pub
, etc),this should both whet your whistle and quench your thirst:And you may also enjoySSH Fingerprints Explained.
The OpenSSL smorgasbord
Create Ssh Key Openssl
Oh man.. people just name OpenSSL keys anything.
The conventions are plentiful and kinda inconsistent.However, they're mostly used for either HTTPS or application-levelcryptography and a couple of common themes have emerged:
privkey.pem
key.pem
example.com.key
priv.key
key.der
Since Let's Encrypt it's become more popular to name the private key
privkey.pem
,and I'm a big fan of that convention (and, as such, I've made it the default forGreenlock.js).OpenSSL Public Keys
Openssl Ssh Key Generate
If you're actually using OpenSSL for SSL (now known as TLS),you don't really have the concept of a 'public key' as such.It's not its own thing per say.
When you create a Certificate Signing Request (CSR), which liststhe domains you intend to secure you must supply your private keythe tool doing the signing.
It will then extract the public key and embed it in the CSR,which is signed, returned to you, and later verified by your web browseragainst your private key.
That file is usually named something like this:
csr.pem
(the intermediary before you get a cert)cert.pem
(Let's Encrypt convention)fullchain.pem
(when including authority chains)example.com.crt
example.com.pem
(sidenote: if you're interested in how I reverse-engineered CSRto create small libraries to handle it instead of the typicallyHUGE ones, I talk a little bit inCSR, My Old Friendand ASN.1 for Dummies,which is maybe too light on the direct subject but hopefully at leastentertaining)
OpenSSL Public Keys Reprise
In the non-ssl cases where you're actually using raw public keysthey look like this:
Again I'll reference ASN.1 for Dummiesif you're interested to know what all that gobbledygook means.
I don't know what the most common conventions are for these public keys,since they're largely application specific but I like to call mine
pubkey.pem
,sometimes with something extra to designate the type, like pubkey-ec-p256.pem
.OpenSSL private keys are typicallyA file in
id_rsa
or id_ecdsa
(without the .pub
) is the private key.SSH Private keys (
id_rsa
) are stored in one of the standard OpenSSL formats.RSA vs EC / ECDSA
If the suject of the differences between RSA and EC piques your(and you found the format of this article and my wirting style tobe palatable enough), I'll suggest something else with which tochase this all down:
By AJ ONeal
Thanks! It's really motivating to know that people like you are benefiting from what I'm doing and want more of it. :)
Did I make your day?
Generate Ssh Key Openssl
(you can learn about the bigger picture I'm working towards on my patreon page )