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,432 @@
1
+ require 'spec_helper'
2
+
3
+ describe GPG::Runner do
4
+ include ProcessHelper
5
+
6
+ let(:runner) { GPG::Runner.new }
7
+
8
+ describe :version_default do
9
+ it 'reads gpg version' do
10
+ setup_process('gpg --version', true, "gpg (GnuPG) 2.0.22\nlibgcrypt 1.5.3\nblah\nblah")
11
+ expect(runner.version_default).to eq('2.0.22')
12
+ end
13
+
14
+ it 'returns empty when gpg fails' do
15
+ setup_process('gpg --version', false, nil)
16
+ expect(runner.version_default).to eq('')
17
+ end
18
+ end
19
+
20
+ describe :read_private_key_fingerprints do
21
+ it 'reads all the private key fingerprints' do
22
+ fingerprints = [
23
+ '23AD063A33C2EBE09F9A71ED9539E22A3388EE24',
24
+ 'A99BFCC3B6B952D66AFC1F3C48508D311DD34131'
25
+ ]
26
+ seeded_output = '''
27
+ /root/.gnupg/secring.gpg
28
+ ------------------------
29
+ sec 2048R/3388EE24 2013-03-04
30
+ Key fingerprint = 23AD 063A 33C2 EBE0 9F9A 71ED 9539 E22A 3388 EE24
31
+ uid Chris Nelson <superchrisnelson@gmail.com>
32
+ ssb 2048R/349BAAD3 2013-03-04
33
+
34
+ sec 2048R/1DD34131 2012-06-14
35
+ Key fingerprint = A99B FCC3 B6B9 52D6 6AFC 1F3C 4850 8D31 1DD3 4131
36
+ uid JRuby BG PGP Bug <foo@bar.com>
37
+ ssb 2048R/412E5D21 2012-06-14
38
+ '''
39
+ setup_process('gpg --quiet --list-secret-keys --fingerprint --keyid-format LONG', true, seeded_output)
40
+
41
+ expect(runner.read_private_key_fingerprints).to eq(fingerprints)
42
+ end
43
+
44
+ it 'returns empty when there are no secret keys' do
45
+ setup_process('gpg --quiet --list-secret-keys --fingerprint --keyid-format LONG', true, nil)
46
+
47
+ expect(runner.read_private_key_fingerprints).to eq([])
48
+ end
49
+
50
+ it 'returns empty when gpg fails' do
51
+ setup_process('gpg --quiet --list-secret-keys --fingerprint --keyid-format LONG', false, nil)
52
+
53
+ expect(runner.read_private_key_fingerprints).to eq([])
54
+ end
55
+ end
56
+
57
+ describe :read_public_key_fingerprints do
58
+ it 'reads all the public key fingerprints' do
59
+ fingerprints = [
60
+ '23AD063A33C2EBE09F9A71ED9539E22A3388EE24',
61
+ 'A99BFCC3B6B952D66AFC1F3C48508D311DD34131'
62
+ ]
63
+ seeded_output = '''
64
+ /root/.gnupg/pubring.gpg
65
+ ------------------------
66
+ pub 2048R/3388EE24 2013-03-04
67
+ Key fingerprint = 23AD 063A 33C2 EBE0 9F9A 71ED 9539 E22A 3388 EE24
68
+ uid Chris Nelson <superchrisnelson@gmail.com>
69
+ sub 2048R/349BAAD3 2013-03-04
70
+
71
+ pub 2048R/1DD34131 2012-06-14
72
+ Key fingerprint = A99B FCC3 B6B9 52D6 6AFC 1F3C 4850 8D31 1DD3 4131
73
+ uid JRuby BG PGP Bug <foo@bar.com>
74
+ sub 2048R/412E5D21 2012-06-14
75
+ '''
76
+
77
+ setup_process('gpg --quiet --list-keys --fingerprint --keyid-format LONG', true, seeded_output)
78
+
79
+ expect(runner.read_public_key_fingerprints).to eq(fingerprints)
80
+ end
81
+
82
+ it 'returns empty when there are no public keys' do
83
+ setup_process('gpg --quiet --list-keys --fingerprint --keyid-format LONG', false, '')
84
+
85
+ expect(runner.read_public_key_fingerprints).to eq([])
86
+ end
87
+
88
+ it 'returns empty when gpg fails' do
89
+ setup_process('gpg --quiet --list-keys --fingerprint --keyid-format LONG', false, nil)
90
+
91
+ expect(runner.read_public_key_fingerprints).to eq([])
92
+ end
93
+ end
94
+
95
+ describe :read_private_key_recipients do
96
+ it 'reads all the private key recipients' do
97
+ recipients = [
98
+ 'superchrisnelson@gmail.com',
99
+ 'foo@bar.com'
100
+ ]
101
+ seeded_output = '''
102
+ /root/.gnupg/secring.gpg
103
+ ------------------------
104
+ sec 2048R/3388EE24 2013-03-04
105
+ Key fingerprint = 23AD 063A 33C2 EBE0 9F9A 71ED 9539 E22A 3388 EE24
106
+ uid Chris Nelson <superchrisnelson@gmail.com>
107
+ ssb 2048R/349BAAD3 2013-03-04
108
+
109
+ sec 2048R/1DD34131 2012-06-14
110
+ Key fingerprint = A99B FCC3 B6B9 52D6 6AFC 1F3C 4850 8D31 1DD3 4131
111
+ uid JRuby BG PGP Bug <foo@bar.com>
112
+ ssb 2048R/412E5D21 2012-06-14
113
+ '''
114
+ setup_process('gpg --quiet --list-secret-keys --fingerprint --keyid-format LONG', true, seeded_output)
115
+
116
+ expect(runner.read_private_key_recipients).to eq(recipients)
117
+ end
118
+
119
+ it 'returns empty when there are no secret keys' do
120
+ setup_process('gpg --quiet --list-secret-keys --fingerprint --keyid-format LONG', true, nil)
121
+
122
+ expect(runner.read_private_key_recipients).to eq([])
123
+ end
124
+
125
+ it 'returns empty when gpg fails' do
126
+ setup_process('gpg --quiet --list-secret-keys --fingerprint --keyid-format LONG', false, nil)
127
+
128
+ expect(runner.read_private_key_recipients).to eq([])
129
+ end
130
+ end
131
+
132
+ describe :read_public_key_recipients do
133
+ it 'reads all the public key recipients' do
134
+ recipients = [
135
+ 'superchrisnelson@gmail.com',
136
+ 'foo@bar.com'
137
+ ]
138
+ seeded_output = '''
139
+ /root/.gnupg/secring.gpg
140
+ ------------------------
141
+ sec 2048R/3388EE24 2013-03-04
142
+ Key fingerprint = 23AD 063A 33C2 EBE0 9F9A 71ED 9539 E22A 3388 EE24
143
+ uid Chris Nelson <superchrisnelson@gmail.com>
144
+ ssb 2048R/349BAAD3 2013-03-04
145
+
146
+ sec 2048R/1DD34131 2012-06-14
147
+ Key fingerprint = A99B FCC3 B6B9 52D6 6AFC 1F3C 4850 8D31 1DD3 4131
148
+ uid JRuby BG PGP Bug <foo@bar.com>
149
+ ssb 2048R/412E5D21 2012-06-14
150
+ '''
151
+ setup_process('gpg --quiet --list-keys --fingerprint --keyid-format LONG', true, seeded_output)
152
+
153
+ expect(runner.read_public_key_recipients).to eq(recipients)
154
+ end
155
+
156
+ it 'returns empty when there are no secret keys' do
157
+ setup_process('gpg --quiet --list-keys --fingerprint --keyid-format LONG', true, nil)
158
+
159
+ expect(runner.read_public_key_recipients).to eq([])
160
+ end
161
+
162
+ it 'returns empty when gpg fails' do
163
+ setup_process('gpg --quiet --list-keys --fingerprint --keyid-format LONG', false, nil)
164
+
165
+ expect(runner.read_public_key_recipients).to eq([])
166
+ end
167
+ end
168
+
169
+ describe :delete_private_key do
170
+ it 'deletes they key with the specified fingerprint' do
171
+ setup_process('gpg --quiet --batch --yes --delete-secret-key AAAAAAA', true, '')
172
+
173
+ expect(runner.delete_private_key('AAAAAAA')).to eq(true)
174
+
175
+ expect(Open3).to have_received(:popen2e)
176
+ end
177
+
178
+ it 'returns false when the deletion fails' do
179
+ setup_process('gpg --quiet --batch --yes --delete-secret-key AAAAAAA', false, '')
180
+
181
+ expect(runner.delete_private_key('AAAAAAA')).to eq(false)
182
+ end
183
+ end
184
+
185
+ describe :delete_public_key do
186
+ it 'deletes the public key with the specified fingerprint' do
187
+ setup_process('gpg --quiet --batch --yes --delete-key AAAAAAA', true, '')
188
+
189
+ expect(runner.delete_public_key('AAAAAAA')).to eq(true)
190
+
191
+ expect(Open3).to have_received(:popen2e)
192
+ end
193
+
194
+ it 'returns false when the deletion fails' do
195
+ setup_process('gpg --quiet --batch --yes --delete-key AAAAAAA', false, '')
196
+
197
+ expect(runner.delete_public_key('AAAAAAA')).to eq(false)
198
+ end
199
+ end
200
+
201
+ describe :import_key_from_file do
202
+ before { allow(File).to receive(:read) }
203
+
204
+ it 'imports the key contents from a file and returns the recipients' do
205
+ output = '''
206
+ Version: GnuPG v1.4.12 (Darwin)
207
+ gpg: armor header:
208
+ Chris Nelson <superchrisnelson@gmail.com>gpg: sec 2048R/3388EE24 2013-03-04
209
+ gpg: key 3388EE24: secret key imported
210
+ gpg: pub 2048R/3388EE24 2013-03-04 Chris Nelson <superchrisnelson@gmail.com>
211
+ gpg: pub 2048R/3388EE24 2013-03-04 John Doe <jdoe@gmail.com>
212
+ gpg: using PGP trust model
213
+ gpg: key 3388EE24: public key "Chris Nelson <superchrisnelson@gmail.com>" imported
214
+ gpg: Total number processed: 1
215
+ gpg: imported: 1 (RSA: 1)
216
+ gpg: secret keys read: 1
217
+ gpg: secret keys imported: 1
218
+ '''
219
+ setup_process('gpg --batch -v --import "~/secret.pgp"', true, output)
220
+
221
+ expect(runner.import_key_from_file('~/secret.pgp')).to eq([
222
+ 'superchrisnelson@gmail.com',
223
+ 'jdoe@gmail.com'
224
+ ])
225
+
226
+ expect(Open3).to have_received(:popen2e)
227
+ end
228
+
229
+ it 'returns the recipients even when the import does not return success' do
230
+ output = '''
231
+ gpg: armor header: Version: GnuPG v1.4.12 (Darwin)
232
+ gpg: sec rsa2048/9539E22A3388EE24 2013-03-04 Chris Nelson <superchrisnelson@gmail.com>
233
+ gpg: sec rsa2048/9539E22A3388EE24 2013-03-04 John Doe <jdoe@gmail.com>
234
+ gpg: pub rsa2048/9539E22A3388EE24 2013-03-04 Chris Nelson <superchrisnelson@gmail.com>
235
+ gpg: key 9539E22A3388EE24: "Chris Nelson <superchrisnelson@gmail.com>" not changed
236
+ gpg: key 9539E22A3388EE24/9539E22A3388EE24: secret key already exists
237
+ gpg: key 9539E22A3388EE24/A09B286C349BAAD3: secret key already exists
238
+ gpg: key 9539E22A3388EE24: secret key imported
239
+ gpg: Total number processed: 1
240
+ gpg: unchanged: 1
241
+ gpg: secret keys read: 1
242
+ gpg: secret keys unchanged: 1
243
+ '''
244
+ setup_process('gpg --batch -v --import "~/secret.pgp"', false, output)
245
+
246
+ expect(runner.import_key_from_file('~/secret.pgp')).to eq([
247
+ 'superchrisnelson@gmail.com',
248
+ 'jdoe@gmail.com'
249
+ ])
250
+ end
251
+
252
+ it 'returns empty when the output is empty' do
253
+ setup_process('gpg --batch -v --import "~/secret.pgp"', false, '')
254
+
255
+ expect(runner.import_key_from_file('~/secret.pgp')).to eq([])
256
+ end
257
+ end
258
+
259
+ describe :verify_signature_file do
260
+ before { allow(File).to receive(:read) }
261
+
262
+ it 'verifies the signature contents from a file' do
263
+ setup_process('gpg --quiet --batch --verify "~/signature.asc"', true, '')
264
+
265
+ expect(runner.verify_signature_file('~/signature.asc')).to eq(true)
266
+
267
+ expect(Open3).to have_received(:popen2e)
268
+ end
269
+
270
+ it 'returns false when verification fails' do
271
+ setup_process('gpg --quiet --batch --verify "~/signature.asc"', false, '')
272
+
273
+ expect(runner.verify_signature_file('~/signature.asc')).to eq(false)
274
+ end
275
+
276
+ it 'verifies and reads the signature contents from a file' do
277
+ setup_process('gpg --quiet --batch --output "~/output.txt" "~/signature.asc"', true, '')
278
+
279
+ expect(runner.verify_signature_file('~/signature.asc', '~/output.txt')).to eq(true)
280
+
281
+ expect(Open3).to have_received(:popen2e)
282
+ end
283
+
284
+ it 'returns false when signature data read fails' do
285
+ setup_process('gpg --quiet --batch --output "~/output.txt" "~/signature.asc"', false, '')
286
+
287
+ expect(runner.verify_signature_file('~/signature.asc', '~/output.txt')).to eq(false)
288
+
289
+ expect(Open3).to have_received(:popen2e)
290
+ end
291
+ end
292
+
293
+ describe :decrypt_file do
294
+ context 'without passphrase ' do
295
+ it 'decrypts a file' do
296
+ setup_process('gpg --quiet --batch --yes --ignore-mdc-error --output "/tmp/plaintext.txt" --decrypt "~/encrypted_text.txt"', true, '')
297
+
298
+ expect(runner.decrypt_file('~/encrypted_text.txt', '/tmp/plaintext.txt')).to eq(true)
299
+
300
+ expect(Open3).to have_received(:popen2e)
301
+ end
302
+
303
+ it 'returns false when decryption failed' do
304
+ setup_process('gpg --quiet --batch --yes --ignore-mdc-error --output "/tmp/plaintext.txt" --decrypt "~/encrypted_text.txt"', false, '')
305
+
306
+ expect(runner.decrypt_file('~/encrypted_text.txt', '/tmp/plaintext.txt')).to eq(false)
307
+ end
308
+ end
309
+
310
+ context 'with passphrase' do
311
+ context 'gpg 2.0' do
312
+ before {
313
+ allow(runner).to receive(:version_default).and_return('2.0.4')
314
+ }
315
+
316
+ it 'decrypts a file' do
317
+ setup_process('gpg --quiet --batch --passphrase "supersecret111" --yes --ignore-mdc-error --output "/tmp/plaintext.txt" --decrypt "~/encrypted_text.txt"', true, '')
318
+
319
+ expect(runner.decrypt_file('~/encrypted_text.txt', '/tmp/plaintext.txt', 'supersecret111')).to eq(true)
320
+
321
+ expect(Open3).to have_received(:popen2e)
322
+ end
323
+
324
+ it 'returns false when decryption failed' do
325
+ setup_process('gpg --quiet --batch --passphrase "supersecret111" --yes --ignore-mdc-error --output "/tmp/plaintext.txt" --decrypt "~/encrypted_text.txt"', false, '')
326
+
327
+ expect(runner.decrypt_file('~/encrypted_text.txt', '/tmp/plaintext.txt', 'supersecret111')).to eq(false)
328
+ end
329
+ end
330
+
331
+ context 'gpg >= 2.1' do
332
+ before {
333
+ allow(runner).to receive(:version_default).and_return('2.1.23')
334
+ }
335
+
336
+ it 'decrypts a file' do
337
+ setup_process('gpg --quiet --batch --pinentry-mode loopback --passphrase "supersecret123" --yes --ignore-mdc-error --output "/tmp/plaintext.txt" --decrypt "~/encrypted_text.txt"', true, '')
338
+
339
+ expect(runner.decrypt_file('~/encrypted_text.txt', '/tmp/plaintext.txt', 'supersecret123')).to eq(true)
340
+
341
+ expect(Open3).to have_received(:popen2e)
342
+ end
343
+
344
+ it 'returns false when decryption failed' do
345
+ setup_process('gpg --quiet --batch --pinentry-mode loopback --passphrase "supersecret123" --yes --ignore-mdc-error --output "/tmp/plaintext.txt" --decrypt "~/encrypted_text.txt"', false, '')
346
+
347
+ expect(runner.decrypt_file('~/encrypted_text.txt', '/tmp/plaintext.txt', 'supersecret123')).to eq(false)
348
+ end
349
+ end
350
+ end
351
+ end
352
+
353
+ describe :sign_file do
354
+ context 'without passphrase' do
355
+ it 'signs a file' do
356
+ setup_process('gpg --quiet --batch --yes --ignore-mdc-error --output "/tmp/signed.txt" --sign "~/plaintext.txt"', true, '')
357
+
358
+ expect(runner.sign_file('~/plaintext.txt', '/tmp/signed.txt')).to eq(true)
359
+
360
+ expect(Open3).to have_received(:popen2e)
361
+ end
362
+
363
+ it 'returns false when signing failed' do
364
+ setup_process('gpg --quiet --batch --yes --ignore-mdc-error --output "/tmp/signed.txt" --sign "~/plaintext.txt"', false, '')
365
+
366
+ expect(runner.sign_file('~/plaintext.txt', '/tmp/signed.txt')).to eq(false)
367
+ end
368
+ end
369
+
370
+ context 'with passphrase' do
371
+ context 'gpg 2.0' do
372
+ before {
373
+ allow(runner).to receive(:version_default).and_return('2.0.4')
374
+ }
375
+
376
+ it 'signs a file' do
377
+ setup_process('gpg --quiet --batch --passphrase "supersecret111" --yes --ignore-mdc-error --output "/tmp/signed.txt" --sign "~/plaintext.txt"', true, '')
378
+
379
+ expect(runner.sign_file('~/plaintext.txt', '/tmp/signed.txt', 'supersecret111')).to eq(true)
380
+
381
+ expect(Open3).to have_received(:popen2e)
382
+ end
383
+
384
+ it 'returns false when signing failed' do
385
+ setup_process('gpg --quiet --batch --passphrase "supersecret111" --yes --ignore-mdc-error --output "/tmp/signed.txt" --sign "~/plaintext.txt"', false, '')
386
+
387
+ expect(runner.sign_file('~/plaintext.txt', '/tmp/signed.txt', 'supersecret111')).to eq(false)
388
+ end
389
+ end
390
+
391
+ context 'gpg >= 2.1' do
392
+ before {
393
+ allow(runner).to receive(:version_default).and_return('2.1.23')
394
+ }
395
+
396
+ it 'signs a file' do
397
+ setup_process('gpg --quiet --batch --pinentry-mode loopback --passphrase "supersecret123" --yes --ignore-mdc-error --output "/tmp/output.txt" --sign "~/plaintext.txt"', true, '')
398
+
399
+ expect(runner.sign_file('~/plaintext.txt', '/tmp/output.txt', 'supersecret123')).to eq(true)
400
+
401
+ expect(Open3).to have_received(:popen2e)
402
+ end
403
+
404
+ it 'returns false when signing failed' do
405
+ setup_process('gpg --quiet --batch --pinentry-mode loopback --passphrase "supersecret123" --yes --ignore-mdc-error --output "/tmp/output.txt" --sign "~/plaintext.txt"', false, '')
406
+
407
+ expect(runner.sign_file('~/plaintext.txt', '/tmp/output.txt', 'supersecret123')).to eq(false)
408
+ end
409
+ end
410
+ end
411
+ end
412
+
413
+ describe :encrypt_file do
414
+ it 'encrypts a file' do
415
+ setup_process('gpg --quiet --batch --yes --output "/tmp/out.txt" --recipient "foo@bar.com" --trust-model always --encrypt "/tmp/in.txt"', true, '')
416
+
417
+ expect(runner.encrypt_file('/tmp/in.txt', '/tmp/out.txt', ['foo@bar.com'])).to eq(true)
418
+ end
419
+
420
+ it 'encrypts a file for multiple recipients' do
421
+ setup_process('gpg --quiet --batch --yes --output "/tmp/out.txt" --recipient "foo@bar.com" --recipient "aaaa@yahoo.com" --trust-model always --encrypt "/tmp/in.txt"', true, '')
422
+
423
+ expect(runner.encrypt_file('/tmp/in.txt', '/tmp/out.txt', ['foo@bar.com', 'aaaa@yahoo.com'])).to eq(true)
424
+ end
425
+
426
+ it 'returns false when encryption failed' do
427
+ setup_process('gpg --quiet --batch --yes --output "/tmp/out.txt" --recipient "foo@bar.com" --trust-model always --encrypt "/tmp/in.txt"', false, '')
428
+
429
+ expect(runner.encrypt_file('/tmp/in.txt', '/tmp/out.txt', ['foo@bar.com'])).to eq(false)
430
+ end
431
+ end
432
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe GPG::TempPathHelper do
4
+ it 'creates a temporary file path' do
5
+ path = GPG::TempPathHelper.create
6
+
7
+ expect(path.start_with?(Dir.tmpdir)).to eq(true)
8
+ expect(File.exists?(path)).to eq(false)
9
+ end
10
+
11
+ it 'creates unique paths every time' do
12
+ paths = (1..100).map { GPG::TempPathHelper.create }
13
+
14
+ expect(paths.uniq).to eq(paths)
15
+ expect(paths.length).to eq(100)
16
+ end
17
+
18
+ it 'can receive an execution block' do
19
+ path2 = nil
20
+ path1 = GPG::TempPathHelper.create do |p|
21
+ path2 = p
22
+ end
23
+
24
+ expect(path2).to eq(path1)
25
+ end
26
+
27
+ it 'deletes the temporary file if it exists' do
28
+ path = GPG::TempPathHelper.create do |p|
29
+ File.write(p, 'test')
30
+ expect(File.exists?(p)).to eq(true)
31
+ end
32
+
33
+ expect(File.exists?(path)).to eq(false)
34
+ end
35
+
36
+ it 'deletes the temporary file even when there is an exception in the block' do
37
+ exception_raised = false
38
+ path = nil
39
+ begin
40
+ GPG::TempPathHelper.create do |p|
41
+ path = p
42
+ File.write(p, 'test')
43
+ expect(File.exists?(p)).to eq(true)
44
+ value = 45 / 0
45
+ end
46
+ rescue
47
+ exception_raised = true
48
+ end
49
+
50
+ expect(exception_raised).to eq(true)
51
+ expect(File.exists?(path)).to eq(false)
52
+ end
53
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe PGP::Signer do
4
+ include KeysHelper
5
+
6
+ let(:private_key_path) { Fixtures_Path.join('private_key_with_passphrase.asc').to_s }
7
+ let(:public_key_path) { Fixtures_Path.join('public_key_with_passphrase.asc').to_s }
8
+
9
+ let(:signer) do
10
+ signer = PGP::Signer.new
11
+ signer.passphrase = "testingpgp"
12
+ signer.add_keys_from_file(private_key_path)
13
+ signer
14
+ end
15
+
16
+ let(:unsigned_file) { Fixtures_Path.join('signed_file.txt') }
17
+ let(:unsigned_data) { File.read(unsigned_file)}
18
+ let(:signed_file) { Fixtures_Path.join('signed_file.txt.asc') }
19
+ let(:verifier) do
20
+ verifier = PGP::Verifier.new
21
+ verifier.add_keys_from_file(public_key_path)
22
+ verifier
23
+ end
24
+
25
+ before { remove_all_keys }
26
+
27
+ describe '#sign' do
28
+
29
+ it "signs" do
30
+ expect(verifier.verify(signer.sign(unsigned_data))).to eq(unsigned_data)
31
+ end
32
+
33
+ end
34
+
35
+ describe "encrypting and signing" do
36
+ let(:encryptor) { PGP::Encryptor.new(File.read public_key_path) }
37
+ let(:decryptor) do
38
+ decryptor = PGP::Decryptor.new
39
+ decryptor.passphrase = "testingpgp"
40
+ decryptor.add_keys_from_file(private_key_path)
41
+ decryptor
42
+ end
43
+ it "can decrypt and verify something that has been signed and encrypted" do
44
+ expect(verifier.verify(decryptor.decrypt(encryptor.encrypt(signer.sign("something fabulous"))))).to eq("something fabulous")
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe PGP::Verifier do
4
+ include KeysHelper
5
+
6
+ let(:verifier) { PGP::Verifier.new }
7
+ let(:unsigned_file) { Fixtures_Path.join('signed_file.txt') }
8
+ let(:signed_file) { Fixtures_Path.join('signed_file.txt.asc') }
9
+
10
+ before { remove_all_keys }
11
+
12
+ describe '#verify' do
13
+ context 'When the Public Key is from a file' do
14
+ let(:public_key_path) { Fixtures_Path.join('public_key_with_passphrase.asc').to_s }
15
+
16
+ before do
17
+ verifier.add_keys_from_file(public_key_path)
18
+ end
19
+
20
+ it "verifies" do
21
+ expect(verifier.verify(File.read(signed_file))).to eq(File.read(unsigned_file))
22
+ end
23
+ end
24
+
25
+ context 'When the public key cannot verify a signature' do
26
+ let(:public_key_path_wrong_public_key) { Fixtures_Path.join('wrong_public_key_for_signature.asc').to_s }
27
+
28
+ before do
29
+ verifier.add_keys_from_file(public_key_path_wrong_public_key)
30
+ end
31
+
32
+ it "should raise an exception" do
33
+ expect {
34
+ verifier.verify(File.read(signed_file))
35
+ }.to raise_exception 'Signature could not be verified'
36
+ end
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'RSpec multiple yields quirks' do
4
+ ##
5
+ ## I wrote this test to capture my lack of understanding on how to mock a method that yields multiple times
6
+ ##
7
+ #it 'this should work' do
8
+ # stub1 = double
9
+ # allow(stub1).to receive(:path).and_return('path1')
10
+ #
11
+ # stub2 = double
12
+ # allow(stub2).to receive(:path).and_return('path2')
13
+ #
14
+ # allow(Tempfile).to receive(:open).and_return(stub1, stub2)
15
+ #
16
+ # paths = []
17
+ # Tempfile.open do |f1|
18
+ # Tempfile.open do |f2|
19
+ # paths = [f1.path, f2.path]
20
+ # end
21
+ # end
22
+ # expect(paths).to eq(['path1', 'path2'])
23
+ #end
24
+
25
+ it 'workaround' do
26
+ stub1 = double
27
+ allow(stub1).to receive(:path).and_return('path1', 'path2')
28
+
29
+ allow(Tempfile).to receive(:open).and_yield(stub1)
30
+
31
+ paths = []
32
+ Tempfile.open do |f1|
33
+ Tempfile.open do |f2|
34
+ paths = [f1.path, f2.path]
35
+ end
36
+ end
37
+ expect(paths).to eq(['path1', 'path2'])
38
+ end
39
+ end
40
+
41
+ describe 'Nested Temp files' do
42
+ it 'can be read externally' do
43
+ file_contents1 = "3" * 300000
44
+ actual = ''
45
+
46
+ Tempfile.open do |f1|
47
+ Tempfile.open do |f2|
48
+ f1.write(file_contents1)
49
+ f1.rewind
50
+
51
+ buffer = File.read(f1.path)
52
+ f2.write(buffer)
53
+ f2.rewind
54
+
55
+ actual = File.read(f2.path)
56
+ end
57
+ end
58
+
59
+ expect(actual).to eq(file_contents1)
60
+ end
61
+
62
+ it 'can be read with its handler' do
63
+ file_contents1 = "3" * 300000
64
+ actual = ''
65
+
66
+ Tempfile.open do |f1|
67
+ Tempfile.open do |f2|
68
+ f1.write(file_contents1)
69
+ f1.rewind
70
+
71
+ buffer = f1.read
72
+ f2.write(buffer)
73
+ f2.rewind
74
+
75
+ buffer = f2.read
76
+ actual << buffer
77
+ end
78
+ end
79
+
80
+ expect(actual).to eq(file_contents1)
81
+ end
82
+
83
+ it 'can be read mixing approaches' do
84
+ file_contents1 = "3" * 300000
85
+ actual = ''
86
+
87
+ Tempfile.open do |f1|
88
+ Tempfile.open do |f2|
89
+ f1.write(file_contents1)
90
+ f1.rewind
91
+
92
+ buffer = File.read(f1.path)
93
+ File.write(f2.path, buffer)
94
+
95
+ f2.rewind
96
+ actual = f2.read
97
+ end
98
+ end
99
+
100
+ expect(actual).to eq(file_contents1)
101
+ end
102
+ end