rspec-pgp_matchers 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c1ede8d3cd2fbc6cea19ba3d0c1dbce8cf0b390239869beec38fe4f6da3e607b
4
- data.tar.gz: 6b090779819012e1697e460e78a41cc85d4eaa1687e24441a136f268ebc29c61
3
+ metadata.gz: 4715837cead4425a9b36c7f7b722d5d64c0910e0987a8ea1c8b56b5c06ef1372
4
+ data.tar.gz: 713c60d3e6196483f586ec1026eec5b3a4d05155e3540f8207bb24ad116ed711
5
5
  SHA512:
6
- metadata.gz: f30291f6f0f4eb68a1e3d42e5bdab7208722f4998a0d8e0c17edae16e903fb031864c94005c816aca76b8b52ad6b22b8b240c23708302f94f17220a34517f9be
7
- data.tar.gz: 9e49089ab7d42085d1ac94d6807a83408010ba4c17665cb70040b12febb41f301f43cdd4d630f1c463450fdf7028bc7663064d2a78ad351c6bb0a052ee92d3db
6
+ metadata.gz: ec96116566ec3b4bded4fd3b78566ae567a4d6d69fce22b9b9d8627f4767ffde79b729613e185f4bbb9f10df91e8422df7a7e19ba2255d96ea098ef5d96f0faa
7
+ data.tar.gz: 8e6d0397bbe146ec9804074a3455a5cb51f3e2cb60eae25f0464748d6c5a1e92a7e9fb83d431afa22907e34e4a940fe1d8f03aba18852752254d434f3028e0c7
@@ -1,12 +1,11 @@
1
- dist: trusty
1
+ dist: bionic
2
2
  language: ruby
3
- sudo: true
4
3
 
5
4
  rvm:
6
- - "2.3"
7
- - "2.4"
8
- - "2.5"
9
5
  - "2.6"
6
+ - "2.5"
7
+ - "2.4"
8
+ - "2.3"
10
9
  - "ruby-head"
11
10
 
12
11
  env:
@@ -0,0 +1,4 @@
1
+ -
2
+ README.adoc
3
+ LICENSE.txt
4
+ PROTECTED_KEYS.adoc
@@ -0,0 +1,99 @@
1
+ = Working with passphrase-protected keys
2
+
3
+ It is recommended not to use passphrase-protected keys with this gem.
4
+ Remember, `RSpec::PGPMatchers` are meant for testing, therefore there is
5
+ no security trade-off involved. Nevertheless, passphrase-protected keys are
6
+ supported as well. With some hassle, though…
7
+
8
+ IMPORTANT: This guide was written for GnuPG 2.2. Other versions may require
9
+ a different set of configuration options.
10
+
11
+ == Passing the passphrase in gpg.conf
12
+
13
+ This is the easier option, however it will work only if you use the same
14
+ passphrase for all the keys.
15
+
16
+ 1. Write GnuPG options to a config file located at `<pgp/home/path>/gpg.conf`:
17
+ +
18
+ ----
19
+ yes
20
+ batch
21
+ no-tty
22
+ use-agent
23
+ pinentry-mode loopback
24
+ passphrase <passphrase>
25
+ ----
26
+
27
+ 2. Write GnuPG Agent options to a config file located at
28
+ `<pgp/home/path>/gpg-agent.conf`:
29
+ +
30
+ ----
31
+ allow-loopback-pinentry
32
+ ----
33
+
34
+ 3. If GnuPG Agent was running, reload it to pick the updated configuration:
35
+ +
36
+ ----
37
+ gpgconf --homedir <pgp/home/path> --reload gpg-agent
38
+ ----
39
+
40
+ == Passphrase presetting
41
+
42
+ This is the recommended and more comprehensive solution, though also bit more
43
+ complicated.
44
+
45
+ 1. Write GnuPG options to a config file located at `<pgp/home/path>/gpg.conf`:
46
+ +
47
+ ----
48
+ yes
49
+ batch
50
+ no-tty
51
+ use-agent
52
+ ----
53
+
54
+ 2. Write GnuPG Agent options to a config file located at
55
+ `<pgp/home/path>/gpg-agent.conf`:
56
+ +
57
+ ----
58
+ allow-preset-passphrase
59
+ ----
60
+
61
+ 3. If GnuPG Agent was running, reload it to pick the updated configuration:
62
+ +
63
+ ----
64
+ gpgconf --homedir <pgp/home/path> --reload gpg-agent
65
+ ----
66
+
67
+ 4. Obtain keygrips of password-protected keys you want to use:
68
+ +
69
+ ----
70
+ gpg --homedir <pgp/home/path> --list-keys --with-keygrip
71
+ ----
72
+ +
73
+ Note that sometimes you will need a subkey's keygrip rather than primary key's
74
+ one. Subkeys are typically used for message encryption, but can be used for
75
+ signing as well.
76
+
77
+ 5. Preset passwords for keys:
78
+ +
79
+ ----
80
+ gpg-preset-passphrase --homedir <pgp/home/path> --preset --passphrase <passphrase> <keygrip>
81
+ ----
82
+ +
83
+ or (will read passphrase from standard input):
84
+ +
85
+ ----
86
+ gpg-preset-passphrase --homedir <pgp/home/path> --preset <keygrip>
87
+ ----
88
+ +
89
+ Note that `gpg-preset-passphrase` is not in `PATH` on some systems.
90
+ For instance, when GnuPG is installed on MacOS via Homebrew, it is located at
91
+ `/usr/local/opt/gnupg/libexec`, which is not in `PATH` by default.
92
+
93
+ == Resources
94
+
95
+ * The GNU Privacy Guard Manual:
96
+ ** https://gnupg.org/documentation/manuals/gnupg/GPG-Options.html#GPG-Options[GPG options]
97
+ ** https://gnupg.org/documentation/manuals/gnupg/Agent-Options.html#Agent-Options[GPG Agent options]
98
+ ** https://www.gnupg.org/documentation/manuals/gnupg/gpg_002dpreset_002dpassphrase.html#gpg_002dpreset_002dpassphrase[GPG Preset Passphrase tool]
99
+ * "link:https://wincent.com/wiki/Using_gpg-agent_on_OS_X[Using gpg-agent on OS X]" on wincent.com -- main source of inspiration for above writing
@@ -1,5 +1,7 @@
1
1
  = RSpec::PGPMatchers
2
2
 
3
+ ifdef::env-yard[:relfileprefix: file.]
4
+
3
5
  image:https://img.shields.io/gem/v/rspec-pgp_matchers.svg[
4
6
  Gem Version, link="https://rubygems.org/gems/rspec-pgp_matchers"]
5
7
  image:https://img.shields.io/travis/riboseinc/rspec-pgp_matchers/master.svg[
@@ -111,6 +113,27 @@ RSpec::PGPMatchers::GPGRunner.run_verify("cleartext", "signature_string")
111
113
  In all above cases, a triple consisting of captured standard output, captured
112
114
  standard error, and `Process::Status` instance is returned.
113
115
 
116
+ === Working with passphrase-protected keys
117
+
118
+ Consider using unprotected keys in your tests. It will save you a lot of
119
+ hassle. However, passphrase-protected keys are also supported. See
120
+ `<<PROTECTED_KEYS.adoc#,PROTECTED_KEYS.adoc>>` for details.
121
+
122
+ === Unusual GnuPG executable name
123
+
124
+ By default, this gem assumes that GnuPG executable is named `gpg`, and that
125
+ it is in `$PATH`. This behaviour can be changed, for example:
126
+
127
+ [source,ruby]
128
+ ----
129
+ RSpec::PGPMatchers.gpg_executable = "gpg2" # different executable name
130
+ RSpec::PGPMatchers.gpg_executable = "/opt/gpg/bin/gpg" # absolute path
131
+ RSpec::PGPMatchers.gpg_executable = "../gpg/bin/gpg" # relative path
132
+ ----
133
+
134
+ Avoid hardcoding values. Usually, setting a proper `$PATH` environment variable
135
+ is better than assigning an absolute path to `gpg_executable` attribute.
136
+
114
137
  == Development
115
138
 
116
139
  After checking out the repo, run `bin/setup` to install dependencies.
@@ -7,8 +7,8 @@ require "rspec/pgp_matchers"
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
9
  # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
10
+ require "pry"
11
+ Pry.start
12
12
 
13
- require "irb"
14
- IRB.start(__FILE__)
13
+ # require "irb"
14
+ # IRB.start(__FILE__)
@@ -1,5 +1,3 @@
1
- # rubocop:disable Security/Eval
2
- eval File.read(File.expand_path("common.gemfile", __dir__))
3
- # rubocop:enable Security/Eval
1
+ eval_gemfile "common.gemfile"
4
2
 
5
3
  gem "rspec-expectations", "~> 3.4.0"
@@ -1,5 +1,3 @@
1
- # rubocop:disable Security/Eval
2
- eval File.read(File.expand_path("common.gemfile", __dir__))
3
- # rubocop:enable Security/Eval
1
+ eval_gemfile "common.gemfile"
4
2
 
5
3
  gem "rspec-expectations", "~> 3.5.0"
@@ -1,5 +1,3 @@
1
- # rubocop:disable Security/Eval
2
- eval File.read(File.expand_path("common.gemfile", __dir__))
3
- # rubocop:enable Security/Eval
1
+ eval_gemfile "common.gemfile"
4
2
 
5
3
  gem "rspec-expectations", "~> 3.6.0"
@@ -1,5 +1,3 @@
1
- # rubocop:disable Security/Eval
2
- eval File.read(File.expand_path("common.gemfile", __dir__))
3
- # rubocop:enable Security/Eval
1
+ eval_gemfile "common.gemfile"
4
2
 
5
3
  gem "rspec-expectations", "~> 3.7.0"
@@ -1,6 +1,7 @@
1
1
  # (c) Copyright 2018 Ribose Inc.
2
2
  #
3
3
 
4
+ require "rspec/expectations"
4
5
  require "rspec/pgp_matchers/version"
5
6
  require "rspec/pgp_matchers/gpg_matcher_helper"
6
7
  require "rspec/pgp_matchers/gpg_runner"
@@ -9,9 +10,34 @@ require "rspec/pgp_matchers/be_a_valid_pgp_signature_of"
9
10
 
10
11
  module RSpec
11
12
  module PGPMatchers
13
+ @gpg_executable = "gpg"
14
+
12
15
  class << self
16
+ # Name of the GnuPG executable or path to that executable. Defaults to
17
+ # +gpg+.
18
+ #
19
+ # Absolute and relative paths are allowed, but usually setting +$PATH+
20
+ # environment variable is a better idea.
21
+ #
22
+ # @return [String] executable name or absolute or relative path to that
23
+ # executable
24
+ attr_accessor :gpg_executable
25
+
26
+ # Path to the OpenPGP home directory. Defaults to +nil+ and must be set
27
+ # prior using the matchers.
28
+ #
29
+ # Given directory may be initialized with other tool than GnuPG, e.g. RNP,
30
+ # but it must be in a format which is readable by GnuPG. Also,
31
+ # if specified directory is empty, then it will be initialized by GnuPG
32
+ # at first use, it must exist though. Nevertheless, the latter case is
33
+ # not very practical, as the OpenPGP home directory created this way
34
+ # contains no keys.
35
+ #
36
+ # It is recommended to have a dedicated PGP home directory just for
37
+ # testing, so that test keys are separated from regular ones.
38
+ #
39
+ # @return [String] absolute or relative path to the OpenPGP home directory
13
40
  attr_accessor :homedir
14
41
  end
15
- # Your code goes here...
16
42
  end
17
43
  end
@@ -6,6 +6,10 @@ require "tempfile"
6
6
 
7
7
  module RSpec
8
8
  module PGPMatchers
9
+ # A collection of utility methods to be included in matchers. Mostly for
10
+ # extracting information from GnuPG output.
11
+ #
12
+ # @api private
9
13
  module GPGMatcherHelper
10
14
  extend Forwardable
11
15
 
@@ -6,21 +6,39 @@ require "tempfile"
6
6
 
7
7
  module RSpec
8
8
  module PGPMatchers
9
+ # A helper module for executing GnuPG commands.
9
10
  module GPGRunner
10
11
  class << self
12
+ # Executes arbitrary GnuPG command.
13
+ #
14
+ # @param gpg_cmd [String] command to run
15
+ # @return [Array] tuple +[stdout, stderr, status]+
16
+ # like in stdlib's {Open3.capture3}
17
+ #
18
+ # @example
19
+ # # Will list all GnuPG keys
20
+ # run_command("--list-keys")
21
+ # # Will list keys and their keygrips
22
+ # run_command("--list-keys --with-keygrip")
11
23
  def run_command(gpg_cmd)
12
24
  env = { "LC_ALL" => "C" } # Gettext English locale
13
25
 
26
+ gpg_executable = Shellwords.escape(RSpec::PGPMatchers.gpg_executable)
14
27
  homedir_path = Shellwords.escape(RSpec::PGPMatchers.homedir)
15
28
 
16
29
  Open3.capture3(env, <<~SH)
17
- gpg \
30
+ #{gpg_executable} \
18
31
  --homedir #{homedir_path} \
19
32
  --no-permission-warning \
20
33
  #{gpg_cmd}
21
34
  SH
22
35
  end
23
36
 
37
+ # Decrypts a message.
38
+ #
39
+ # @param encrypted_string [String] encrypted message
40
+ # @return [Array] tuple +[stdout, stderr, status]+
41
+ # like in stdlib's {Open3.capture3}
24
42
  def run_decrypt(encrypted_string)
25
43
  enc_file = make_tempfile_containing(encrypted_string)
26
44
  cmd = gpg_decrypt_command(enc_file)
@@ -29,6 +47,12 @@ module RSpec
29
47
  File.unlink(enc_file.path)
30
48
  end
31
49
 
50
+ # Verifies a signature.
51
+ #
52
+ # @param cleartext [String] message in clear text
53
+ # @param signature_string [String] signature
54
+ # @return [Array] tuple +[stdout, stderr, status]+
55
+ # like in stdlib's {Open3.capture3}
32
56
  def run_verify(cleartext, signature_string)
33
57
  sig_file = make_tempfile_containing(signature_string)
34
58
  data_file = make_tempfile_containing(cleartext)
@@ -3,6 +3,6 @@
3
3
 
4
4
  module RSpec
5
5
  module PGPMatchers
6
- VERSION = "0.1.2".freeze
6
+ VERSION = "0.2.0".freeze
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-pgp_matchers
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-01-12 00:00:00.000000000 Z
11
+ date: 2019-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec-expectations
@@ -114,8 +114,10 @@ files:
114
114
  - ".rspec"
115
115
  - ".rubocop.yml"
116
116
  - ".travis.yml"
117
+ - ".yardopts"
117
118
  - Gemfile
118
119
  - LICENSE.txt
120
+ - PROTECTED_KEYS.adoc
119
121
  - README.adoc
120
122
  - Rakefile
121
123
  - bin/bundle
@@ -154,8 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
154
156
  - !ruby/object:Gem::Version
155
157
  version: '0'
156
158
  requirements: []
157
- rubyforge_project:
158
- rubygems_version: 2.7.6
159
+ rubygems_version: 3.0.3
159
160
  signing_key:
160
161
  specification_version: 4
161
162
  summary: RSpec matchers for testing OpenPGP messages