Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ECC SSH keygen for cloud provisioning #2051

Open
ryscheng opened this issue Nov 12, 2015 · 16 comments
Open

ECC SSH keygen for cloud provisioning #2051

ryscheng opened this issue Nov 12, 2015 · 16 comments

Comments

@ryscheng
Copy link
Member

Currently used for SSH keygen. We can just use SSH2, which we use elsewhere.

@agallant
Copy link
Collaborator

Are we sure that SSH2 can generate keypairs? If I'm looking at the right documentation (https://github.com/mscdex/ssh2-streams) it looks like it can load/parse existing private/public keys and optionally generate a public key based on a loaded private key.

@trevj
Copy link
Contributor

trevj commented Jan 25, 2016

@agallant agallant changed the title Remove forge in uproxy-lib/src/cloud/provision ECC SSH keygen for cloud provisioning Jan 26, 2016
@agallant
Copy link
Collaborator

I think the main goal is shorter keys, and since SSH2 may not help I'll start checking out other possibilities. One that caught my eye - https://github.com/jaredly/ssh-keypair

Nice simple wrapper around ssh-keygen, currently doesn't seem to support much configuration, but would be easy enough for us to tweak.

@trevj
Copy link
Contributor

trevj commented Jan 26, 2016

Agreed! Closing this other issue, since these two are equivalent:
#2160

@agallant
Copy link
Collaborator

So I tweaked that package - https://github.com/soycode/ssh-keypair

It works (assuming your system ssh-keygen supports ecdsa type, which is true on Ubuntu 14.04 but false on OSX 10.10), and looks something like this:

ssh_keygen = require('ssh-keypair');
ssh_keygen('User <email>',
                    function(err, priv, pub) { /* do stuff with keys */ },
                    { type: 'ecdsa', path: 'keypath' });

Note that the path parameter is optional, and if specified means that the priv/pub variables will not be populated in the callback and instead the key will be written to the filesystem.

Anyway, as I said it does work and seems straightforward, and gives lovely short keys with ecdsa. I'll see if the maintainer of ssh-keypair is interested in merging this (it does change the API a bit to specify the type option), else we can fork and use if desired.

@trevj
Copy link
Contributor

trevj commented Jan 26, 2016

So, that looks like a wrapper around the ssh-keygen command line utility. That looks fine for node but since uProxy runs in the browser I don't see it's going to invoke the utility.

I think the probem, rather than key generation, is establishing an SSH connection with an ECC key. That's the missing piece in ssh2:
mscdex/ssh2#352

@agallant
Copy link
Collaborator

Gotcha, well it looks like there isn't any particular alternative to ssh2 so hopefully we can get that to support it. As you said key generation is unlikely to be an issue, but in any case here's a pure node solution for it - https://www.npmjs.com/package/sshpk

@trevj
Copy link
Contributor

trevj commented Mar 1, 2016

Seems like there has been some progress on this in ssh2-streams!:
mscdex/ssh2-streams#3 (comment)

@trevj
Copy link
Contributor

trevj commented Mar 9, 2016

There's been a bunch of commits, e.g.:
mscdex/ssh2-streams@8aee5df

I tested this node: spun up an SSH server, generated some keys, and manually symlink-ed in the latest ssh2-streams but wasn't able to succesfully login:

Error: error:0606B06E:digital envelope routines:EVP_SignFinal:wrong public key type
    at Error (native)
    at Sign.sign (crypto.js:280:26)
    at /usr/local/google/home/trevj/src/ecdsa/node_modules/ssh2/lib/client.js:431:31
    at SSH2Stream.authPK (/usr/local/google/home/trevj/src/ssh2-streams/lib/ssh.js:1574:3)
    at SSH2Stream.onUSERAUTH_PK_OK (/usr/local/google/home/trevj/src/ecdsa/node_modules/ssh2/lib/client.js:424:14)
    at SSH2Stream.g (events.js:261:16)
    at emitNone (events.js:68:13)
    at SSH2Stream.emit (events.js:167:7)
    at parse_USERAUTH (/usr/local/google/home/trevj/src/ssh2-streams/lib/ssh.js:4130:12)
    at parsePacket (/usr/local/google/home/trevj/src/ssh2-streams/lib/ssh.js:3847:12)

@trevj
Copy link
Contributor

trevj commented Mar 9, 2016

For my own reference, how to test this stuff:

docker run -ti -P 7000:22 ubuntu:latest /bin/bash

apt-get update && apt-get install -y openssh-server
/etc/init.d/ssh start

ssh-keygen -t ecdsa -b 256
cat ~/.ssh/id_ecdsa.pub >> ~/.ssh/authorized_keys
base64 -w 0 ~/.ssh/id_ecdsa ; echo

ssh bob@localhost -p 7000

@agallant
Copy link
Collaborator

Just to add my notes - I've been investigating, trying to get it working within uproxy/uproxy-lib, no success yet unfortunately. Whatever additional ecdsa support ssh2-streams has added may not be as simple as "just upgrade the package and it works" - also, we are depending more directly on ssh2 than ssh2-streams, so there may be something through that step as well.

Will continue looking into it - on the plus side, when I generated invite URLs w/ecdsa the length came out to <500 characters. So, it'll be nice once it works at least!

@agallant
Copy link
Collaborator

It looks like several recent releases of ssh2/ssh2-streams were cut, I'll give another look to see if we can get this working.

@agallant
Copy link
Collaborator

Still not quite "just working", but not clear why. I'm going to focus on other more obviously tractable issues, but revisit this some to add logging and try to figure it out.

@trevj
Copy link
Contributor

trevj commented Sep 28, 2016

Our choices for shorter keys are ECDSA and Ed25519:
http://man.openbsd.org/OpenBSD-current/man1/ssh-keygen.1

It seems we should prefer the latter, i.e. Ed25519:
https://wiki.archlinux.org/index.php/SSH_keys

mkdir ~/ecc
cd ~/ecc
ssh-keygen -t ed25519 -N '' -f id_ed25519
ssh-keygen -t ecdsa -N '' -f id_ecdsa

In another window:

docker run --rm -p 7000:22 -ti -v ~/ecc:/ecc ubuntu:xenial
apt-get update && apt-get install -y openssh-server && service ssh start
mkdir ~/.ssh
cat /ecc/id_ed25519.pub /ecc/id_ecdsa.pub >> ~/.ssh/authorized_keys

Save this to ~/ecc/login.js (adapted from https://github.com/mscdex/ssh2):

var Client = require('ssh2').Client;

var conn = new Client();
conn.on('ready', function() {
  console.log('Client :: ready');
  conn.exec('uptime', function(err, stream) {
    if (err) throw err;
    stream.on('close', function(code, signal) {
      console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
      conn.end();
    }).on('data', function(data) {
      console.log('STDOUT: ' + data);
    }).stderr.on('data', function(data) {
      console.log('STDERR: ' + data);
    });
  });
}).connect({
  host: '172.17.0.1',
  port: 7000,
  username: 'root',
  privateKey: require('fs').readFileSync('id_ed25519') // CHANGE THIS FOR ECDSA
});

Test it in Node.js like so:

docker run --rm -ti -v `pwd`:/worker -w /worker mhart/alpine-node:4 node login.js

At the time of writing, only ECDSA keys are supported and even they are only supported by Node 6+.

Now...what about current versions of browserify?

@bemasc
Copy link
Contributor

bemasc commented Sep 28, 2016

FWIW, we already use ECDSA for all our PGP needs via e2e and WebCrypto.

@trevj
Copy link
Contributor

trevj commented Sep 28, 2016

To issue an ECDSA-based cloud server invite:

  • SSH into your cloud server
  • edit /issue_invite.sh:
    • find the ssh-keygen line and change -t rsa to read -t ecdsa
  • issue a new invite with docker exec uproxy-sshd /issue_invite.sh

Right now, you'll see a message in the logs:

cloud social [2016-09-28T20:47:05.867Z] failed to log into cloud server during invite accept: Cannot parse privateKey: EC private keys are not supported in this version of node

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants