I have a network that is only accessible through bastion servers over ssh. In it, I am developing web applications that are exposed to end users via GUI's served up over websockets. All traffic into and out of the network travels through an SSH tunnel from whatever service host, through the bastion, to the end user's machine.

So, traffic from the network's boundary to the end client is already encrypted. And, I already have a system setup for associating end users with SSH-RSA key pairs that are rotated periodically.

So, here's my crazy idea:

On any web app in the network that requires user authentication, have the end user provide their username on the network, as well as their public key. Have the web app's authentication service verify that this public key is indeed already associated with the end user in the network's keystore, then generate a challenge using the key. Client side, the end user decrypts the challenge using their private key and presents the end result to the server for authentication.

Here's the kicker: a load of services in this network are implemented in JavaScript on NodeJS. Because NodeJS can call system services, I can offload the work of generating challenges using public keys to a more traditional process. But, client side, I might need to decrypt the challenge in-browser using the private key.

Getting the private key into the browser is easy enough. Whether or not loading the private key into a browser is even a good idea is another question, entirely.

But, more specifically:

  1. Are there any blazing "Oh, don't do that!" security flaws in the setup summarized above?
  2. What are a few standard packages used in Linux for generating challenges using an RSA public key?
  3. Does anyone know of a good package for decrypting messages using a public RSA key implemented in JavaScript?
  • "...and presents the end result to the server for authentication", how do they do that? What are your security goals? Mutual authentication, client-side authentication only? What is your threat model? Do you want to protect the clients from a malicious server? Server from malicious clients? Etc.
    – mikeazo
    Jul 24, 2015 at 14:58
  • You should definitely read What's wrong with in-browser cryptography? and Javascript Cryptography Considered Harmful
    – mikeazo
    Jul 24, 2015 at 15:00
  • By transmitting the now clear text challenge phrase to the server via websockets, tunneled through an SSH connection. Security goals: authenticate the user. What's a threat model? No. No. etc. Jul 24, 2015 at 15:01
  • Have read it. My thinking is that the runtime isn't vulnerable because it is delivered to the client over an SSH tunnel. Jul 24, 2015 at 15:03
  • I won't be generating random numbers in the browser. Keys are generated the usual way, using traditional methods for setting up users on ssh servers. Jul 24, 2015 at 15:08

1 Answer 1

  1. Are there any blazing "Oh, don't do that!" security flaws in the setup summarized above?

The basic protocol you are proposing is: client identifies themselves, server checks the public key and verifies that they are a valid user, server encrypts a challenge using the public key, client decrypts to get the challenge back and returns it as proof of knowing the private key.

I don't see any blazing issues. It may be better to follow what SSH itself does for public key authentication as shown in RFC 4252, section 7. There, they have the client sign something with the private key that the server can then verify. Always good to stick with standards.

  1. What are a few standard packages used in Linux for generating challenges using an RSA public key?

If you have openssl, I'd do this openssl rand -base64 16 (or possibly 32 bytes).

Otherwise, you can use /dev/random (or possibly /dev/urandom if absolutely necessary). Something like this head -c 16 /dev/random | base64. See this for more details

  1. Does anyone know of a good package for decrypting messages using a public private RSA key implemented in JavaScript?

A number of these libraries support RSA. Not sure how good they are and how easy it will be to transform the SSH private key into something they can use.

This answer is a summary of our chat

  • 1
    Considering how vulnerable browsers are to XSS attacks, I'm hesitant to use client-signed messages for authentication. Anyone who has the signed message outbound from the client effectively has the ability to impersonate the end user. I suppose this could also be said of the response half of a server-generated challenge-response, though. Jul 24, 2015 at 18:13
  • @GoFYerPedantry if an attacker can inject javascript, and the private key is loaded into the javascript memory, they can also get it. That to me is a bigger concern since then they could establish the SSH connection. But you did say you weren't worried about protecting the server from malicious clients :)
    – mikeazo
    Jul 24, 2015 at 18:20
  • More to the point, I said I didn't like the idea of exposing the private key to the browser. :) Jul 24, 2015 at 18:23
  • @GoFYerPedantry, true, true. Another possibly cool option would be to have the ssh connection (in addition to establishing the tunnel) return a one-time-use auth token for the user. Not sure how that would be passed to the browser, though.
    – mikeazo
    Jul 24, 2015 at 18:30
  • I guess a keypoint is--how many permissions does a key buy the person wielding it? The client needs to transmit some identifying thing to the server--whether it be a traditional password, response to a challenge, client-generated signature, and so on. As long as that thing is changed frequently, hard to brute force and follows the principle of least permissions, we've done the best we can. ...right? :/ Jul 24, 2015 at 18:31

You must log in to answer this question.

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