rspec-pgp_matchers 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +4 -5
- data/.yardopts +4 -0
- data/PROTECTED_KEYS.adoc +99 -0
- data/README.adoc +23 -0
- data/bin/console +4 -4
- data/ci/gemfiles/rspec-3.4.gemfile +1 -3
- data/ci/gemfiles/rspec-3.5.gemfile +1 -3
- data/ci/gemfiles/rspec-3.6.gemfile +1 -3
- data/ci/gemfiles/rspec-3.7.gemfile +1 -3
- data/lib/rspec/pgp_matchers.rb +27 -1
- data/lib/rspec/pgp_matchers/gpg_matcher_helper.rb +4 -0
- data/lib/rspec/pgp_matchers/gpg_runner.rb +25 -1
- data/lib/rspec/pgp_matchers/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4715837cead4425a9b36c7f7b722d5d64c0910e0987a8ea1c8b56b5c06ef1372
|
4
|
+
data.tar.gz: 713c60d3e6196483f586ec1026eec5b3a4d05155e3540f8207bb24ad116ed711
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec96116566ec3b4bded4fd3b78566ae567a4d6d69fce22b9b9d8627f4767ffde79b729613e185f4bbb9f10df91e8422df7a7e19ba2255d96ea098ef5d96f0faa
|
7
|
+
data.tar.gz: 8e6d0397bbe146ec9804074a3455a5cb51f3e2cb60eae25f0464748d6c5a1e92a7e9fb83d431afa22907e34e4a940fe1d8f03aba18852752254d434f3028e0c7
|
data/.travis.yml
CHANGED
data/.yardopts
ADDED
data/PROTECTED_KEYS.adoc
ADDED
@@ -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
|
data/README.adoc
CHANGED
@@ -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.
|
data/bin/console
CHANGED
@@ -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
|
-
|
11
|
-
|
10
|
+
require "pry"
|
11
|
+
Pry.start
|
12
12
|
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
13
|
+
# require "irb"
|
14
|
+
# IRB.start(__FILE__)
|
data/lib/rspec/pgp_matchers.rb
CHANGED
@@ -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,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
|
-
|
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)
|
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.
|
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-
|
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
|
-
|
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
|