iostreams 1.1.1 → 1.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: 1a141ad8f92a6c1387ad487fc8cf545bcc010ebc862967ffce8f79f71b7ba2d6
4
- data.tar.gz: 0210b8d23390ddff6fe31133c24b88b2beb7e5e0f54d6b9df962632dc369a9ec
3
+ metadata.gz: 56c0432a5b7820924d8e7f72df07579366ae09dae03d8abe431e5b8fbc88de2b
4
+ data.tar.gz: 73d78b153b9bfd079f9d3345f8f56eed7afec70a7fddda14f5478135faedf6d3
5
5
  SHA512:
6
- metadata.gz: 810573a43277573365e946205465a4a1cc87c65cf517450dc6f363f5bb7168e66a25cd2d891e346d09c4b96aa9166f369fd2bc9dc21ec2112d87bce270467ff2
7
- data.tar.gz: 2304155b27a897f270263283bdf499855a81f80885b9103b6c116f135904a42d73bfb29705a8156f3bde973b7a899eba9b123073e7b140a2e502b2203869ad1f
6
+ metadata.gz: 84b123abc4f78428344baa772356cfac922584ed8c03af41701c5bdcd17380283b3592c9989941b1126999a6b3dcef7367b4a0d4bbf67143ab678a24dc798ff6
7
+ data.tar.gz: 4c35ae431bc0862b47e738b04f0dd88a98661b299845f3124c08f368c3532cf03012504d0ddcd18375295dd8590ea565e5a2483244602dd88f25fca7f7ef1328
data/README.md CHANGED
@@ -5,7 +5,7 @@ Input and Output streaming for Ruby.
5
5
 
6
6
  ## Project Status
7
7
 
8
- Production Ready, but API is subject to breaking changes until V1 is released.
8
+ Production Ready.
9
9
 
10
10
  ## Features
11
11
 
@@ -180,7 +180,7 @@ module IOStreams
180
180
 
181
181
  # Deprecated
182
182
  def self.has_key?(**args)
183
- key(**args)
183
+ key?(**args)
184
184
  end
185
185
 
186
186
  # Returns [Array<Hash>] the list of keys.
@@ -327,7 +327,7 @@ module IOStreams
327
327
  def self.import_and_trust(key:)
328
328
  raise(ArgumentError, "Key cannot be empty") if key.nil? || (key == "")
329
329
 
330
- email = key_info(key: key).first.fetch(:email)
330
+ email = key_info(key: key).last.fetch(:email)
331
331
  raise(ArgumentError, "Recipient email cannot be extracted from supplied key") unless email
332
332
 
333
333
  import(key: key)
@@ -12,6 +12,11 @@ module IOStreams
12
12
  # Default: None.
13
13
  attr_writer :default_signer_passphrase
14
14
 
15
+ # Encrypt all pgp output files with this recipient for audit purposes.
16
+ # Allows the generated pgp files to be decrypted with this email address.
17
+ # Useful for audit or problem resolution purposes.
18
+ attr_accessor :audit_recipient
19
+
15
20
  private
16
21
 
17
22
  attr_reader :default_signer_passphrase
@@ -19,6 +24,7 @@ module IOStreams
19
24
 
20
25
  @default_signer_passphrase = nil
21
26
  @default_signer = nil
27
+ @audit_recipient = nil
22
28
  end
23
29
 
24
30
  # Write to a PGP / GPG file, encrypting the contents as it is written.
@@ -26,8 +32,12 @@ module IOStreams
26
32
  # file_name: [String]
27
33
  # Name of file to write to.
28
34
  #
29
- # recipient: [String]
30
- # Email of user for which to encypt the file.
35
+ # recipient: [String|Array<String>]
36
+ # One or more emails of users for which to encrypt the file.
37
+ #
38
+ # import_and_trust_key: [String|Array<String>]
39
+ # One or more pgp keys to import and then use to encrypt the file.
40
+ # Note: Ascii Keys can contain multiple keys, only the last one in the file is used.
31
41
  #
32
42
  # signer: [String]
33
43
  # Name of user with which to sign the encypted file.
@@ -46,12 +56,26 @@ module IOStreams
46
56
  # compress_level: [Integer]
47
57
  # Compression level
48
58
  # Default: 6
49
- def self.file(file_name, recipient: nil, import_and_trust_key: nil, signer: default_signer, signer_passphrase: default_signer_passphrase, compression: :zip, compress_level: 6, original_file_name: nil)
59
+ def self.file(file_name,
60
+ recipient: nil,
61
+ import_and_trust_key: nil,
62
+ signer: default_signer,
63
+ signer_passphrase: default_signer_passphrase,
64
+ compression: :zip,
65
+ compress_level: 6,
66
+ original_file_name: nil)
67
+
50
68
  raise(ArgumentError, "Requires either :recipient or :import_and_trust_key") unless recipient || import_and_trust_key
51
69
 
52
- recipient = IOStreams::Pgp.import_and_trust(key: import_and_trust_key) if import_and_trust_key
53
70
  compress_level = 0 if compression == :none
54
71
 
72
+ recipients = Array(recipient)
73
+ recipients << audit_recipient if audit_recipient
74
+
75
+ Array(import_and_trust_key).each do |key|
76
+ recipients << IOStreams::Pgp.import_and_trust(key: key)
77
+ end
78
+
55
79
  # Write to stdin, with encrypted contents being written to the file
56
80
  command = "#{IOStreams::Pgp.executable} --batch --no-tty --yes --encrypt"
57
81
  command << " --sign --local-user \"#{signer}\"" if signer
@@ -61,7 +85,8 @@ module IOStreams
61
85
  end
62
86
  command << " -z #{compress_level}" if compress_level != 6
63
87
  command << " --compress-algo #{compression}" unless compression == :none
64
- command << " --recipient \"#{recipient}\" -o \"#{file_name}\""
88
+ recipients.each { |address| command << " --recipient \"#{address}\"" }
89
+ command << " -o \"#{file_name}\""
65
90
 
66
91
  IOStreams::Pgp.logger&.debug { "IOStreams::Pgp::Writer.open: #{command}" }
67
92
 
@@ -1,3 +1,3 @@
1
1
  module IOStreams
2
- VERSION = "1.1.1".freeze
2
+ VERSION = "1.2.0".freeze
3
3
  end
@@ -52,6 +52,32 @@ class PgpWriterTest < Minitest::Test
52
52
  assert_equal decrypted, result
53
53
  end
54
54
 
55
+ it "supports multiple recipients" do
56
+ IOStreams::Pgp::Writer.file(file_name, recipient: %w[receiver@example.org receiver2@example.org], signer: "sender@example.org", signer_passphrase: "sender_passphrase") do |io|
57
+ io.write(decrypted)
58
+ end
59
+
60
+ result = IOStreams::Pgp::Reader.file(file_name, passphrase: "receiver_passphrase", &:read)
61
+ assert_equal decrypted, result
62
+
63
+ result = IOStreams::Pgp::Reader.file(file_name, passphrase: "receiver2_passphrase", &:read)
64
+ assert_equal decrypted, result
65
+ end
66
+
67
+ it "encrypts for recipient and audit recipient" do
68
+ IOStreams::Pgp::Writer.stub(:audit_recipient, "receiver2@example.org") do
69
+ IOStreams::Pgp::Writer.file(file_name, recipient: "receiver@example.org", signer: "sender@example.org", signer_passphrase: "sender_passphrase") do |io|
70
+ io.write(decrypted)
71
+ end
72
+ end
73
+
74
+ result = IOStreams::Pgp::Reader.file(file_name, passphrase: "receiver_passphrase", &:read)
75
+ assert_equal decrypted, result
76
+
77
+ result = IOStreams::Pgp::Reader.file(file_name, passphrase: "receiver2_passphrase", &:read)
78
+ assert_equal decrypted, result
79
+ end
80
+
55
81
  it "fails with bad signer passphrase" do
56
82
  skip "GnuPG v2.1 and above passes when it should not" if IOStreams::Pgp.pgp_version.to_f >= 2.1
57
83
  assert_raises IOStreams::Pgp::Failure do
@@ -32,6 +32,10 @@ unless IOStreams::Pgp.key?(email: "receiver@example.org")
32
32
  puts "Generating test PGP key: receiver@example.org"
33
33
  IOStreams::Pgp.generate_key(name: "Receiver", email: "receiver@example.org", passphrase: "receiver_passphrase", key_length: 2048)
34
34
  end
35
+ unless IOStreams::Pgp.key?(email: "receiver2@example.org")
36
+ puts "Generating test PGP key: receiver2@example.org"
37
+ IOStreams::Pgp.generate_key(name: "Receiver2", email: "receiver2@example.org", passphrase: "receiver2_passphrase", key_length: 2048)
38
+ end
35
39
 
36
40
  # Test paths
37
41
  root = File.expand_path(File.join(__dir__, "../tmp"))
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iostreams
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reid Morrison
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-04 00:00:00.000000000 Z
11
+ date: 2020-04-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email:
@@ -131,7 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
131
  - !ruby/object:Gem::Version
132
132
  version: '0'
133
133
  requirements: []
134
- rubygems_version: 3.1.2
134
+ rubygems_version: 3.0.8
135
135
  signing_key:
136
136
  specification_version: 4
137
137
  summary: Input and Output streaming for Ruby.