Keypairs
Applications often need to have a public/private keypair so sign messages. This gem manages your application level key pairs with automatic rotation and support for encoding and decoding JWTs.
Note: This gem is intended to work within Rails applications. It can probably be adjusted easily to also work for non-rails / sinatra project but that's out of scope for now.
Installation
-
Add gem
Add this line to your application's Gemfile:
gem 'keypairs'
The of course run
bundle install
. -
Copy migration
The default migration file can be copied to your app with:
bundle exec rails keypairs:install:migrations
Then of course run
bundle exec rails db:migrate
-
Setup encryption key
The private keys are encrypted with the lockbox gem. In order for this to work, you need to set the master key as described in the readme, but the easiest thing is to set the environment variable
LOCKBOX_MASTER_KEY
to a sufficient long string (you can generate one withLockbox.generate_key
).
Usage
The central point of this gem is the Keypair
model which is backed by the keypairs
table. If you need to sign messages, you can get the current keypair with the Keypair.current
method. This method performs the rotation of the keypairs if required.
You can access the private an public key of the keypair (OpenSSL::PKey::RSA
) and encrypt and decrypt messages with them:
encoded_message = Keypair.current.private_key.private_decrypt('foobar')
Keypair.current.public_key.public_decrypt(encoded_message)
# => 'foobar'
JWT support
You can encode and decode JWTs directly on the class:
payload = { foo: 'bar' }
id_token = Keypair.jwt_encode(payload)
decoded = Keypair.jwt_decode(id_token)
It's almost always a good idea to add a subject to your payload and pass the same subject during decoding. That way you know that users don't use a key for other purposes (for example a key intended for an OAuth2 flow used as a session key). So for example:
subject = 'MyAppSession'
payload = { foo: 'bar', subject: subject }
id_token = Keypair.jwt_encode(payload)
decoded = Keypair.jwt_decode(id_token, subject: subject)
Exposing public keys
If you want others to validate your messages based on the public keys, you can share the JWK version of you current keys by adding them to your config/routes.rb
:
get :jwks, to: Keypairs::PublicKeysController.action(:index)
Releasing new version
Publishing a new version is handled by the publish workflow. This workflow publishes a GitHub release to rubygems and GitHub package registry with the version defined in the release.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/Drieam/keypairs.
License
The gem is available as open source under the terms of the MIT License.