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
@@ -0,0 +1,189 @@
1
+ require 'open3'
2
+
3
+ module GPG
4
+ class Runner
5
+ include PGP::LogCapable
6
+
7
+ attr_accessor :version_cache
8
+
9
+ def version_default
10
+ if self.version_cache.nil?
11
+ self.version_cache = read_version('gpg --version', '')
12
+ end
13
+
14
+ self.version_cache
15
+ end
16
+
17
+ def read_private_key_recipients
18
+ run('gpg --quiet --list-secret-keys --fingerprint --keyid-format LONG') do |stdin, output, handle|
19
+ return [] unless handle.value.success?
20
+ extract_recipients(output)
21
+ end
22
+ end
23
+
24
+ def read_public_key_recipients
25
+ run('gpg --quiet --list-keys --fingerprint --keyid-format LONG') do |stdin, output, handle|
26
+ return [] unless handle.value.success?
27
+ extract_recipients(output)
28
+ end
29
+ end
30
+
31
+ def read_private_key_fingerprints
32
+ run('gpg --quiet --list-secret-keys --fingerprint --keyid-format LONG') do |stdin, output, handle|
33
+ return [] unless handle.value.success?
34
+ extract_fingerprints(output)
35
+ end
36
+ end
37
+
38
+ def read_public_key_fingerprints
39
+ run('gpg --quiet --list-keys --fingerprint --keyid-format LONG') do |stdin, output, handle|
40
+ return [] unless handle.value.success?
41
+ extract_fingerprints(output)
42
+ end
43
+ end
44
+
45
+ def delete_private_key(fingerprint)
46
+ run_gpg_silent_command("gpg --quiet --batch --yes --delete-secret-key #{fingerprint}")
47
+ end
48
+
49
+ def delete_public_key(fingerprint)
50
+ run_gpg_silent_command("gpg --quiet --batch --yes --delete-key #{fingerprint}")
51
+ end
52
+
53
+ def import_key_from_file(path)
54
+ log("Import Key; path: #{path}; contents:\n#{File.read(path)}")
55
+ command = "gpg --batch -v --import \"#{path}\""
56
+ run(command) do |stdin, output, handle|
57
+ extract_recipients(output)
58
+ end
59
+ end
60
+
61
+ def verify_signature_file(path, data_output_path=nil)
62
+ if data_output_path.nil?
63
+ log("Verify Signature; path: #{path}; contents:\n#{File.read(path)}")
64
+ run_gpg_silent_command("gpg --quiet --batch --verify \"#{path}\"")
65
+ else
66
+ log("Verify Signature; path: #{path}; data_output_path: #{data_output_path}; contents:\n#{File.read(path)}")
67
+ run_gpg_silent_command("gpg --quiet --batch --output \"#{data_output_path}\" \"#{path}\"")
68
+ end
69
+ end
70
+
71
+ def decrypt_file(path, data_output_path, passphrase=nil)
72
+ passphrase ||= ''
73
+ command_pieces = [
74
+ 'gpg',
75
+ '--quiet',
76
+ '--batch',
77
+ pinentry_mode_command_options(passphrase),
78
+ passphrase_command_options(passphrase),
79
+ '--yes',
80
+ '--ignore-mdc-error',
81
+ '--output',
82
+ "\"#{data_output_path}\"",
83
+ '--decrypt',
84
+ "\"#{path}\""
85
+ ]
86
+ command = command_pieces.reject(&:empty?).join(' ')
87
+ run_gpg_silent_command(command)
88
+ end
89
+
90
+ def sign_file(path, data_output_path, passphrase=nil)
91
+ passphrase ||= ''
92
+ command_pieces = [
93
+ 'gpg',
94
+ '--quiet',
95
+ '--batch',
96
+ pinentry_mode_command_options(passphrase),
97
+ passphrase_command_options(passphrase),
98
+ '--yes',
99
+ '--ignore-mdc-error',
100
+ '--output',
101
+ "\"#{data_output_path}\"",
102
+ '--sign',
103
+ "\"#{path}\""
104
+ ]
105
+ command = command_pieces.reject(&:empty?).join(' ')
106
+ run_gpg_silent_command(command)
107
+ end
108
+
109
+ def encrypt_file(path, data_output_path, recipients)
110
+ recipients_str = recipients
111
+ .map { |s| "--recipient \"#{s}\"" }
112
+ .join(' ')
113
+ command = "gpg --quiet --batch --yes --output \"#{data_output_path}\" #{recipients_str} --trust-model always --encrypt \"#{path}\""
114
+ run_gpg_silent_command(command)
115
+ end
116
+
117
+ private
118
+
119
+ def run_gpg_silent_command(command)
120
+ run(command) do |stdin, output, handle|
121
+ handle.value.success?
122
+ end
123
+ end
124
+
125
+ def read_version(command, default_value)
126
+ run(command) do |stdin, output, handle|
127
+ return default_value unless handle.value.success?
128
+ output.lines.first.split(' ').last.strip
129
+ end
130
+ end
131
+
132
+ def extract_fingerprints(str)
133
+ (str || '')
134
+ .lines
135
+ .filter { |l| l.downcase.include? 'key fingerprint =' }
136
+ .map { |l| l.split('=').last }
137
+ .map { |l| l.gsub(' ', '').strip }
138
+ end
139
+
140
+ def extract_recipients(str)
141
+ (str || '')
142
+ .lines
143
+ .map { |l| l.scan(/\<(.+)\>/m) }
144
+ .flatten
145
+ .reject(&:empty?)
146
+ .uniq
147
+ end
148
+
149
+ def run(command)
150
+ log("Running Command: #{command}")
151
+
152
+ Open3.popen2e(command) do |stdin, output, handle|
153
+ output_data = stream_to_string(output)
154
+
155
+ log("Output:\n#{output_data}")
156
+ log("Success?: #{handle.value.success?}")
157
+
158
+ yield(stdin, output_data, handle)
159
+ end
160
+ end
161
+
162
+ def stream_to_string(stream)
163
+ result = ''
164
+ loop do
165
+ data = stream.gets
166
+
167
+ if data.nil?
168
+ break
169
+ end
170
+
171
+ result << data
172
+ end
173
+ result
174
+ end
175
+
176
+ def passphrase_command_options(passphrase)
177
+ return '' if passphrase.empty?
178
+
179
+ "--passphrase \"#{passphrase}\""
180
+ end
181
+
182
+ def pinentry_mode_command_options(passphrase)
183
+ return '' if passphrase.empty?
184
+ return '' if version_default.start_with?('2.0.')
185
+
186
+ '--pinentry-mode loopback'
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,25 @@
1
+ module GPG
2
+ class TempPathHelper
3
+ def self.create(&block)
4
+ path = File.join(Dir.tmpdir, random_string)
5
+
6
+ yield(path) if block
7
+
8
+ path
9
+ ensure
10
+ delete(path)
11
+ end
12
+
13
+ private
14
+
15
+ def self.delete(path)
16
+ if File.exists?(path)
17
+ File.delete(path)
18
+ end
19
+ end
20
+
21
+ def self.random_string(length=20)
22
+ (0...length).map { (65 + rand(26)).chr }.join
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ module PGP
2
+ module KeysImporter
3
+ def add_keys(key_string)
4
+ GPG::Engine.new.import_key(key_string)
5
+ end
6
+
7
+ def add_keys_from_file(filename)
8
+ add_keys(File.read(filename))
9
+ end
10
+ end
11
+ end
data/lib/pgp/log.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'logger'
2
+
3
+ module PGP
4
+ class Log
5
+ class << self
6
+ attr_writer :logger
7
+ attr_writer :verbose
8
+
9
+ def logger
10
+ @logger ||= Logger.new($stdout).tap do |log|
11
+ log.progname = self.name
12
+ end
13
+ end
14
+
15
+ def verbose
16
+ @verbose ||= false
17
+ end
18
+ end
19
+ end
20
+
21
+ module LogCapable
22
+ def log(message)
23
+ if PGP::Log.verbose
24
+ PGP::Log.logger.info(message)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,9 @@
1
+ module PGP
2
+ class RubyDecryptor
3
+ def self.decrypt(encrypted_text, private_key_file, passphrase=nil)
4
+ engine = GPG::Engine.new
5
+ engine.import_key(File.read(private_key_file))
6
+ engine.decrypt(encrypted_text, passphrase)[1]
7
+ end
8
+ end
9
+ end
data/lib/pgp/signer.rb ADDED
@@ -0,0 +1,16 @@
1
+ module PGP
2
+ class Signer
3
+ include PGP::KeysImporter
4
+
5
+ attr_accessor :passphrase
6
+
7
+ def sign(data)
8
+ result = GPG::Engine.new.sign(data, self.passphrase)
9
+ result[1]
10
+ end
11
+
12
+ def sign_file(file_path)
13
+ sign File.read(file_path)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ module PGP
2
+ class Verifier
3
+ include PGP::KeysImporter
4
+
5
+ def verify(signed_data)
6
+ result = GPG::Engine.new.verify_signature(signed_data)
7
+ signature_valid = result[0]
8
+
9
+ raise 'Signature could not be verified' unless signature_valid
10
+
11
+ result[1]
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module PGP
2
+ VERSION = '0.0.1'
3
+ end
data/lib/pgp.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'pgp/log'
2
+ require 'pgp/keys_importer'
3
+ require 'pgp/decryptor'
4
+ require 'pgp/encryptor'
5
+ require 'pgp/verifier'
6
+ require 'pgp/signer'
7
+ require 'pgp/gpg/temp_path_helper'
8
+ require 'pgp/gpg/runner'
9
+ require 'pgp/gpg/engine'
10
+
11
+ module PGP
12
+ autoload :VERSION, 'pgp/version'
13
+ autoload :RubyDecryptor, 'pgp/ruby_decryptor'
14
+ autoload :CLI, 'pgp/cli'
15
+
16
+ # This exists for stubbing during tests
17
+ def self.time_now
18
+ Time.now
19
+ end
20
+ end
data/lib/ruby-pgp.rb ADDED
@@ -0,0 +1 @@
1
+ require 'pgp'
data/ruby-pgp.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'pgp/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = 'ruby-pgp'
9
+ gem.version = PGP::VERSION
10
+ gem.licenses = ['MIT']
11
+ gem.authors = ['Camilo Sanchez']
12
+ gem.email = ['gems@tddapps.com']
13
+ gem.description = %q{PGP for Ruby}
14
+ gem.summary = %q{This is a GnuPG2 wrapper modeled after the jruby-pgp api}
15
+ gem.homepage = 'https://github.com/cshtdd/ruby-pgp'
16
+
17
+ gem.files = `git ls-files`.split($/)
18
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
+ gem.require_paths = ['lib']
21
+
22
+ gem.add_development_dependency 'rake', '~> 13'
23
+ gem.add_development_dependency 'rspec', '~> 3.9.0'
24
+ end
data/run_tests.sh ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+
3
+ source /etc/profile.d/rvm.sh
4
+
5
+ bundle install
6
+
7
+ rspec
@@ -0,0 +1,9 @@
1
+ module KeysHelper
2
+ def remove_all_keys
3
+ gpg = GPG::Engine.new
4
+ gpg.delete_all_keys
5
+
6
+ raise 'No public keys expected' unless gpg.runner.read_public_key_fingerprints.empty?
7
+ raise 'No private keys expected' unless gpg.runner.read_private_key_fingerprints.empty?
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module ProcessHelper
2
+ def setup_process(command, success, output)
3
+ output_stub = double
4
+ exit_code_stub = double
5
+ handle_stub = double
6
+
7
+ allow(handle_stub).to receive(:value).and_return(exit_code_stub)
8
+
9
+ allow(output_stub).to receive(:gets).and_return(output, nil)
10
+ allow(exit_code_stub).to receive(:success?).and_return(success)
11
+ allow(Open3).to receive(:popen2e).with(command).and_yield(nil, output_stub, handle_stub)
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ module TempHelper
2
+ def setup_temp_file(contents='')
3
+ stub = create_temp_file_stub(contents)
4
+ allow(Tempfile).to receive(:open).and_yield(stub)
5
+ stub
6
+ end
7
+
8
+ def create_temp_file_stub(contents='')
9
+ stub = double
10
+ allow(stub).to receive(:path).and_return(random_string)
11
+ allow(stub).to receive(:write).with(contents)
12
+ allow(stub).to receive(:read).and_return(contents)
13
+ allow(stub).to receive(:rewind)
14
+ stub
15
+ end
16
+
17
+ def random_string(length=20)
18
+ (0...length).map { (65 + rand(26)).chr }.join
19
+ end
20
+
21
+ def setup_temp_paths(paths)
22
+ allow(GPG::TempPathHelper).to receive(:create) do |&block|
23
+ p = paths.pop
24
+ block.call(p)
25
+ p
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+
4
+ describe PGP::CLI do
5
+ let(:private_key_path) { Fixtures_Path.join('private_key.asc').to_s }
6
+ let(:public_key_path) { Fixtures_Path.join('public_key.asc').to_s }
7
+
8
+ let(:decrypted_file) { Fixtures_Path.join('unencrypted_file.txt').to_s }
9
+ let(:encrypted_file) { Fixtures_Path.join('unencrypted_file.txt.asc').to_s }
10
+
11
+ after {
12
+ # These files are created in our current working directory
13
+ FileUtils.rm_rf('unencrypted_file.txt.gpg')
14
+ FileUtils.rm_rf('unencrypted_file.txt')
15
+ }
16
+
17
+
18
+ describe 'Encrypting' do
19
+ it "should encrypt a given file to the given public key" do
20
+ PGP::CLI::Runner.go!([decrypted_file, "-p", "spec/support/fixtures/public_key.asc"])
21
+
22
+ expect(File.exist?('unencrypted_file.txt.gpg')).to eq(true)
23
+ end
24
+ end
25
+
26
+ describe 'Decrypting' do
27
+ it "should decrypt a given file to the given private key" do
28
+ PGP::CLI::Runner.go!([encrypted_file, "-P", "spec/support/fixtures/private_key.asc", "-d"])
29
+
30
+ expect(File.exist?('unencrypted_file.txt')).to eq(true)
31
+ end
32
+ end
33
+
34
+ describe 'Public Keys'
35
+
36
+ describe 'Private Keys'
37
+
38
+ describe 'Input Files'
39
+
40
+ describe 'Output Files'
41
+ end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe PGP::Decryptor do
4
+ include KeysHelper
5
+
6
+ let(:private_key_path) { Fixtures_Path.join('private_key.asc').to_s }
7
+ let(:public_key_path) { Fixtures_Path.join('public_key.asc').to_s }
8
+
9
+ let(:decryptor) { PGP::Decryptor.new }
10
+
11
+ let(:encrypted_file) { Fixtures_Path.join('unencrypted_file.txt.asc') }
12
+ let(:encrypted_text) { File.read(encrypted_file) }
13
+ let(:file_path) { Fixtures_Path.join('unencrypted_file.txt') }
14
+ let(:unencrypted_text) { File.read(file_path) }
15
+
16
+ before { remove_all_keys }
17
+
18
+ describe '#decrypt' do
19
+ before {
20
+ decryptor.add_keys_from_file(private_key_path)
21
+ }
22
+
23
+ it "should successfully decrypt an encrypted file" do
24
+ expect(decryptor.decrypt(encrypted_text)).to eq(unencrypted_text)
25
+ end
26
+
27
+ describe 'ruby_decryptor' do
28
+ it 'should successfully decrypt an encrypted file' do
29
+ actual_text = PGP::RubyDecryptor.decrypt(encrypted_text, private_key_path)
30
+ expect(actual_text).to eq(unencrypted_text)
31
+ end
32
+ end
33
+ end
34
+
35
+ describe "decrypt with private key and passphrase" do
36
+ let(:private_key_with_passphrase_path) { Fixtures_Path.join('private_key_with_passphrase.asc') }
37
+ let(:encrypted_with_passphrase_file) { Fixtures_Path.join('encrypted_with_passphrase_key.txt.asc') }
38
+ let(:encrypted_text) { File.read(encrypted_with_passphrase_file) }
39
+ let(:unencrypted_text) { File.read(Fixtures_Path.join('encrypted_with_passphrase_key.txt'))}
40
+ let(:passphrase) { "testingpgp" }
41
+
42
+ before do
43
+ decryptor.passphrase = passphrase
44
+ decryptor.add_keys_from_file(private_key_with_passphrase_path)
45
+ end
46
+
47
+ it "should decrypt" do
48
+ expect(decryptor.decrypt(encrypted_text)).to eq(unencrypted_text)
49
+ end
50
+
51
+ describe 'ruby_decryptor' do
52
+ it 'should decrypt' do
53
+ actual_text = PGP::RubyDecryptor.decrypt(encrypted_text, private_key_path, passphrase)
54
+ expect(actual_text).to eq(unencrypted_text)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe PGP::Encryptor do
4
+ include KeysHelper
5
+
6
+ let(:private_key_path) { Fixtures_Path.join('private_key.asc').to_s }
7
+ let(:public_key_path) { Fixtures_Path.join('public_key.asc').to_s }
8
+
9
+ let(:encryptor) { PGP::Encryptor.new }
10
+ let(:string) { "FooBar" }
11
+
12
+ before { remove_all_keys }
13
+
14
+ describe '#initialize' do
15
+ let(:encryptor) { PGP::Encryptor.new(File.read public_key_path) }
16
+
17
+ it "should accept public key(s) as an argument" do
18
+ encrypted_string = encryptor.encrypt(string, "some filename.txt")
19
+
20
+ expect(PGP::RubyDecryptor.decrypt(encrypted_string, private_key_path)).to eq(string)
21
+ end
22
+ end
23
+
24
+ describe '#encrypt' do
25
+ after {
26
+ File.delete("some filename.txt") if File.exists?("some filename.txt")
27
+ }
28
+
29
+ context 'When the Public Key is from a file' do
30
+ before {
31
+ encryptor.add_keys_from_file(public_key_path)
32
+ }
33
+
34
+ it "it's encrypted string should be decryptable. durr" do
35
+ encrypted_string = encryptor.encrypt(string, "some filename.txt")
36
+
37
+ expect(File.read("some filename.txt")).to eq(encrypted_string)
38
+ expect(PGP::RubyDecryptor.decrypt(encrypted_string, private_key_path)).to eq(string)
39
+ end
40
+
41
+ it "should not require that a filename be specified" do
42
+ encrypted_string = encryptor.encrypt(string)
43
+
44
+ expect(PGP::RubyDecryptor.decrypt(encrypted_string, private_key_path)).to eq(string)
45
+ end
46
+ end # context 'When the Public Key is from a file'
47
+
48
+ context 'When the Public Key has been read in to memory' do
49
+ before {
50
+ encryptor.add_keys(File.read public_key_path)
51
+ }
52
+
53
+ it "it's encrypted string should be decryptable. durr" do
54
+ encrypted_string = encryptor.encrypt(string, "some filename.txt")
55
+
56
+ expect(File.read("some filename.txt")).to eq(encrypted_string)
57
+ expect(PGP::RubyDecryptor.decrypt(encrypted_string, private_key_path)).to eq(string)
58
+ end
59
+
60
+ it "should not require that a filename be specified" do
61
+ encrypted_string = encryptor.encrypt(string)
62
+
63
+ expect(PGP::RubyDecryptor.decrypt(encrypted_string, private_key_path)).to eq(string)
64
+ end
65
+ end # context 'When the Public Key has been read in to memory'
66
+
67
+ end # describe '#encrypt'
68
+
69
+ describe '#encrypt_file' do
70
+ let(:file_path) { Fixtures_Path.join('unencrypted_file.txt') }
71
+ let(:contents) { File.read(file_path) }
72
+
73
+ before {
74
+ encryptor.add_keys(File.read public_key_path)
75
+ }
76
+
77
+ pending "should have an encryptStream method to avoid memory bloat"
78
+
79
+ it "should encrypt a file" do
80
+ encrypted_file = encryptor.encrypt_file(file_path)
81
+
82
+ expect(PGP::RubyDecryptor.decrypt(encrypted_file, private_key_path)).to eq(contents)
83
+ end
84
+ end # describe '#encrypt_file'
85
+
86
+ end