diff --git a/security.md b/security.md index 83330214..c766c683 100644 --- a/security.md +++ b/security.md @@ -28,10 +28,11 @@ optionally lets you set a security policy, and you can verify the signing key for a gem before you install it. However, this method of securing gems is not widely used. It requires a number -of manual steps on the part of the developer, and there is no well-established -chain of trust for gem signing keys. Discussion of new signing models using -X509 or OpenPGP is going on in the [rubygems-trust -wiki](https://github.com/rubygems-trust/rubygems.org/wiki/_pages) and +of [manual steps on the part of the developer](#building_gems), and there is no +well-established chain of trust for gem signing keys. Discussion of new signing models such as +X509 and OpenPGP is going on in the [rubygems-trust +wiki](https://github.com/rubygems-trust/rubygems.org/wiki/_pages), the +[RubyGems-Developers list](https://groups.google.com/d/msg/rubygems-developers/lnnGTlfsuYo/TLDcJ2RPSDoJ) and in [IRC](irc://chat.freenode.net/#rubygems-trust). The goal is to improve (or replace) the signing system so that it is easy for authors and transparent for users. @@ -39,29 +40,96 @@ users. Using Gems ------- -* Install with a trust policy. +Install with a trust policy. * `gem install gemname -P HighSecurity`: All dependent gems must be signed and verified. * `gem install gemname -P MediumSecurity`: All signed dependent gems must be verified. * `bundle --trust-policy MediumSecurity`: Same as above, except Bundler only recognizes the long `--trust-policy` flag, not the short `-P`. -* Risks of being pwned, as described by [Benjamin Smith's Hacking with Gems talk](http://lanyrd.com/2013/rulu/scgxzr/) + * *Caveat*: Gem certificates are trusted globally, such that adding a cert.pem for one gem automatically trusts + all gems signed by that cert. + +Verify the checksum, if available + + gem fetch gemname -v version + ruby -rdigest/sha2 -e "puts Digest::SHA512.new.hexdigest(File.read('gemname-version.gem')) + +Know the risks of being pwned, as described by [Benjamin Smith's Hacking with Gems talk](http://lanyrd.com/2013/rulu/scgxzr/) Building Gems ------- -* Official: `gem cert` +### Sign with: `gem cert` + +1) Create self-signed gem cert + + cd ~/.ssh + gem cert --build your@email.com + chmod 600 gem-p* + +- use the email address you specify in your gemspecs + +2) Configure gemspec with cert + +Add cert public key to your repository + + cd /path/to/your/gem + mkdir certs + cp ~/.ssh/gem-public_cert.pem certs/yourhandle.pem + git add certs/yourhandle.pem + +Add cert paths to your gemspec + + s.cert_chain = ['certs/yourhandle.pem'] + s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/ + +3) Add your own cert to your approved list, just like anyone else + + gem cert --add certs/yourhandle.pem + +4) Build gem and test that you can install it + + gem build gemname.gemspec + gem install gemname-version.gem -P HighSecurity + # or -P MediumSecurity if your gem depends on unsigned gems + +5) Example text for installation documentation + +> MetricFu is cryptographically signed. To be sure the gem you install hasn't been tampered with: +> +> Add my public key (if you haven't already) as a trusted certificate +> +> `gem cert --add <(curl -Ls https://raw.github.com/metricfu/metric_fu/master/certs/bf4.pem)` +> +> `gem install metric_fu -P MediumSecurity` +> +> The MediumSecurity trust profile will verify signed gems, but allow the installation of unsigned dependencies. +> +> This is necessary because not all of MetricFu's dependencies are signed, so we cannot use HighSecurity. + +------- + +### Include checksum of released gems in your repository - * [How to cryptographically sign your RubyGem](http://www.benjaminfleischer.com/2013/11/08/how-to-sign-your-rubygem-cert/) - Step-by-step guide + require 'digest/sha2' + built_gem_path = 'pkg/gemname-version.gem' + checksum = Digest::SHA512.new.hexdigest(File.read(built_gem_path)) + checksum_path = 'checksum/gemname-version.gem.sha512' + File.open(checksum_path, 'w' ) {|f| f.write(checksum) } + # add and commit 'checksum_path' + +------- -* Alternative: [Rubygems OpenPGP signing](https://web.archive.org/web/20130914152133/http://www.rubygems-openpgp-ca.org/), [gem](https://github.com/grant-olson/rubygems-openpgp) +### Not Recommended: OpenPGP signing is [not recommended due to lack of support](http://www.rubygems-openpgp-ca.org/blog/nobody-cares-about-signed-gems.html). - * For example, see the [ruby-lint gem](https://github.com/YorickPeterse/ruby-lint/blob/0858d8f841/README.md#security) +For details, see discussion [with Grant Olson](https://github.com/grant-olson/rubygems-openpgp/issues/34#issuecomment-29016709) and +[Yorick Peterse](https://github.com/rubygems/guides/pull/70#issuecomment-29007487). Credits ------- Several sources were used for content for this guide: +* [How to cryptographically sign your RubyGem](http://www.benjaminfleischer.com/2013/11/08/how-to-sign-your-rubygem-cert/) - Step-by-step guide * [Signing rubygems - Pasteable instructions](http://developer.zendesk.com/blog/2013/02/03/signing-gems/) * [Twitter gem gemspec](https://github.com/sferik/twitter/blob/master/twitter.gemspec) * [RubyGems Trust Model Overview](https://github.com/rubygems-trust/rubygems.org/wiki/Overview), [doc](http://goo.gl/ybFIO)