[Rubygems-developers] Proposal for signing gems
kgo at grant-olson.net
Thu May 26 17:03:34 EDT 2011
[Round 2. Looks like the list server doesn't like PGP/Mime mails.
Apologies if this shows up as a dupe.]
I was lucky enough to get to RailsConf this year and I saw Nick's
presentation. While thinking about gems and looking at the internal
layout, it occurred to me that gems aren't signed and that
I've never actually verified a gem. This opens us up to the possibility
of downloading and installing a malicious gem posing as a legitimate one.
I chatted with Nick for a minute after the presentation. He mentioned
that there is some signing functionality built-in, but no one uses it,
no one knows if it's designed properly, and it'd be nice to see that change.
I took a look at the existing signing functionality. The docs
indicate that it uses X509 certificates. With all due respect to the
author of the signing code, I don't think this is the best choice.
Also, when I attempt to run the command to build an X509 cert in ruby
1.9.2, the command failed.
I'd really like to see signed gems, and I'm willing to do the work, but
I wanted to run my design by people first and see if we can reach a
consensus, rather than writing the code and finding out no one wants the
Any and all questions and comments are appreciated.
We should sign gems with gpg
I don't think X509 signatures are the way to go. I think we should use
OpenPGP signatures instead.
1. Self-signed X509 certificates are basically worthless. There's no
easy way to verify that the key is legitimate. OpenPGP certificates are
designed to be generated by you, and then signed by other people to
validate their authenticity.
2. Setting up an X509 CA will take some resources. OpenPGP already has
a dedicated pool of servers run by volunteers at pool.sks-keyservers.net.
3. The current generation policy isn't so good. Your private key isn't
encrypted. It's a strange file in a strange location that could easily
be lost. In gpg, all files are stored in ~/.gnupg. Private keys are
encrypted by default.
4. gpg has better tooling and documentation than openssl. There are
plenty of things like Seahorse or GPA to examine your keys. Policies
are documented and explained.
5. gpg allows the user to decide their default threat model and key
verification model. X509 assumes you trust the powers that be.
6. The OpenPGP certificate will (optionally) be tied to the owner's real
life id, if (for example) they sign release emails, use git's signing
functionality on release tags, sign binary releases. This makes it
easier to verify that the key isn't forged. (See trust model 3 below.)
The way I envision it, a gem maintainer would generate and publish a key
with gpg if they didn't already have one. He would put the key id in
the gem configuration file. When he builds the gem, gpg kicks in and
An end user who wants to verify the key runs a command after fetching
the gem. If they have the key, we run gpg and verify the signature. If
not, we provide the key id so they can download it manually with gpg.
The code to implement this should be pretty simple.
Authenticating keys / Certificate authority
With gpg, the user can determine their trust model.
1. The current model. The user doesn't care. They don't check gpg
sigs. All is well. I imagine this will still be the model used by a
strong majority of users.
2. The user uses the OpenPGP web of trust. To be honest, this is a
PITA. It involves getting into the strong set by meeting people in
person and exchanging key fingerprints to make sure that there's no
man-in-the-middle attack. And even if the user is in the strong set,
there's no guarantee the gem maintainer is.
3. Continuity model. I downloaded the signing key for Ubuntu about four
releases ago. Even though I haven't done full verification, there
haven't been any reports of problems, and the next three releases were
signed by the same key. If the key changed and gpg couldn't verify the
next Ubuntu release, it would raise some eyebrows. You can use the same
philosophy with gems.
4. Simulated CA. Similar to the way a distributed source control system
can be used as a centralized system, the OpenPGP web of trust can be
setup to act as if there's a certificate authority.
For an example of option 4, look at the PGP Corp Global Directory.
You go to the website and submit your public key. It sends you an email
that you need to reply to. If you reply, signs your key and
publishes the information. If another user trusts the Global Directory
key, they will now trust your key.
Technically, this is subject to a man-in-the-middle attack. But it's
the same policy that gets used when I forget my password at something
like Amazon. And Amazon has my credit card info. I think the
procedure is valid against all but the most exotic attacks as long as
its limitations are known and documented.
[For conciseness' sake, I'm just going to pretend we've agreed that
rubygems.org is the CA. It could of course be another service, but I
think it makes sense to do all this in a centralized place. Right now
I'm more concerned with presenting the model.]
1. Allow gem publisher to upload a private key from their account page.
2. Upon receipt of key, send an email to the gem publisher's email
containing an encrypted token.
3. The gem publisher decrypts the token,
4. The gem publisher posts the decrypted token onto a form at the
website and submits. This establishes the gem publisher has control of
(a) the email address, and (b) the OpenPGP key. (Excluding a possible
mitm at the network level.)
5. rubygems.org signs the key with it's own signing key, possibly with a
6 month or 1 year expiration date.
6. The new signature is submitted to the keyservers at
pool.sks-keyservers.net, making the verification available world-wide.
Now an unrelated gem user can configure gpg to trust the rubygems
signing key. When they download the gem from above and retrieve the gem
publisher's key, they will see that the key is valid because it's
trusted by rubygems. If it's not trusted, it's up to User B to
investigate and determine if they trust the gem or not.
Note that the relationship between these keys isn't contained in the
gem. It's contained on the keyservers. If another website or mirror
provides the same gem with the same signature, it will still show up as
valid, assuming the gem user trusts the rubygems.org signing key.
In the year 2013
Assuming all goes well, most people are signing their gems, and the
community likes the feature, we could configure a keyring for use by
gems only, similar to the way apt-get maintains its own keyring.
This keyring would automatically include the rubygems.org signing key on
installation. When downloading a new gem, verification will happen
automatically. If the key isn't on the gem keyring it will be
downloaded automatically. If the key isn't trusted, the user will
receive a warning and asked if they want to continue. If the signature
check fails, the gem will not be installed.
"I am gravely disappointed. Again you have made me unleash my dogs of war."
More information about the Rubygems-developers