[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[1] 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 feature. 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 signs it. 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[2]. 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.] rubygems.org could: 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. [1] http://docs.rubygems.org/read/chapter/21 [2] https://keyserver.pgp.com/vkd/GetWelcomeScreen.event -- Grant "I am gravely disappointed. Again you have made me unleash my dogs of war." _______________________________________________ Rubygems-developers mailing list http://rubyforge.org/projects/rubygems Rubygems-developers@rubyforge.org http://rubyforge.org/mailman/listinfo/rubygems-developers