Skip to content

Commit

Permalink
Merge pull request #70 from bf4/security_details
Browse files Browse the repository at this point in the history
Expand gem security build/install instructions; add checksum; recommend against OpenPGP
  • Loading branch information
bf4 committed Nov 21, 2013
2 parents beddd0b + bb47d31 commit e63a922
Showing 1 changed file with 78 additions and 10 deletions.
88 changes: 78 additions & 10 deletions security.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,40 +28,108 @@ 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:https://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.

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:https://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:https://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 [email protected]
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:https://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:https://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:https://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:https://www.benjaminfleischer.com/2013/11/08/how-to-sign-your-rubygem-cert/) - Step-by-step guide
* [Signing rubygems - Pasteable instructions](http:https://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:https://goo.gl/ybFIO)
Expand Down

0 comments on commit e63a922

Please sign in to comment.