iostreams 0.11.0 → 0.12.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/lib/io_streams/pgp.rb +255 -83
- data/lib/io_streams/version.rb +1 -1
- data/lib/iostreams.rb +1 -0
- data/test/pgp_test.rb +238 -0
- data/test/zip_writer_test.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4dcddf28ba98342cec548ede58e83e08f6d4948
|
4
|
+
data.tar.gz: 0fd6ff53b81dc4fdd8847f5c646d875aa03f7c4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09453fc367c6d133311676971c31e9135549559995f2ffbcb9960bfd6054121344c6c6b5d7eb85bfb993b1531a8d70a7299659bceb0cffb12805b9ce823ac035'
|
7
|
+
data.tar.gz: afb3e83e545230f98a6e2acf936e937d20fdc3a753607aae039788daae426cd0bbd03d5018272e0c179512b7e4b55e6a9fcc8af2ad4b83b43aa05996630de446
|
data/lib/io_streams/pgp.rb
CHANGED
@@ -62,8 +62,8 @@ module IOStreams
|
|
62
62
|
# Select highest level: 5
|
63
63
|
#
|
64
64
|
# Delete test keys:
|
65
|
-
# IOStreams::Pgp.delete_keys(email: 'sender@example.org',
|
66
|
-
# IOStreams::Pgp.delete_keys(email: 'receiver@example.org',
|
65
|
+
# IOStreams::Pgp.delete_keys(email: 'sender@example.org', private: true)
|
66
|
+
# IOStreams::Pgp.delete_keys(email: 'receiver@example.org', private: true)
|
67
67
|
#
|
68
68
|
# Limitations
|
69
69
|
# - Designed for processing larger files since a process is spawned for each file processed.
|
@@ -84,9 +84,13 @@ module IOStreams
|
|
84
84
|
class Failure < StandardError
|
85
85
|
end
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
class UnsupportedVersion < Failure
|
88
|
+
end
|
89
|
+
|
90
|
+
# Generate a new ultimate trusted local public and private key.
|
91
|
+
#
|
92
|
+
# Returns [String] the key id for the generated key.
|
93
|
+
# Raises an exception if it fails to generate the key.
|
90
94
|
#
|
91
95
|
# name: [String]
|
92
96
|
# Name of who owns the key, such as organization
|
@@ -105,126 +109,197 @@ module IOStreams
|
|
105
109
|
#
|
106
110
|
# See `man gpg` for the remaining options
|
107
111
|
def self.generate_key(name:, email:, comment: nil, passphrase: nil, key_type: 'RSA', key_length: 4096, subkey_type: 'RSA', subkey_length: key_length, expire_date: nil)
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
end
|
126
|
-
end
|
127
|
-
key_id
|
128
|
-
else
|
129
|
-
raise(Pgp::Failure, "GPG Failed to generate key: #{out.read.chomp}")
|
112
|
+
version_check
|
113
|
+
params = ''
|
114
|
+
params << "Key-Type: #{key_type}\n" if key_type
|
115
|
+
params << "Key-Length: #{key_length}\n" if key_length
|
116
|
+
params << "Subkey-Type: #{subkey_type}\n" if subkey_type
|
117
|
+
params << "Subkey-Length: #{subkey_length}\n" if subkey_length
|
118
|
+
params << "Name-Real: #{name}\n" if name
|
119
|
+
params << "Name-Comment: #{comment}\n" if comment
|
120
|
+
params << "Name-Email: #{email}\n" if email
|
121
|
+
params << "Expire-Date: #{expire_date}\n" if expire_date
|
122
|
+
params << "Passphrase: #{passphrase}\n" if passphrase
|
123
|
+
params << '%commit'
|
124
|
+
out, err, status = Open3.capture3('gpg --batch --gen-key', binmode: true, stdin_data: params)
|
125
|
+
logger.debug { "IOStreams::Pgp.generate_key output:\n#{out}#{err}" } if logger
|
126
|
+
if status.success?
|
127
|
+
if match = err.match(/gpg: key ([0-9A-F]+)\s+/)
|
128
|
+
return match[1]
|
130
129
|
end
|
130
|
+
else
|
131
|
+
raise(Pgp::Failure, "GPG Failed to generate key: #{out}#{err}")
|
131
132
|
end
|
132
133
|
end
|
133
134
|
|
134
|
-
# Delete
|
135
|
-
# Returns false if no key was found
|
136
|
-
# Raises an exception if it fails to delete the key
|
135
|
+
# Delete all private and public keys for a particular email.
|
137
136
|
#
|
138
|
-
#
|
137
|
+
# Returns false if no key was found.
|
138
|
+
# Raises an exception if it fails to delete the key.
|
139
|
+
#
|
140
|
+
# email: [String] Email address for the key.
|
139
141
|
#
|
140
142
|
# public: [true|false]
|
141
143
|
# Whether to delete the public key
|
142
144
|
# Default: true
|
143
145
|
#
|
144
|
-
#
|
145
|
-
# Whether to delete the
|
146
|
+
# private: [true|false]
|
147
|
+
# Whether to delete the private key
|
146
148
|
# Default: false
|
147
|
-
def self.delete_keys(email:, public: true,
|
149
|
+
def self.delete_keys(email:, public: true, private: false)
|
150
|
+
version_check
|
148
151
|
cmd = "for i in `gpg --with-colons --fingerprint #{email} | grep \"^fpr\" | cut -d: -f10`; do\n"
|
149
|
-
cmd << "gpg --batch --delete-secret-keys \"$i\" ;\n" if
|
152
|
+
cmd << "gpg --batch --delete-secret-keys \"$i\" ;\n" if private
|
150
153
|
cmd << "gpg --batch --delete-keys \"$i\" ;\n" if public
|
151
154
|
cmd << 'done'
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
155
|
+
|
156
|
+
out, err, status = Open3.capture3(cmd, binmode: true)
|
157
|
+
logger.debug { "IOStreams::Pgp.delete_keys output:\n#{err}#{out}" } if logger
|
158
|
+
|
159
|
+
if status.success?
|
160
|
+
return false if err =~ /(not found|No public key)/i
|
161
|
+
raise(Pgp::Failure, "GPG Failed to delete keys for #{email}:#{err}#{out}") if out.include?('error')
|
162
|
+
true
|
163
|
+
else
|
164
|
+
raise(Pgp::Failure, "GPG Failed calling gpg to delete private keys for #{email}: #{err}#{out}")
|
161
165
|
end
|
162
166
|
end
|
163
167
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
168
|
+
# Returns [true|false] whether their is a key for the supplied email or key_id
|
169
|
+
def self.has_key?(email: nil, key_id: nil, private: false)
|
170
|
+
raise(ArgumentError, 'Either :email, or :key_id must be supplied') if email.nil? && key_id.nil?
|
171
|
+
|
172
|
+
!list_keys(email: email, key_id: key_id, private: private).empty?
|
173
|
+
end
|
174
|
+
|
175
|
+
# Returns [Array<Hash>] the list of keys.
|
176
|
+
# Each Hash consists of:
|
177
|
+
# key_length: [Integer]
|
178
|
+
# key_type: [String]
|
179
|
+
# key_id: [String]
|
180
|
+
# date: [String]
|
181
|
+
# name: [String]
|
182
|
+
# email: [String]
|
183
|
+
# Returns [] if no keys were found.
|
184
|
+
def self.list_keys(email: nil, key_id: nil, private: false)
|
185
|
+
version_check
|
186
|
+
cmd = private ? '--list-secret-keys' : '--list-keys'
|
187
|
+
out, err, status = Open3.capture3("gpg #{cmd} #{email || key_id}", binmode: true)
|
188
|
+
logger.debug { "IOStreams::Pgp.list_keys output:\n#{err}#{out}" } if logger
|
189
|
+
if status.success? && out.length > 0
|
190
|
+
# Sample output
|
191
|
+
# pub 4096R/3A5456F5 2017-06-07
|
192
|
+
# uid [ unknown] Joe Bloggs <j@bloggs.net>
|
193
|
+
# sub 4096R/2C9B240B 2017-06-07
|
194
|
+
parse_list_output(out)
|
195
|
+
else
|
196
|
+
return [] if err =~ /(key not found|No (public|secret) key)/i
|
197
|
+
raise(Pgp::Failure, "GPG Failed calling gpg to list keys for #{email || key_id}: #{err}#{out}")
|
176
198
|
end
|
177
199
|
end
|
178
200
|
|
179
|
-
#
|
180
|
-
#
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
201
|
+
# Extract information from the supplied key.
|
202
|
+
#
|
203
|
+
# Useful for confirming encryption keys before importing them.
|
204
|
+
#
|
205
|
+
# Returns [Array<Hash>] the list of primary keys.
|
206
|
+
# Each Hash consists of:
|
207
|
+
# key_length: [Integer]
|
208
|
+
# key_type: [String]
|
209
|
+
# key_id: [String]
|
210
|
+
# date: [String]
|
211
|
+
# name: [String]
|
212
|
+
# email: [String]
|
213
|
+
def self.key_info(key:)
|
214
|
+
version_check
|
215
|
+
out, err, status = Open3.capture3('gpg', binmode: true, stdin_data: key)
|
216
|
+
logger.debug { "IOStreams::Pgp.key_info output:\n#{err}#{out}" } if logger
|
217
|
+
if status.success? && out.length > 0
|
218
|
+
# Sample Output:
|
219
|
+
#
|
220
|
+
# pub 4096R/3A5456F5 2017-06-07
|
221
|
+
# uid Joe Bloggs <j@bloggs.net>
|
222
|
+
# sub 4096R/2C9B240B 2017-06-07
|
223
|
+
parse_list_output(out)
|
224
|
+
else
|
225
|
+
raise(Pgp::Failure, "GPG Failed extracting key details: #{err} #{out}")
|
195
226
|
end
|
196
227
|
end
|
197
228
|
|
198
|
-
# Returns [String] the
|
229
|
+
# Returns [String] containing all the keys for the supplied email address.
|
199
230
|
#
|
200
|
-
# email: [String] Email address for requested key
|
231
|
+
# email: [String] Email address for requested key.
|
201
232
|
#
|
202
233
|
# ascii: [true|false]
|
203
234
|
# Whether to export as ASCII text instead of binary format
|
204
235
|
# Default: true
|
205
236
|
#
|
206
|
-
#
|
237
|
+
# private: [true|false]
|
207
238
|
# Whether to export the private key
|
208
239
|
# Default: false
|
209
|
-
def self.export(email:, ascii: true,
|
240
|
+
def self.export(email:, ascii: true, private: false)
|
241
|
+
version_check
|
210
242
|
armor = ascii ? ' --armor' : nil
|
211
|
-
cmd =
|
243
|
+
cmd = private ? '--export-secret-keys' : '--export'
|
212
244
|
out, err, status = Open3.capture3("gpg#{armor} #{cmd} #{email}", binmode: true)
|
245
|
+
logger.debug { "IOStreams::Pgp.export output:\n#{err}" } if logger
|
213
246
|
if status.success? && out.length > 0
|
214
247
|
out
|
215
248
|
else
|
216
|
-
raise(Pgp::Failure, "GPG Failed reading key: #{email}: #{err}
|
249
|
+
raise(Pgp::Failure, "GPG Failed reading key: #{email}: #{err}")
|
217
250
|
end
|
218
251
|
end
|
219
252
|
|
220
253
|
# Imports the supplied public/private key
|
221
|
-
#
|
222
|
-
|
254
|
+
#
|
255
|
+
# Returns [Array<Hash>] keys that were successfully imported.
|
256
|
+
# Each Hash consists of:
|
257
|
+
# key_id: [String]
|
258
|
+
# type: [String]
|
259
|
+
# name: [String]
|
260
|
+
# email: [String]
|
261
|
+
# Returns [] if the same key was previously imported.
|
262
|
+
#
|
263
|
+
# Raises Pgp::Failure if there was an issue importing any of the keys.
|
264
|
+
#
|
265
|
+
# Notes:
|
266
|
+
# * Importing a new key for the same email address does not remove the prior key if any.
|
267
|
+
# * Invalidated keys must be removed manually.
|
268
|
+
def self.import(key:)
|
269
|
+
version_check
|
223
270
|
out, err, status = Open3.capture3('gpg --import', binmode: true, stdin_data: key)
|
224
|
-
|
225
|
-
|
271
|
+
logger.debug { "IOStreams::Pgp.import output:\n#{err}#{out}" } if logger
|
272
|
+
if status.success? && err.length > 0
|
273
|
+
# Sample output
|
274
|
+
#
|
275
|
+
# gpg: key C16500E3: secret key imported\n"
|
276
|
+
# gpg: key C16500E3: public key "Joe Bloggs <pgp_test@iostreams.net>" imported
|
277
|
+
# gpg: Total number processed: 1
|
278
|
+
# gpg: imported: 1 (RSA: 1)
|
279
|
+
# gpg: secret keys read: 1
|
280
|
+
# gpg: secret keys imported: 1
|
281
|
+
#
|
282
|
+
# Ignores unchanged:
|
283
|
+
# gpg: key 9615D46D: \"Joe Bloggs <j@bloggs.net>\" not changed\n
|
284
|
+
results = []
|
285
|
+
secret = false
|
286
|
+
err.each_line do |line|
|
287
|
+
if line =~ /secret key imported/
|
288
|
+
secret = true
|
289
|
+
elsif match = line.match(/key\s+(\w+):\s+(\w+).+\"(.*)<(.*)>\"/)
|
290
|
+
results << {
|
291
|
+
key_id: match[1].to_s.strip,
|
292
|
+
private: secret,
|
293
|
+
name: match[3].to_s.strip,
|
294
|
+
email: match[4].to_s.strip
|
295
|
+
}
|
296
|
+
secret = false
|
297
|
+
end
|
298
|
+
end
|
299
|
+
results
|
226
300
|
else
|
227
|
-
|
301
|
+
return [] if err =~ /already in secret keyring/
|
302
|
+
raise(Pgp::Failure, "GPG Failed importing key: #{err}#{out}")
|
228
303
|
end
|
229
304
|
end
|
230
305
|
|
@@ -236,11 +311,13 @@ module IOStreams
|
|
236
311
|
# After importing keys, they are not trusted and the relevant trust level must be set.
|
237
312
|
# Default: 5 : Ultimate
|
238
313
|
def self.set_trust(email:, level: 5)
|
314
|
+
version_check
|
239
315
|
fingerprint = fingerprint(email: email)
|
240
316
|
return unless fingerprint
|
241
317
|
|
242
318
|
trust = "#{fingerprint}:#{level + 1}:\n"
|
243
319
|
out, err, status = Open3.capture3('gpg --import-ownertrust', stdin_data: trust)
|
320
|
+
logger.debug { "IOStreams::Pgp.set_trust output:\n#{err}#{out}" } if logger
|
244
321
|
if status.success?
|
245
322
|
err
|
246
323
|
else
|
@@ -248,5 +325,100 @@ module IOStreams
|
|
248
325
|
end
|
249
326
|
end
|
250
327
|
|
328
|
+
# DEPRECATED - Use key_ids instead of fingerprints
|
329
|
+
def self.fingerprint(email:)
|
330
|
+
version_check
|
331
|
+
Open3.popen2e("gpg --list-keys --fingerprint --with-colons #{email}") do |stdin, out, waith_thr|
|
332
|
+
output = out.read.chomp
|
333
|
+
if waith_thr.value.success?
|
334
|
+
output.each_line do |line|
|
335
|
+
if match = line.match(/\Afpr.*::([^\:]*):\Z/)
|
336
|
+
return match[1]
|
337
|
+
end
|
338
|
+
end
|
339
|
+
nil
|
340
|
+
else
|
341
|
+
return if output =~ /(public key not found|No public key)/i
|
342
|
+
raise(Pgp::Failure, "GPG Failed calling gpg to list keys for #{email}: #{output}")
|
343
|
+
end
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
def self.logger=(logger)
|
348
|
+
@logger = logger
|
349
|
+
end
|
350
|
+
|
351
|
+
# Returns [String] the version of pgp currently installed
|
352
|
+
def self.pgp_version
|
353
|
+
@pgp_version ||= begin
|
354
|
+
out, err, status = Open3.capture3("gpg --version")
|
355
|
+
logger.debug { "IOStreams::Pgp.version output:\n#{err}#{out}" } if logger
|
356
|
+
if status.success?
|
357
|
+
# Sample output
|
358
|
+
# gpg (GnuPG) 2.0.30
|
359
|
+
# libgcrypt 1.7.6
|
360
|
+
# Copyright (C) 2015 Free Software Foundation, Inc.
|
361
|
+
# License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
|
362
|
+
# This is free software: you are free to change and redistribute it.
|
363
|
+
# There is NO WARRANTY, to the extent permitted by law.
|
364
|
+
#
|
365
|
+
# Home: ~/.gnupg
|
366
|
+
# Supported algorithms:
|
367
|
+
# Pubkey: RSA, RSA, RSA, ELG, DSA
|
368
|
+
# Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
|
369
|
+
# CAMELLIA128, CAMELLIA192, CAMELLIA256
|
370
|
+
# Hash: MD5, SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
|
371
|
+
# Compression: Uncompressed, ZIP, ZLIB, BZIP2
|
372
|
+
if match = out.lines.first.match(/(\d+\.\d+.\d+)/)
|
373
|
+
match[1]
|
374
|
+
end
|
375
|
+
else
|
376
|
+
return [] if err =~ /(key not found|No (public|secret) key)/i
|
377
|
+
raise(Pgp::Failure, "GPG Failed calling gpg to list keys for #{email || key_id}: #{err}#{out}")
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
private
|
383
|
+
|
384
|
+
@logger = nil
|
385
|
+
|
386
|
+
def self.logger
|
387
|
+
@logger
|
388
|
+
end
|
389
|
+
|
390
|
+
def self.version_check
|
391
|
+
raise(Pgp::UnsupportedVersion, "Version #{pgp_version} of gpg is not yet supported. You are welcome to submit a Pull Request.") if pgp_version.to_f >= 2.1
|
392
|
+
end
|
393
|
+
|
394
|
+
def self.parse_list_output(out)
|
395
|
+
results = []
|
396
|
+
hash = {}
|
397
|
+
out.each_line do |line|
|
398
|
+
if match = line.match(/(pub|sec)\s+(\d+)(.*)\/(\w+)\s+(\S+)/)
|
399
|
+
hash = {
|
400
|
+
private: match[1] == 'sec',
|
401
|
+
key_length: match[2].to_s.to_i,
|
402
|
+
key_type: match[3],
|
403
|
+
key_id: match[4],
|
404
|
+
date: (Date.parse(match[5].to_s) rescue match[5])
|
405
|
+
}
|
406
|
+
elsif match = line.match(/uid\s+(.+)<(.+)>/)
|
407
|
+
name = match[1].strip
|
408
|
+
hash[:email] = match[2].strip
|
409
|
+
if match = name.match(/(\[(.+)\])?(.+)/)
|
410
|
+
trust = match[2].to_s.strip
|
411
|
+
hash[:trust] = trust unless trust.empty?
|
412
|
+
hash[:name] = match[3].to_s.strip
|
413
|
+
else
|
414
|
+
hash[:name] = name
|
415
|
+
end
|
416
|
+
results << hash
|
417
|
+
hash = {}
|
418
|
+
end
|
419
|
+
end
|
420
|
+
results
|
421
|
+
end
|
422
|
+
|
251
423
|
end
|
252
424
|
end
|
data/lib/io_streams/version.rb
CHANGED
data/lib/iostreams.rb
CHANGED
data/test/pgp_test.rb
ADDED
@@ -0,0 +1,238 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
#IOStreams::Pgp.logger = SemanticLogger[IOStreams::Pgp]
|
4
|
+
|
5
|
+
module Streams
|
6
|
+
class PgpTest < Minitest::Test
|
7
|
+
describe IOStreams::Pgp::Reader do
|
8
|
+
let :user_name do
|
9
|
+
'Joe Bloggs'
|
10
|
+
end
|
11
|
+
|
12
|
+
let :email do
|
13
|
+
'pgp_test@iostreams.net'
|
14
|
+
end
|
15
|
+
|
16
|
+
let :generated_key_id do
|
17
|
+
IOStreams::Pgp.generate_key(name: user_name, email: email, key_length: 1024)
|
18
|
+
end
|
19
|
+
|
20
|
+
let :public_key do
|
21
|
+
generated_key_id
|
22
|
+
IOStreams::Pgp.export(email: email)
|
23
|
+
end
|
24
|
+
|
25
|
+
let :private_key do
|
26
|
+
generated_key_id
|
27
|
+
IOStreams::Pgp.export(email: email, private: true)
|
28
|
+
end
|
29
|
+
|
30
|
+
before do
|
31
|
+
IOStreams::Pgp.delete_keys(email: email, public: true, private: true)
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '.pgp_version' do
|
35
|
+
it 'returns pgp version' do
|
36
|
+
assert IOStreams::Pgp.pgp_version
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '.generate_key' do
|
41
|
+
it 'returns the key id' do
|
42
|
+
assert generated_key_id
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '.has_key?' do
|
47
|
+
before do
|
48
|
+
generated_key_id
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'confirms public key' do
|
52
|
+
assert IOStreams::Pgp.has_key?(key_id: generated_key_id)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'confirms private key' do
|
56
|
+
assert IOStreams::Pgp.has_key?(key_id: generated_key_id, private: true)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '.delete_keys' do
|
61
|
+
it 'handles no keys' do
|
62
|
+
refute IOStreams::Pgp.delete_keys(email: 'random@iostreams.net', public: true, private: true)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'deletes existing keys' do
|
66
|
+
generated_key_id
|
67
|
+
assert IOStreams::Pgp.delete_keys(email: email, public: true, private: true)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'deletes just the private key' do
|
71
|
+
generated_key_id
|
72
|
+
assert IOStreams::Pgp.delete_keys(email: email, public: false, private: true)
|
73
|
+
refute IOStreams::Pgp.has_key?(key_id: generated_key_id, private: true)
|
74
|
+
assert IOStreams::Pgp.has_key?(key_id: generated_key_id, private: false)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '.export' do
|
79
|
+
before do
|
80
|
+
generated_key_id
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'exports public keys by email' do
|
84
|
+
assert ascii_keys = IOStreams::Pgp.export(email: email)
|
85
|
+
assert ascii_keys =~ /BEGIN PGP PUBLIC KEY BLOCK/, ascii_keys
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'exports private keys by email' do
|
89
|
+
assert ascii_keys = IOStreams::Pgp.export(email: email, private: true)
|
90
|
+
assert ascii_keys =~ /BEGIN PGP PRIVATE KEY BLOCK/, ascii_keys
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'exports public keys as binary' do
|
94
|
+
assert keys = IOStreams::Pgp.export(email: email, ascii: false)
|
95
|
+
refute keys =~ /BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK/, keys
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'exports private keys as binary' do
|
99
|
+
assert keys = IOStreams::Pgp.export(email: email, ascii: false, private: true)
|
100
|
+
refute keys =~ /BEGIN PGP (PUBLIC|PRIVATE) KEY BLOCK/, keys
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe '.list_keys' do
|
105
|
+
before do
|
106
|
+
generated_key_id
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'lists public keys' do
|
110
|
+
assert keys = IOStreams::Pgp.list_keys(email: email)
|
111
|
+
assert_equal 1, keys.size
|
112
|
+
assert key = keys.first
|
113
|
+
|
114
|
+
assert_equal key[:date], Date.today
|
115
|
+
assert_equal email, key[:email]
|
116
|
+
assert_equal generated_key_id, key[:key_id]
|
117
|
+
assert_equal 1024, key[:key_length]
|
118
|
+
assert_equal 'R', key[:key_type]
|
119
|
+
assert_equal user_name, key[:name]
|
120
|
+
refute key[:private], key
|
121
|
+
assert_equal 'ultimate', key[:trust]
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'lists private keys' do
|
125
|
+
assert keys = IOStreams::Pgp.list_keys(email: email, private: true)
|
126
|
+
assert_equal 1, keys.size
|
127
|
+
assert key = keys.first
|
128
|
+
|
129
|
+
assert_equal key[:date], Date.today
|
130
|
+
assert_equal email, key[:email]
|
131
|
+
assert_equal generated_key_id, key[:key_id]
|
132
|
+
assert_equal 1024, key[:key_length]
|
133
|
+
assert_equal 'R', key[:key_type]
|
134
|
+
assert_equal user_name, key[:name]
|
135
|
+
assert key[:private], key
|
136
|
+
refute key.key?(:trust)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe '.key_info' do
|
141
|
+
it 'extracts public key info' do
|
142
|
+
assert keys = IOStreams::Pgp.key_info(key: public_key)
|
143
|
+
assert_equal 1, keys.size
|
144
|
+
assert key = keys.first
|
145
|
+
|
146
|
+
assert_equal key[:date], Date.today
|
147
|
+
assert_equal email, key[:email]
|
148
|
+
assert_equal generated_key_id, key[:key_id]
|
149
|
+
assert_equal 1024, key[:key_length]
|
150
|
+
assert_equal 'R', key[:key_type]
|
151
|
+
assert_equal user_name, key[:name]
|
152
|
+
refute key[:private], key
|
153
|
+
refute key.key?(:trust)
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'extracts private key info' do
|
157
|
+
assert keys = IOStreams::Pgp.key_info(key: private_key)
|
158
|
+
assert_equal 1, keys.size
|
159
|
+
assert key = keys.first
|
160
|
+
|
161
|
+
assert_equal key[:date], Date.today
|
162
|
+
assert_equal email, key[:email]
|
163
|
+
assert_equal generated_key_id, key[:key_id]
|
164
|
+
assert_equal 1024, key[:key_length]
|
165
|
+
assert_equal 'R', key[:key_type]
|
166
|
+
assert_equal user_name, key[:name]
|
167
|
+
assert key[:private], key
|
168
|
+
refute key.key?(:trust)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe '.import' do
|
173
|
+
it 'handle duplicate public key' do
|
174
|
+
generated_key_id
|
175
|
+
assert_equal [], IOStreams::Pgp.import(key: public_key)
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'handle duplicate private key' do
|
179
|
+
generated_key_id
|
180
|
+
assert_equal [], IOStreams::Pgp.import(key: private_key)
|
181
|
+
end
|
182
|
+
|
183
|
+
describe 'without keys' do
|
184
|
+
before do
|
185
|
+
@public_key = public_key
|
186
|
+
@private_key = private_key
|
187
|
+
IOStreams::Pgp.delete_keys(email: email, public: true, private: true)
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'imports ascii public key' do
|
191
|
+
assert keys = IOStreams::Pgp.import(key: @public_key)
|
192
|
+
assert_equal 1, keys.size
|
193
|
+
assert key = keys.first
|
194
|
+
|
195
|
+
assert_equal email, key[:email]
|
196
|
+
assert_equal generated_key_id, key[:key_id]
|
197
|
+
assert_equal user_name, key[:name]
|
198
|
+
refute key[:private], key
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'imports ascii private key' do
|
202
|
+
assert keys = IOStreams::Pgp.import(key: @private_key)
|
203
|
+
assert_equal 1, keys.size
|
204
|
+
assert key = keys.first
|
205
|
+
|
206
|
+
assert_equal email, key[:email]
|
207
|
+
assert_equal generated_key_id, key[:key_id]
|
208
|
+
assert_equal user_name, key[:name]
|
209
|
+
assert key[:private], key
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'imports binary public key' do
|
213
|
+
assert keys = IOStreams::Pgp.import(key: @public_key)
|
214
|
+
assert_equal 1, keys.size
|
215
|
+
assert key = keys.first
|
216
|
+
|
217
|
+
assert_equal email, key[:email]
|
218
|
+
assert_equal generated_key_id, key[:key_id]
|
219
|
+
assert_equal user_name, key[:name]
|
220
|
+
refute key[:private], key
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'imports binary private key' do
|
224
|
+
assert keys = IOStreams::Pgp.import(key: @private_key)
|
225
|
+
assert_equal 1, keys.size
|
226
|
+
assert key = keys.first
|
227
|
+
|
228
|
+
assert_equal email, key[:email]
|
229
|
+
assert_equal generated_key_id, key[:key_id]
|
230
|
+
assert_equal user_name, key[:name]
|
231
|
+
assert key[:private], key
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
data/test/zip_writer_test.rb
CHANGED
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: 0.
|
4
|
+
version: 0.12.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: 2017-
|
11
|
+
date: 2017-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- test/gzip_writer_test.rb
|
70
70
|
- test/io_streams_test.rb
|
71
71
|
- test/pgp_reader_test.rb
|
72
|
+
- test/pgp_test.rb
|
72
73
|
- test/pgp_writer_test.rb
|
73
74
|
- test/test_helper.rb
|
74
75
|
- test/xlsx_reader_test.rb
|
@@ -116,6 +117,7 @@ test_files:
|
|
116
117
|
- test/gzip_writer_test.rb
|
117
118
|
- test/io_streams_test.rb
|
118
119
|
- test/pgp_reader_test.rb
|
120
|
+
- test/pgp_test.rb
|
119
121
|
- test/pgp_writer_test.rb
|
120
122
|
- test/test_helper.rb
|
121
123
|
- test/xlsx_reader_test.rb
|