lib/io_streams/pgp.rb in iostreams-0.20.3 vs lib/io_streams/pgp.rb in iostreams-1.0.0.beta
- old
+ new
@@ -214,11 +214,11 @@
# date: [String]
# name: [String]
# email: [String]
def self.key_info(key:)
version_check
- command = "#{executable}"
+ command = executable.to_s
out, err, status = Open3.capture3(command, binmode: true, stdin_data: key)
logger.debug { "IOStreams::Pgp.key_info: #{command}\n#{err}#{out}" } if logger
if status.success? && out.length > 0
# Sample Output:
@@ -273,12 +273,12 @@
def self.import(key:)
version_check
command = "#{executable} --import"
out, err, status = Open3.capture3(command, binmode: true, stdin_data: key)
- logger.debug { "IOStreams::Pgp.import: #{command}\n#{err}#{out}" } if logger
- if status.success? && err.length > 0
+ logger&.debug { "IOStreams::Pgp.import: #{command}\n#{err}#{out}" }
+ if status.success? && !err.empty?
# Sample output
#
# gpg: key C16500E3: secret key imported\n"
# gpg: key C16500E3: public key "Joe Bloggs <pgp_test@iostreams.net>" imported
# gpg: Total number processed: 1
@@ -304,14 +304,30 @@
end
end
results
else
return [] if err =~ /already in secret keyring/
+
raise(Pgp::Failure, "GPG Failed importing key: #{err}#{out}")
end
end
+ # Returns [String] email for the supplied after importing and trusting the key
+ #
+ # Notes:
+ # - If the same email address has multiple keys then only the first is currently trusted.
+ def self.import_and_trust(key:)
+ raise(ArgumentError, "Key cannot be empty") if key.nil? || (key == '')
+
+ email = key_info(key: key).first.fetch(:email)
+ raise(ArgumentError, "Recipient email cannot be extracted from supplied key") unless email
+
+ import(key: key)
+ set_trust(email: email)
+ email
+ end
+
# Set the trust level for an existing key.
#
# Returns [String] output if the trust was successfully updated
# Returns nil if the email was not found
#
@@ -323,32 +339,33 @@
return unless fingerprint
command = "#{executable} --import-ownertrust"
trust = "#{fingerprint}:#{level + 1}:\n"
out, err, status = Open3.capture3(command, stdin_data: trust)
- logger.debug { "IOStreams::Pgp.set_trust: #{command}\n#{err}#{out}" } if logger
+ logger&.debug { "IOStreams::Pgp.set_trust: #{command}\n#{err}#{out}" }
if status.success?
err
else
raise(Pgp::Failure, "GPG Failed trusting key: #{err} #{out}")
end
end
# DEPRECATED - Use key_ids instead of fingerprints
def self.fingerprint(email:)
version_check
- Open3.popen2e("#{executable} --list-keys --fingerprint --with-colons #{email}") do |stdin, out, waith_thr|
+ Open3.popen2e("#{executable} --list-keys --fingerprint --with-colons #{email}") do |_stdin, out, waith_thr|
output = out.read.chomp
if waith_thr.value.success?
output.each_line do |line|
if match = line.match(/\Afpr.*::([^\:]*):\Z/)
return match[1]
end
end
nil
else
return if output =~ /(public key not found|No public key)/i
+
raise(Pgp::Failure, "GPG Failed calling #{executable} to list keys for #{email}: #{output}")
end
end
end
@@ -359,11 +376,11 @@
# Returns [String] the version of pgp currently installed
def self.pgp_version
@pgp_version ||= begin
command = "#{executable} --version"
out, err, status = Open3.capture3(command)
- logger.debug { "IOStreams::Pgp.version: #{command}\n#{err}#{out}" } if logger
+ logger&.debug { "IOStreams::Pgp.version: #{command}\n#{err}#{out}" }
if status.success?
# Sample output
# #{executable} (GnuPG) 2.0.30
# libgcrypt 1.7.6
# Copyright (C) 2015 Free Software Foundation, Inc.
@@ -381,10 +398,11 @@
if match = out.lines.first.match(/(\d+\.\d+.\d+)/)
match[1]
end
else
return [] if err =~ /(key not found|No (public|secret) key)/i
+
raise(Pgp::Failure, "GPG Failed calling #{executable} to list keys for #{email || key_id}: #{err}#{out}")
end
end
end
@@ -395,11 +413,13 @@
def self.logger
@logger
end
def self.version_check
- raise(Pgp::UnsupportedVersion, "Version #{pgp_version} of #{executable} is not yet supported. You are welcome to submit a Pull Request.") if pgp_version.to_f >= 2.3
+ if pgp_version.to_f >= 2.3
+ raise(Pgp::UnsupportedVersion, "Version #{pgp_version} of #{executable} is not yet supported. You are welcome to submit a Pull Request.")
+ end
end
# v2.2.1 output:
# pub rsa1024 2017-10-24 [SCEA]
# 18A0FC1C09C0D8AE34CE659257DC4AE323C7368C
@@ -423,11 +443,11 @@
private: match[1] == 'sec',
key_length: match[3].to_s.to_i,
key_type: match[2],
date: (Date.parse(match[4].to_s) rescue match[4])
}
- elsif match = line.match(/(pub|sec)\s+(\d+)(.*)\/(\w+)\s+(\d+-\d+-\d+)(\s+(.+)<(.+)>)?/)
+ elsif match = line.match(%r{(pub|sec)\s+(\d+)(.*)/(\w+)\s+(\d+-\d+-\d+)(\s+(.+)<(.+)>)?})
# Matches: pub 2048R/C7F9D9CB 2016-10-26
# Or: pub 2048R/C7F9D9CB 2016-10-26 Receiver <receiver@example.org>
hash = {
private: match[1] == 'sec',
key_length: match[2].to_s.to_i,
@@ -453,11 +473,10 @@
hash = {}
elsif match = line.match(/([A-Z0-9]+)/)
# v2.2 18A0FC1C09C0D8AE34CE659257DC4AE323C7368C
hash[:key_id] ||= match[1]
end
-
end
results
end
def self.delete_public_or_private_keys(email:, private: false)
@@ -465,18 +484,23 @@
list = list_keys(email: email, private: private)
return false if list.empty?
list.each do |key_info|
- if key_id = key_info[:key_id]
- command = "#{executable} --batch --no-tty --yes --delete-#{keys} #{key_id}"
- out, err, status = Open3.capture3(command, binmode: true)
- logger.debug { "IOStreams::Pgp.delete_keys: #{command}\n#{err}#{out}" } if logger
+ key_id = key_info[:key_id]
+ next unless key_id
- raise(Pgp::Failure, "GPG Failed calling #{executable} to delete #{keys} for #{email}: #{err}: #{out}") unless status.success?
- raise(Pgp::Failure, "GPG Failed to delete #{keys} for #{email} #{err.strip}:#{out}") if out.include?('error')
+ command = "#{executable} --batch --no-tty --yes --delete-#{keys} #{key_id}"
+ out, err, status = Open3.capture3(command, binmode: true)
+ logger&.debug { "IOStreams::Pgp.delete_keys: #{command}\n#{err}#{out}" }
+
+ unless status.success?
+ raise(Pgp::Failure, "GPG Failed calling #{executable} to delete #{keys} for #{email}: #{err}: #{out}")
end
+ if out.include?('error')
+ raise(Pgp::Failure, "GPG Failed to delete #{keys} for #{email} #{err.strip}:#{out}")
+ end
end
true
end
def self.delete_public_or_private_keys_v1(email:, private: false)
@@ -485,15 +509,19 @@
command = "for i in `#{executable} --list-#{keys} --with-colons --fingerprint #{email} | grep \"^fpr\" | cut -d: -f10`; do\n"
command << "#{executable} --batch --no-tty --yes --delete-#{keys} \"$i\" ;\n"
command << 'done'
out, err, status = Open3.capture3(command, binmode: true)
- logger.debug { "IOStreams::Pgp.delete_keys: #{command}\n#{err}: #{out}" } if logger
+ logger&.debug { "IOStreams::Pgp.delete_keys: #{command}\n#{err}: #{out}" }
return false if err =~ /(not found|no public key)/i
- raise(Pgp::Failure, "GPG Failed calling #{executable} to delete #{keys} for #{email}: #{err}: #{out}") unless status.success?
- raise(Pgp::Failure, "GPG Failed to delete #{keys} for #{email} #{err.strip}: #{out}") if out.include?('error')
+ unless status.success?
+ raise(Pgp::Failure, "GPG Failed calling #{executable} to delete #{keys} for #{email}: #{err}: #{out}")
+ end
+ if out.include?('error')
+ raise(Pgp::Failure, "GPG Failed to delete #{keys} for #{email} #{err.strip}: #{out}")
+ end
+
true
end
-
end
end