An SSH public keyserver

I spent a few nights working on a web site recently — it’s a public OpenSSH keyserver, in the style of the OpenPGP keyservers, and it’s up now. I’d like to attempt to persuade you all to consider uploading your public SSH keys to http://sshkeys.net/, for a few reasons:

  • If you publish your public key, it’s going to be easy for people setting up accounts for you in the future to find it, with a simple wget sshkeys.net/you@yourdomain.com.

  • If you manage machines, having your potential users upload keys to the site should save your time by making sure they get past problems like uploading the wrong file, since the site will tell them if they try to upload anything other than a public key.

  • There should be side benefits of having a large repository of SSH public keys: I think we would have detected the recent Debian/OpenSSL randomness bug sooner if we’d been on the lookout for unexpected duplicate keys, for example.

I used Django for the site and it was shockingly effortless, to the point where I didn’t have to write any SQL or interact with the database manually. I wrote the following model, which says that there are Addresses, Keys, and combinations of Address and Key that have some extra fields like whether they’ve been verified against the supplied e-mail address or not:

class Address (models.Model):
    address = models.CharField(max_length=255)
    def __unicode__(self):
        return self.address

class SSHKey (models.Model):
    owners = models.ManyToManyField(Address, through='AddressKey')
    keytext = models.CharField(max_length=1024)
    def __unicode__(self):
        return self.keytext

class AddressKey:
    address = models.ForeignKey(Address)
    sshkey = models.ForeignKey(SSHKey)
    date_added = models.DateTimeField('date added')
    verified = models.BooleanField(default=False)
    token = models.CharField(max_length=40)
    token_sent = models.DateTimeField()

After that, it all just worked. The gap between having it all working in the Admin interface (time taken: 3 hours) and having it all working with production views was much larger, though. The Admin interface is full of beautiful widgets that are not at all re-usable in your production site.

The full code’s available over at github (under AGPLv3). I’d be very happy to get patches to make it smarter, and let me know if you find any bugs. Thanks!

Comments

  1. On the other hand, if it makes it probably easier to find weak keys/username if there’s a vulnerability like the debian openssl disaster.

    Reply
  2. The Admin interface is full of beautiful widgets that are not at all re-usable in your production site.

    Which version of Django are you using? My understanding is that the changes in 1.0 to the admin implementation and the newforms stuff make it much easier to reuse their swanky elements in your own views.

    Reply
  3. Hi Chris

    While I encourage your project, what immediately comes to mind is this:

    How does one establish trust? The PGP keysystem is just a key distribution point, and signatures on the key from other trusted keys indicate whether or not I can trust a PGP key received from a keyserver or any other source.

    SSH does not have such an equivalent. While this project is great to *locate* SSH keys, a sysadmin ought not to take a key from this place and simply add it to authorized_keys without verifying that it really belongs to its owner. In such a case, if the sysadmin verifies the key by talking to its owner, the sysadmin can directly receive the key from the owner. OTOH, PGP works here because the trust is proved by the signatures.

    Perhaps you could allow people to leave detached PGP signatures for the SSH keys.

    All the best with it and I hope it succeeds 🙂

    Reply
  4. Launchpad already allows users to upload their SSH keys. These keys are uploaded and accessed via HTTPS, which helps make sure they aren’t tampered with in transition.

    That said, it’s cool you could get something up and running so quickly.

    Reply
  5. Two ideas:

    1) replace the comment field with the email address used to publish the key; imagine I pull a key for jdoe@example.com and the key says johnd@localhost – how am I supposed to tell who is who then? 😉

    2) allow pgp signatures either as detached files or (would it be possible?) as ascii-armored text in key’s comment field

    Reply
  6. Strongly agreed with Patrys: you should make it easy to attach PGP signatures in some manner. IMO, the easiest way would be to provide a command for people to run (“gpg -o – –clearsign ~/.ssh/id_rsa.pub”) with a way to paste that in. Make use of one of the best trust networks that are available!

    Reply
  7. Interesting concept. I like that you were able to build a Django site in this manner so quickly. To the power of Python!

    On a more serious note, as others have echoed, the trust model is lacking in SSH keys. Also, what happens when I have multiple public SSH keys?

    Reply
  8. Hi, thanks for all the comments.

    Regarding trust, I agree that it’s lacking at the moment — adding support for GPG-signing keys as suggested sounds pretty good. Of course, if you’re at all worried then you should check fingerprints with the person whose key you’re pulling.

    I think the e-mail confirmation step is a good start, though, and stops you from pretending to be someone else quite adequately. The remaining trust issue is that you have to trust *me* and that you’re actually reaching my machine (if you’re unwilling to check fingerprints, at least).

    Fortunately, installing an SSH key and asking someone to try to log in with it is a good way to tell whether you were given the right key or not..

    Reply
  9. Hi,

    > Also, what happens when I have multiple public SSH keys?

    It just works. You’ll get multiple e-mails asking you to authenticate each key, and each key only goes live once you reply to the mails. If you then wget an address, it will return each matching key on a different line, as authorized_keys does.

    (You can see how the model side of this works by looking at the code I pasted.)

    Reply
  10. > Of course, if you’re at all worried then you should check fingerprints with the person whose key you’re pulling.

    Which is pretty much exactly as hard as getting the key directly from them in the first place, right?

    > The remaining trust issue is that you have to trust *me*

    So, why exactly would I trust you? What steps do you take to ensure that the key really belongs to the person it is claimed to belong to?

    Reply
  11. > What steps do you take to ensure that the key really belongs to the person it is claimed to belong to?

    As explained on the site, I mail a confirmation token to the e-mail address that a key is proposed to be associated with, and I only accept the address-key pair if the link in the confirmation mail is followed.

    Reply
  12. The HTTP URL in the article is showing a slight variation on the theme noticed by Gabriel (in comment #2, above):

    I’m now seeing the “502 Proxy Error” theme. I like the way it draws my attention to the important part “Could not connect to remote machine: Connection refused”.

    The glorious simplicity and lack of visual clutter is just as impressive, though.

    Reply
  13. I agree that you need a trust model, and PGP is probably the way to go – people have done interesting-looking things with PGP in a few other arenas you might want to look at – http://usefulinc.com/foaf/signingFoafFiles and http://konfidi.org/wiki (http://config.fsf.org/trac/public/ticket/5 for more FOAF links 🙂

    I think that if you use https and become a semi-trusted 3rd party yourself (or get someone who is to use your code), there are some interesting possibilities – for example perhaps you could crawl in some form the various ssh key repositories, and then give people personalized ssh key pages that would be useful both for themselves in others (eg a web page with a listing like “according to foo.com and bar.org, user person@example.com and ssh public key ID X, but baz.net thinks person@example.com has ssh public key ID Y” – see also http://www.biglumber.com/

    If you published this information using FOAF RDF, perhaps it’s even something that could become part of people’s FOAF records / viewable via the new generation of FOAF search engines – eg another section at a page like my qdos search result page

    If DNSSEC ever catches on you could also reuse the data via “Using DNS to Securely Publish Secure Shell (SSH) Key Fingerprints” – http://www.ietf.org/rfc/rfc4255.txt

    The other possibility that springs to mind for me is to integrate this with http://bcfg2.org/wiki/Plugins/SSHbase (and any other software that manages ssh keys like it I don’t know of) – to get an entire organization’s public keys synced up with the server automatically.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *