jeroen / openssl

OpenSSL bindings for R
Other
63 stars 20 forks source link

Keys generated by rsa_keygen/write_pem cannot be read by ssh-add in old version of ssh #47

Closed richfitz closed 7 years ago

richfitz commented 7 years ago

Perhaps this is not meant to work, or perhaps it's (another!) different format, but:

I would like to, using the openssl package, generate an ssh key that could be readable by ssh-add. With the current versions of rsa_keygen and write_pem that is not possible (it's also possible that this should not be a pem format - I don't know - but that's the only format that permitted a password).

This is what I have done:

path <- tempfile()
dir.create(path)
dest_key <- file.path(path, "id_rsa")
dest_pub <- file.path(path, "id_rsa.pub")

password <- "secret"

key <- openssl::rsa_keygen()
pubkey <- as.list(key)$pubkey

openssl::write_ssh(pubkey, dest_pub)
openssl::write_pem(key, dest_key, password = password)

So far so good. This keypair can be read with openssl::read_key and openssl::read_pubkey.

If I run ssh-add I first get an error indicating that the permissions on the written file are too lax:

dyn1158-191:file6b3e535ee350 rich$ ssh-add id_rsa
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for 'id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.

That's easily solved with Sys.chmod(dest_key, "600"). After that, I still cannot load the key:

dyn1158-191:file6b3e535ee350 rich$ ssh-add id_rsa
Enter passphrase for id_rsa: 
Bad passphrase, try again for id_rsa: 
Bad passphrase, try again for id_rsa: 
Bad passphrase, try again for id_rsa: 

If I create a key without a password I am still prompted by ssh-add for one.

I have an Yosemite 10.10.4 system which reports a very old version of ssh:

dyn1158-191:file6b3e535ee350 rich$ ssh -V
OpenSSH_6.2p2, OSSLShim 0.9.8r 8 Dec 2011

In a more recent version of ssh on linux (OpenSSH_7.2p2) I can load the key. In both versions though the header generated by the openssl package differs. It contains

-----BEGIN ENCRYPTED PRIVATE KEY-----

but my ~/.ssh/id_rsa starts with

Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,4922...
jeroen commented 7 years ago

On OSX 10.12 this all seems to work as well.

So you're saying that openssl::write_pem(key) generates an -----BEGIN ENCRYPTED PRIVATE KEY----- even when you do if password = NULL ?

Normally it should only generate an encrypted PEM file when you supply a password argument.

richfitz commented 7 years ago

sorry - just with a password do we get -----BEGIN PRIVATE KEY----- in the header. But that's different to what I see in ~/.ssh/id_rsa

richfitz commented 7 years ago

And I noticed I'd missed the password = password arg from the code above so have added it

jeroen commented 7 years ago

I'm confused now what you're trying to do.

The write_ssh() does not set a password, it's just the pubkey. You can only set a PEM password when exporting a private key with write_pem(key, password = password). That will result in a pem file which has BEGIN ENCRYPTED PRIVATE KEY in the header. If you do not set a password it should generate a BEGIN PRIVATE KEY.

I'm not sure what the relation is between ~/.ssh/id_rsa and ssh-add? Or do you mean you copied the file dest_key above to ~/.ssh/id_rsa?

Here is a simplified version, so does this not work for you?

key <- openssl::rsa_keygen()
tmp <- tempfile()
openssl::write_pem(key, tmp)
Sys.chmod(tmp, "400")
system2("ssh-add", tmp)
jeroen commented 7 years ago

Maybe your ~/.ssh/id_rsa is in some legacy format. How did you generate it? Is your ~/.ssh/id_rsa file readable by openssl?

openssl::read_key("~/.ssh/id_rsa")
richfitz commented 7 years ago

Sorry - what I am trying to do is enable someone to generate a password protected ssh key, even if they don't have ssh itself installed (realistically just windows users) without shelling out to ssh-keygen. I want to make sure that whatever key is generated can later be used with ssh/ssh-add if they did install ssh. I'm not actually using ssh-add in R code - it's just an example.

If I run your code I get prompted for a password by ssh-add so the key being generated does not make ssh-add happy

I generated the key originally with ssh-keygen when I set this laptop up (24 July 2015 from the look of it). It looks like the version of ssh-keygen I have still generates keys in this format with headers like:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,3022FBCFFB99AB5E78F8A6BB9668E6F4

openssl::read_key reads the key just fine. Here's an example with a password secret that I just generated (not my real key).

private:

-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,3022FBCFFB99AB5E78F8A6BB9668E6F4

tCHcZ/yFOuea4TtMPnyVGFAEpUoDFtB8a+aPoGe+/H6xpvdjMGKpkLW3cI4hbgvt
vu/Way8GgUf9z21bOWLkInkQaCIlXKpiCLN+C/YM/JQG1L3z1IZZ08lw6PYcBxwX
mihIm0p+9ZOloJe2qcsp7PviyFDDu3pzREDw+Jtmzpi/I2i91ubcqbWEln36ZrD5
GS6PcdShwq1E/sJUHOErYgpLv5nvzs5TpZzO8LeL2EvpYf1oy1cg9ibkjvmiqItw
uKYvkocNDVCdxPnMihxW32TaED17THQazucCokTaRNTbZtm1UFkZqCLKybgL/Xpk
Ap499/+/iKWctoAD+Xl/REb3U0sO778CVY0AqdGI8NtV/PjoxVcramDrqRkLbf1u
gqeH0t+py2o2Fm6Z+l72eAYeDIopnxt4F4X9d8Pn43qViNHCEKrTW4DMQ6iXm+Gt
F16BMKy5BuvINd8lbNnNRFHhnIASTCViYmuS8kbWEwSrlgmwlGQafHG+8qatuiGZ
1HGD01NdBLxcZNDKlHSIgOyNo5TzwBJjsLBRbkGZcMvbhCZePQIqIU2XMYTVOTKk
g2tJnVO2cN+JYY+NDSwl2FdQOLdXn+Z2LVwTyVUrjg9yuMtA5Dp9xLZvnUtRblTE
CpU/PN2pEy5NRpPNXi2zdEZPQ3zkoaQtinNAnPp/Hb07D9dfHwewqWonb24KI7CH
qVyub2/phnyaskRNRQSTcFRFsN+7z2UC8TAKYKSfabszXz/zWqcNwaaCVio0m8fm
Mqx1vUBEqJ3osgF1tAtVyRFZ6W9t2L7KFNRrgMLTpraBzEtrWl//+XQZX5D4NRO9
jPeq1DyHUpQQMMjTpmHRErHjI3MQESFVdSGUeqrhDB3o38WrBU4V23IkcEvOg4KE
qsYLBYi0g998eXs4gwmb3S0ORUdIyE+82Pf7Xu9q5UpLb3PnbagehiDLcOOLOMHl
utSEDpscsQND9Pv3bEsu34KDTash6HxgxOPESlETsx91GzfSu4zPVy9vcx49LKyl
8Ug7j2yxY+aRsh56cLiBTTrWrT6ti6AKA5BbcqBS90rqK1BRn4u0NwrDLF5SujkZ
v3OuS02n78Meo4QIuLMK5JUZsilaAAUERiV3voAdfvp0I5qx4HR1NmH34FNj1dnx
kiGVdMgITQj3ylNVT1pt9mR4urzLLvC7uzOA1s7GbaTgk9kavTG7HamNCc13Dnzl
3HQs4y8zzFfieAp74fSalJsav69idO/V5nobVhMfN+jHY3Y7lBKMGZrRb8jq0dTJ
qYccrprh5dyT0R//2HNpgwIJeuP+nj8fn+jVdqWr0XwxrA6zkve80dIFXKP5hqfY
xXe5MmuAHb67lCIYC3ykDYnp8h+Baf//vVPBrko9QV6b0k9CmnYikRwfC3Sybj3R
CuiCSljrrWQKThElIYhr9AEB/8Ld07GvxK6QpAoIavU+LMS09hmPpEp5cI0SgQeK
QEoCDHFU/aRdYkvc5+nvBrWlaEacwy5NFPkEZqwPm9NEnYCn+EnrB/s7HJoPtrPu
hsMEoVt3Ow3xhBH/KuldLs8MAPYOD9dyRBWnuofqZ0Vst+E5ebxFIbsRkj+475dt
-----END RSA PRIVATE KEY-----

public:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIEglJLM17Qia4CK+DpNULdMHllMQl93+zICn1a0RIIhW24pCfeMijuRaPijRGVKxO+YjYMv87Rqyrqcb8trzyy4AWrWikoizQJ67KtKMuZxFgAx+i4qMnv+AfulBMr0lfNwLPdf0P/YDg9vlPtdxm9uUPYUtZTM/nEkHw8DaiN+Nshhiq4DM3ILrDNcbm+6oE0u8EQlj+eBA2bpmlkqIkEU4nlHvz2Xx4UjOlaxGN8EcNrZvODuLMw05nzPLoZcBJ7GMbWIrEcMr2Q98Sk/VXMN7g0N3TCl5jLRnXGj3hKf93IKvbYzZ5woaRw1+lZJ4lOW0SvCF0kGJ+QfUyMsuP rich@dyn1158-191.insecure.ic.ac.uk
jeroen commented 7 years ago

The problem might be the same as https://github.com/jeroen/openssl/issues/43. Perhaps your version of openssh still uses the PKCS#1 format. Nowadays everything uses PKCS#8 which looks very similar but is internally a different format.

Some relevant C code: https://github.com/jeroen/openssl/blob/master/src/pem.c#L79-L106

The openssl R package deliberately does not have an option to export keys to PKCS#1 because that format is deprecated and won't work anymore with many modern tools. Unfortunately some old versions of osx might still have openssh built against openssl 0.9.8 which defaults to PKCS#1.

Is there a way you can test if the problem appears on older linux disributions (trusty, centos6, etc)? Because if that is not the case I would recommend to stick with the new PKCS#8 format and upgrade your macbook :)

richfitz commented 7 years ago

It looks like the key generated by your package can be read by openssl on trusty (OpenSSH_6.6.1p1 Ubuntu-2ubuntu2.8, OpenSSL 1.0.1f 6 Jan 2014)

Yes, it looks like I should upgrade my laptop. Just waiting for a time where less will break during upgrade than by not upgrading...

jeroen commented 7 years ago

Afaik all linux distros' have updated openssl to at least 1.0.1 after heartbleed so I think all should work even on ubuntu precise or centos 6.

Recent versions of MacOS use apple's native crypto APIs instead of openssl, and therefore apple has stopped updating openssl and it will be removed eventually. Unfortunately it seems that on your system ssh has still been built against the legacy openssl version.

Would you mind testing if the problem disappears if you upgrade openssh:

brew install openssh
richfitz commented 7 years ago

I have updated my OS and this problem has gone away - it must just be a really old version of ssh.

Given that R is basically dropping support for that version of OSX I don't think this is worth your time. Thanks for looking into it for me

jeroen commented 7 years ago

OK perfect. The problem is not the version of ssh but the version of openssl that it was linked to :)

jeroen commented 6 years ago

For future reference: the latest release of the openssl package adds a new function write_pkcs1() for if you really need to write keys to the legacy SSH format.

It is much recommended to use write_pem() instead which writes keys into the standard pkcs8 format. The pkcs8 format supports all key types (rsa, dsa, ec), passphrase encryption, and always starts with:

-----BEGIN PRIVATE KEY-----

PKCS8 is the standard format almost everywhere nowadays.

However some old ssh clients indeed assume the legacy pkcs1 format for id_rsa keys. The PKCS1 format can only be used for RSA keys (not EC or DSA) and start with:

-----BEGIN RSA PRIVATE KEY-----

The write_pkcs1 function can be used to write either private or public keys.