ruby-pgp 0.0.1

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.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rbenv-version +1 -0
  4. data/.rspec +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +14 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +82 -0
  10. data/Rakefile +12 -0
  11. data/bin/jrpgp +12 -0
  12. data/bin/rpgp +12 -0
  13. data/lib/pgp/cli/runner.rb +78 -0
  14. data/lib/pgp/cli.rb +160 -0
  15. data/lib/pgp/decryptor.rb +16 -0
  16. data/lib/pgp/encryptor.rb +33 -0
  17. data/lib/pgp/gpg/engine.rb +141 -0
  18. data/lib/pgp/gpg/runner.rb +189 -0
  19. data/lib/pgp/gpg/temp_path_helper.rb +25 -0
  20. data/lib/pgp/keys_importer.rb +11 -0
  21. data/lib/pgp/log.rb +28 -0
  22. data/lib/pgp/ruby_decryptor.rb +9 -0
  23. data/lib/pgp/signer.rb +16 -0
  24. data/lib/pgp/verifier.rb +14 -0
  25. data/lib/pgp/version.rb +3 -0
  26. data/lib/pgp.rb +20 -0
  27. data/lib/ruby-pgp.rb +1 -0
  28. data/ruby-pgp.gemspec +24 -0
  29. data/run_tests.sh +7 -0
  30. data/spec/helpers/keys_helper.rb +9 -0
  31. data/spec/helpers/process_helper.rb +13 -0
  32. data/spec/helpers/temp_helper.rb +28 -0
  33. data/spec/lib/pgp/cli_spec.rb +41 -0
  34. data/spec/lib/pgp/decryptor_spec.rb +58 -0
  35. data/spec/lib/pgp/encryptor_spec.rb +86 -0
  36. data/spec/lib/pgp/gpg/engine_spec.rb +276 -0
  37. data/spec/lib/pgp/gpg/runner_integration_spec.rb +38 -0
  38. data/spec/lib/pgp/gpg/runner_spec.rb +432 -0
  39. data/spec/lib/pgp/gpg/temp_path_helper_spec.rb +53 -0
  40. data/spec/lib/pgp/signer_spec.rb +48 -0
  41. data/spec/lib/pgp/verifier_spec.rb +40 -0
  42. data/spec/lib/quirks_spec.rb +102 -0
  43. data/spec/spec_helper.rb +27 -0
  44. data/spec/support/fixtures/encrypted_with_passphrase_key.txt +1 -0
  45. data/spec/support/fixtures/encrypted_with_passphrase_key.txt.asc +13 -0
  46. data/spec/support/fixtures/private_key.asc +63 -0
  47. data/spec/support/fixtures/private_key_with_passphrase.asc +59 -0
  48. data/spec/support/fixtures/public_key.asc +36 -0
  49. data/spec/support/fixtures/public_key_with_passphrase.asc +30 -0
  50. data/spec/support/fixtures/signed_file.txt +1 -0
  51. data/spec/support/fixtures/signed_file.txt.asc +14 -0
  52. data/spec/support/fixtures/unencrypted_file.txt +1 -0
  53. data/spec/support/fixtures/unencrypted_file.txt.asc +19 -0
  54. data/spec/support/fixtures/wrong_private_key_for_signature.asc +63 -0
  55. data/spec/support/fixtures/wrong_public_key_for_signature.asc +36 -0
  56. data/spec/verify.sh +124 -0
  57. metadata +155 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b432669b4f5ee44e8a38a98529188ac56c1805976c0165ffa3db9a2842eea353
4
+ data.tar.gz: d50a88d4fcb014eadc8c81e8cf05e98b3263224fd553d83bd0ff59e4aaacf4eb
5
+ SHA512:
6
+ metadata.gz: 4c390a4d5fafe6dc931ef6386e3ff80d6ada3ba0ba5ec8aeab0399e293af6759d524e9959c7d2f7e7d9d79a70ba92e81b3a055785eca6add14dd59e9660fe387
7
+ data.tar.gz: 5804d452f534a60d66fa5d2fb9a1f89276798cde88799dd586ef2ad0b647118429e72b534c2680e96819a07b98416c3b52115e5bbc67ffd8291777e73bf1a2f7
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .idea
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ # ignore some crap the tests generate
20
+ some filename.txt
data/.rbenv-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.6.5
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --format documentation
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.6.5
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: minimal
2
+
3
+ services:
4
+ - docker
5
+
6
+ before_install:
7
+ - docker pull camilin87/ruby-centos:6
8
+ - docker pull camilin87/ruby-centos:7
9
+ - docker pull camilin87/ruby-ubuntu:18.04
10
+
11
+ script:
12
+ - docker run --rm -it -v $PWD:/home/ -w /home/ camilin87/ruby-centos:6 /bin/bash /home/run_tests.sh
13
+ - docker run --rm -it -v $PWD:/home/ -w /home/ camilin87/ruby-centos:7 /bin/bash /home/run_tests.sh
14
+ - docker run --rm -it -v $PWD:/home/ -w /home/ camilin87/ruby-ubuntu:18.04 /bin/bash /home/run_tests.sh
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ruby-pgp.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Scott Gonyea
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # PGP [![Build Status](https://travis-ci.org/cshtdd/ruby-pgp.svg?branch=mri)](https://travis-ci.org/cshtdd/ruby-pgp)
2
+
3
+ This a [GnuPG](https://gnupg.org/) wrapper built with Ruby.
4
+ The gem api is modeled after [jruby-pgp](https://github.com/sgonyea/jruby-pgp) for compatibility reasons with a legacy application.
5
+ This gem is validated with multiple versions of gpg and multiple operating systems.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'ruby-pgp'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install ruby-pgp
20
+
21
+ ## Feature Support:
22
+
23
+ The feature set is very bare, and restricted to the following operations:
24
+
25
+ - Encrypt a file to a known list of Public Key(s).
26
+
27
+ - Decrypt a file using a given set of Private Key(s).
28
+
29
+ - Public and Private keys may be read in from disk or from memory.
30
+
31
+ - Verify the signature of a file that you are decrypting. (thanks, @superchris)
32
+
33
+ - Use password-protected Private Keys. (thanks, @superchris)
34
+
35
+ - Sign a file from the file system. (thanks, @superchris)
36
+
37
+ Currently, you **cannot** do the following (These are TODO items):
38
+
39
+ - Verify any signatures of public / private keys.
40
+
41
+ - Create new Private Keys / generate public keys from a given Private Key.
42
+
43
+ - Sign a file that you are encrypting.
44
+
45
+ - Obtain the name of the file that was encrypted. (Should be an easy feature to add.)
46
+
47
+ - Obtain the "modificationTime" (timestamp) of the encrypted data / file.
48
+
49
+ - Verify a public key based on information from a key server.
50
+
51
+ ## Notes
52
+
53
+ This gem currently features everything I need and nothing I don't. Pull requests are very much welcome;
54
+ feature requests will be considered.
55
+
56
+ ## Usage
57
+
58
+ For usage examples, see the below test files:
59
+
60
+ Encryption: spec/lib/pgp/encryptor_spec.rb
61
+ Decryption: spec/lib/pgp/decryptor_spec.rb
62
+
63
+ ## Contributors
64
+
65
+ @superchris
66
+
67
+ ## Contributing
68
+
69
+ 1. Fork it
70
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
71
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
72
+ 4. Push to the branch (`git push origin my-new-feature`)
73
+ 5. Create new Pull Request
74
+
75
+ ## Testing:
76
+
77
+ Just run:
78
+
79
+ $ rspec
80
+
81
+ The [.travis.yml](.travis.yml) file describes our testing strategy for multiple OS.
82
+ We run the test suite against multiple OS versions with Ruby installed.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ RSpec::Core::RakeTask.new(:rcov) do |task|
7
+ task.rcov = true
8
+ end
9
+
10
+ task :default => :spec
11
+
12
+ task :build => :spec
data/bin/jrpgp ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if $LOAD_PATH.grep('ruby-pgp').none?
4
+ lib_dir = File.expand_path('../../lib', __FILE__)
5
+ $LOAD_PATH.unshift lib_dir
6
+ end
7
+
8
+ require 'pgp/cli/runner'
9
+ require 'pathname'
10
+ require 'optparse'
11
+
12
+ PGP::CLI::Runner.go!(ARGV)
data/bin/rpgp ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if $LOAD_PATH.grep('ruby-pgp').none?
4
+ lib_dir = File.expand_path('../../lib', __FILE__)
5
+ $LOAD_PATH.unshift lib_dir
6
+ end
7
+
8
+ require 'pgp/cli/runner'
9
+ require 'pathname'
10
+ require 'optparse'
11
+
12
+ PGP::CLI::Runner.go!(ARGV)
@@ -0,0 +1,78 @@
1
+ require 'pgp/cli'
2
+
3
+ module PGP
4
+ # Currently, this is pretty quick-and-dirty. I should expand options into accessor methods, I know.
5
+ class CLI
6
+ module Runner
7
+
8
+ def self.go!(args)
9
+ cli = parse_args!(args)
10
+ cli.run!
11
+ end
12
+
13
+ def self.parse_args!(args)
14
+ cli = PGP::CLI.new
15
+
16
+ cli.opt_parser = OptionParser.new do |opts|
17
+ opts.banner = "Usage: jrpgp [options] file [file2] [file3] [...]"
18
+
19
+ opts.on("-e", "--encrypt", "Perform Encryption") do
20
+ cli[:action] = :encrypt
21
+ end
22
+
23
+ opts.on("-d", "--decrypt", "Perform Decryption") do
24
+ cli[:action] = :decrypt
25
+ end
26
+
27
+ opts.on("-p", "--pub-key [file]", String, "The file containing Public Key(s) to encrypt to") do |fi|
28
+ PGP::CLI.ensure_file_exists!(fi)
29
+ cli[:public_keys] << fi
30
+ end
31
+
32
+ opts.on("-P", "--priv-key [file]", String, "The file containing Private Key(s) to use for decryption / signing") do |fi|
33
+ PGP::CLI.ensure_file_exists!(fi)
34
+ cli[:private_keys] << fi
35
+ end
36
+
37
+ opts.on("-i", "--in [file]", String, "The file to encrypt/decrypt") do |fi|
38
+ PGP::CLI.ensure_file_exists!(fi)
39
+ cli[:input_files] << fi
40
+ end
41
+
42
+ opts.on("-o", "--out [file]", String, "The file to output") do |fi|
43
+ cli[:output_files] << fi
44
+ end
45
+
46
+ opts.on("-O", "--out-dir [dir]", String, "The directory where output files should be written") do |dir|
47
+ PGP::CLI.ensure_dir_exists!(dir)
48
+ cli[:outdir] = Pathname(dir).expand_path
49
+ end
50
+
51
+ opts.separator ""
52
+
53
+ opts.on_tail("-h", "--help", "Show this message") do
54
+ puts opts
55
+ exit
56
+ end
57
+
58
+ # Another typical switch to print the version.
59
+ opts.on_tail("--version", "Show version") do
60
+ puts PGP::VERSION.join('.')
61
+ exit
62
+ end
63
+ end
64
+
65
+ cli.opt_parser.parse!(args)
66
+
67
+ args.each do |file|
68
+ PGP::CLI.ensure_file_exists!(file)
69
+ cli[:input_files] << file
70
+ end
71
+
72
+ cli
73
+ end
74
+
75
+ end
76
+ end
77
+ end
78
+
data/lib/pgp/cli.rb ADDED
@@ -0,0 +1,160 @@
1
+ require 'pgp'
2
+
3
+ module PGP
4
+ # Currently, this is pretty quick-and-dirty. I should expand options into accessor methods, I know.
5
+ class CLI
6
+ autoload :Runner, 'pgp/cli/runner'
7
+
8
+ attr_accessor :options, :opt_parser
9
+
10
+ Encrypted_Extension_Regexp = /\.(pgp|gpg|asc)$/i
11
+
12
+ def self.ensure_file_exists!(file)
13
+ raise "The file #{file.inspect} does not appear to exist!" unless File.exist?(file)
14
+ end
15
+
16
+ def self.ensure_dir_exists!(dir)
17
+ raise "The directory #{dir.inspect} does not appear to exist!" unless File.directory?(dir)
18
+ end
19
+
20
+ def initialize
21
+ self.options = {
22
+ :public_keys => [],
23
+ :private_keys => [],
24
+ :input_files => [],
25
+ :output_files => [],
26
+ :outdir => Pathname(Dir.pwd),
27
+ :same_dir => false,
28
+ :action => nil,
29
+ :signature => false, # We do not currently support signing or verifying signatures
30
+ }
31
+ end
32
+
33
+ def [](arg)
34
+ options[arg]
35
+ end
36
+
37
+ def []=(arg, val)
38
+ options[arg] = val
39
+ end
40
+
41
+ def validate_options!
42
+ raise "Input file(s) must be specified!" if input_files.none?
43
+
44
+ case action
45
+ when :encrypt then validate_encrypt_options!
46
+ when :decrypt then validate_decrypt_options!
47
+ else
48
+ raise "Valid actions are encrypt or decrypt. Action specified: #{options[:action]}"
49
+ end
50
+
51
+ rescue RuntimeError => e
52
+ $stderr.puts opt_parser
53
+ raise e
54
+ end
55
+
56
+ def run!
57
+ validate_options!
58
+
59
+ case options[:action]
60
+ when :encrypt then encrypt!
61
+ when :decrypt then decrypt!
62
+ end
63
+ end
64
+
65
+ def encrypt!
66
+ cryptor = Encryptor.new
67
+
68
+ public_keys.each {|pub| cryptor.add_keys_from_file(pub) }
69
+
70
+ input_files.each_with_index do |infile, idx|
71
+ outfile = output_files[idx]
72
+ output = cryptor.encrypt_file(infile)
73
+
74
+ File.open(outfile, "w") do |fi|
75
+ fi.write output
76
+ end
77
+ end
78
+ end
79
+
80
+ def decrypt!
81
+ cryptor = Decryptor.new
82
+
83
+ private_keys.each {|priv| cryptor.add_keys_from_file(priv) }
84
+
85
+ input_files.each_with_index do |infile, idx|
86
+ outfile = output_files[idx]
87
+ output = cryptor.decrypt_file(infile)
88
+
89
+ File.open(outfile, "w") do |fi|
90
+ fi.write output
91
+ end
92
+ end
93
+ end
94
+
95
+ def action
96
+ options[:action] ||= begin
97
+ if input_files.grep(Encrypted_Extension_Regexp).any?
98
+ :decrypt
99
+ else
100
+ :encrypt
101
+ end
102
+ end
103
+ end
104
+
105
+ def public_keys
106
+ options[:public_keys]
107
+ end
108
+
109
+ def private_keys
110
+ options[:private_keys]
111
+ end
112
+
113
+ def input_files
114
+ options[:input_files]
115
+ end
116
+
117
+ def output_files
118
+ options[:output_files]
119
+ end
120
+
121
+ def outdir
122
+ options[:outdir]
123
+ end
124
+
125
+ def same_dir?
126
+ options[:same_dir]
127
+ end
128
+
129
+ protected
130
+ def set_outfile_dir(file)
131
+ return file if same_dir?
132
+ outdir + File.basename(file)
133
+ end
134
+
135
+ def validate_encrypt_options!
136
+ raise "Public Keys are required for encryption" if options[:public_keys].none?
137
+ raise "Private Keys are required for signing files" if options[:signature] and options[:private_keys].none?
138
+
139
+ options[:input_files].each_with_index do |infile, idx|
140
+ next if options[:output_files][idx]
141
+ options[:output_files][idx] = set_outfile_dir("#{infile}.gpg")
142
+ end
143
+ end
144
+
145
+ def validate_decrypt_options!
146
+ raise "Private Keys are required for decryption" if options[:private_keys].none?
147
+ raise "Public Keys are required for verifying signatures" if options[:signature] and options[:public_keys].none?
148
+
149
+ options[:input_files].each_with_index do |infile, idx|
150
+ next if options[:output_files][idx]
151
+
152
+ outfile = infile.gsub(Encrypted_Extension_Regexp, '')
153
+ outfile = "#{infile} - decrypted" if outfile == infile
154
+
155
+ options[:output_files][idx] = set_outfile_dir(outfile)
156
+ end
157
+ end
158
+
159
+ end
160
+ end
@@ -0,0 +1,16 @@
1
+ module PGP
2
+ class Decryptor
3
+ include PGP::KeysImporter
4
+
5
+ attr_accessor :passphrase
6
+
7
+ def decrypt(encrypted_data)
8
+ result = GPG::Engine.new.decrypt(encrypted_data, self.passphrase)
9
+ result[1]
10
+ end
11
+
12
+ def decrypt_file(file_path)
13
+ decrypt File.read(file_path)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ module PGP
2
+ class Encryptor
3
+ attr_accessor :recipients
4
+
5
+ def initialize(key_string=nil)
6
+ self.recipients = []
7
+ add_keys(key_string) if key_string
8
+ end
9
+
10
+ def add_keys(key_string)
11
+ self.recipients += GPG::Engine.new.import_key(key_string)
12
+ end
13
+
14
+ def add_keys_from_file(filename)
15
+ add_keys(File.read(filename))
16
+ end
17
+
18
+ def encrypt(cleartext, filename=nil, mtime=nil)
19
+ result = GPG::Engine.new.encrypt(cleartext, recipients)
20
+
21
+ unless filename.nil?
22
+ File.write(filename, result[1])
23
+ end
24
+
25
+ result[1]
26
+ end
27
+
28
+ def encrypt_file(file_path)
29
+ encrypt(File.read(file_path))
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,141 @@
1
+ require 'tempfile'
2
+ require 'tmpdir'
3
+
4
+ module GPG
5
+ class Engine
6
+ include PGP::LogCapable
7
+
8
+ attr_accessor :runner
9
+
10
+ def initialize(runner = nil)
11
+ self.runner = runner || GPG::Runner.new
12
+ end
13
+
14
+ def import_key(key_contents)
15
+ log("Import Key")
16
+ validate_gpg_version
17
+ Tempfile.open do |f|
18
+ f.write(key_contents)
19
+ f.rewind
20
+
21
+ runner.import_key_from_file(f.path)
22
+ end
23
+ end
24
+
25
+ def verify_signature(signature_data)
26
+ log("Verify Signature")
27
+
28
+ validate_gpg_version
29
+
30
+ data = ''
31
+ result = false
32
+
33
+ GPG::TempPathHelper.create do |path1|
34
+ GPG::TempPathHelper.create do |path2|
35
+ File.write(path1, signature_data)
36
+ result = runner.verify_signature_file(path1, path2)
37
+
38
+ data = File.read(path2) if result
39
+ end
40
+ end
41
+
42
+ [result, data]
43
+ end
44
+
45
+ def decrypt(encrypted_data, passphrase=nil)
46
+ log("Decrypt")
47
+
48
+ validate_gpg_version
49
+
50
+ data = ''
51
+ result = false
52
+
53
+ GPG::TempPathHelper.create do |path1|
54
+ GPG::TempPathHelper.create do |path2|
55
+ File.write(path1, encrypted_data)
56
+ result = runner.decrypt_file(path1, path2, passphrase)
57
+
58
+ data = File.read(path2) if result
59
+ end
60
+ end
61
+
62
+ [result, data]
63
+ end
64
+
65
+ def encrypt(plaintext_data, recipients)
66
+ log("Encrypt")
67
+
68
+ raise 'Recipients cannot be empty' if recipients.empty?
69
+
70
+ validate_gpg_version
71
+
72
+ data = ''
73
+ result = false
74
+
75
+ GPG::TempPathHelper.create do |path1|
76
+ GPG::TempPathHelper.create do |path2|
77
+ File.write(path1, plaintext_data)
78
+ result = runner.encrypt_file(path1, path2, recipients)
79
+
80
+ data = File.read(path2) if result
81
+ end
82
+ end
83
+
84
+ [result, data]
85
+ end
86
+
87
+ def sign(plaintext_data, passphrase=nil)
88
+ log("Sign")
89
+
90
+ validate_gpg_version
91
+
92
+ data = ''
93
+ result = false
94
+
95
+ GPG::TempPathHelper.create do |path1|
96
+ GPG::TempPathHelper.create do |path2|
97
+ File.write(path1, plaintext_data)
98
+ result = runner.sign_file(path1, path2, passphrase)
99
+
100
+ data = File.read(path2) if result
101
+ end
102
+ end
103
+
104
+ [result, data]
105
+ end
106
+
107
+ def delete_all_keys
108
+ delete_all_private_keys
109
+ delete_all_public_keys
110
+ end
111
+
112
+ def delete_all_private_keys
113
+ log('Delete all private keys')
114
+ validate_gpg_version
115
+ runner.read_private_key_fingerprints.each do |k|
116
+ runner.delete_private_key k
117
+ end
118
+ end
119
+
120
+ def delete_all_public_keys
121
+ log('Delete all public keys')
122
+ validate_gpg_version
123
+ runner.read_public_key_fingerprints.each do |k|
124
+ runner.delete_public_key k
125
+ end
126
+ end
127
+
128
+ def read_recipients
129
+ validate_gpg_version
130
+ public_recipients = runner.read_public_key_recipients
131
+ private_recipients = runner.read_private_key_recipients
132
+ (public_recipients + private_recipients).uniq
133
+ end
134
+
135
+ protected
136
+
137
+ def validate_gpg_version
138
+ raise 'GPG Version is incorrect' unless runner.version_default.start_with?('2.')
139
+ end
140
+ end
141
+ end