Skip to content

RSpec matchers for testing OpenPGP messages

License

Notifications You must be signed in to change notification settings

riboseinc/rspec-pgp_matchers

Repository files navigation

RSpec::PGPMatchers

Gem Version Build Status Test Coverage Code Climate

RSpec matchers for testing PGP-encrypted messages, and signatures.

Caution
This gem is not meant to bridge GnuPG executables to production environments. Use it in developments and tests only.
Important
This gem calls GnuPG executables internally. However, it does not rely on machine-readable interface yet, and may easily break when they change something in GnuPG’s human-readable output. As long as it is not resolved in a better way, we are going to maintain compatibility with the most recent versions of GnuPG. At the moment of writing this statement, it is GnuPG 2.2.9.
Tip
In order to check which GnuPG version this gem was tested against, check out builds in Travis. One of the build steps in a "before script" phase executes gpg --version to make things clear.

Usage

Getting started

  1. Make sure that you have GnuPG 2.2 installed.

  2. Add this line to your application’s Gemfile:

    gem "rspec-pgp_matchers", github: "riboseinc/rspec-pgp_matchers", require: false, group: :test
  3. And following to your spec helper:

    require "rspec/pgp_matchers"
    RSpec::PGPMatchers.homedir = "path/to/pgp_home_directory/with/development/keys"

Matching signatures

text = "Some text"
signer_uid = "[email protected]"
someones_uid = "[email protected]"

# Not defined in this gem, but required for this example
signature = sign_text(text: text, signer: signer_uid, ascii_armor: true)

# Both following do pass
expect(signature).to be_a_valid_pgp_signature_of(text)
expect(signature).to be_a_valid_pgp_signature_of(text).signed_by(signer_uid)

# This one fails
expect(signature).to be_a_valid_pgp_signature_of(text).signed_by(someones_uid)

Matching encrypted messages

text = "Some text"
recipient1_uid = "[email protected]"
recipient2_uid = "[email protected]"
someones_uid = "[email protected]"

# Not defined in this gem, but required for this example
encrypted = encrypt_text(
  text: text,
  recipients: [recipient1_uid, recipient2_uid],
  ascii_armor: true
)

# Following do pass
expect(encrypted).to be_a_pgp_encrypted_message
expect(encrypted).to be_a_pgp_encrypted_message.containing(text)
expect(encrypted).to be_a_pgp_encrypted_message.encrypted_for(recipient1_uid, recipient2_uid)

# This one fails
expect(encrypted).to be_a_pgp_encrypted_message.encrypted_for(someones_uid)

Running arbitrary GnuPG commands

An RSpec::PGPMatchers::GPGRunner module can be used to run arbitrary GnuPG commands:

RSpec::PGPMatchers::GPGRunner.run_command("--decrypt PATH_TO_FILE")
RSpec::PGPMatchers::GPGRunner.run_command("--list-keys")

Also, convenient helpers are defined for two common commands:

RSpec::PGPMatchers::GPGRunner.run_decrypt("encrypted_string")
RSpec::PGPMatchers::GPGRunner.run_verify("cleartext", "signature_string")

In all above cases, a triple consisting of captured standard output, captured standard error, and Process::Status instance is returned.

Working with passphrase-protected keys

Consider using unprotected keys in your tests. It will save you a lot of hassle. However, passphrase-protected keys are also supported. See PROTECTED_KEYS.adoc for details.

Unusual GnuPG executable name

By default, this gem assumes that GnuPG executable is named gpg, and that it is in $PATH. This behaviour can be changed, for example:

RSpec::PGPMatchers.gpg_executable = "gpg2" # different executable name
RSpec::PGPMatchers.gpg_executable = "/opt/gpg/bin/gpg" # absolute path
RSpec::PGPMatchers.gpg_executable = "../gpg/bin/gpg" # relative path

Avoid hardcoding values. Usually, setting a proper $PATH environment variable is better than assigning an absolute path to gpg_executable attribute.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Submodules

GnuPG is installed via scripts maintained in a sister repository riboseinc/gpg-build-scripts, and included here as a Git submodule. Learn more about submodules from The GitHub Blog.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/riboseinc/rspec-pgp_matchers.

Credits

This gem is developed, maintained and funded by Ribose Inc.

License

The gem is available as open source under the terms of the MIT License.