class IOStreams::Pgp::Writer

Attributes

audit_recipient[RW]

Encrypt all pgp output files with this recipient for audit purposes. Allows the generated pgp files to be decrypted with this email address. Useful for audit or problem resolution purposes.

default_signer[RW]

Sign all encrypted files with this users key. Default: Do not sign encrypted files.

default_signer_passphrase[RW]

Passphrase to use to open the private key when signing the file. Default: None.

Public Class Methods

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) { |stdin| ... } click to toggle source

Write to a PGP / GPG file, encrypting the contents as it is written.

file_name: [String]

Name of file to write to.

recipient: [String|Array<String>]

One or more emails of users for which to encrypt the file.

import_and_trust_key: [String|Array<String>]

One or more pgp keys to import and then use to encrypt the file.
Note: Ascii Keys can contain multiple keys, only the last one in the file is used.

signer: [String]

Name of user with which to sign the encypted file.
Default: default_signer or do not sign.

signer_passphrase: [String]

Passphrase to use to open the private key when signing the file.
Default: default_signer_passphrase

compression: [:none|:zip|:zlib|:bzip2]

Note: Standard PGP only supports :zip.
:zlib is better than zip.
:bzip2 is best, but uses a lot of memory and is much slower.
Default: :zip

compress_level: [Integer]

Compression level
Default: 6
# File lib/io_streams/pgp/writer.rb, line 58
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)

  raise(ArgumentError, "Requires either :recipient or :import_and_trust_key") unless recipient || import_and_trust_key

  compress_level = 0 if compression == :none

  recipients = Array(recipient)
  recipients << audit_recipient if audit_recipient

  Array(import_and_trust_key).each do |key|
    recipients << IOStreams::Pgp.import_and_trust(key: key)
  end

  # Write to stdin, with encrypted contents being written to the file
  command = "#{IOStreams::Pgp.executable} --batch --no-tty --yes --encrypt"
  command << " --sign --local-user \"#{signer}\"" if signer
  if signer_passphrase
    command << " --pinentry-mode loopback" if IOStreams::Pgp.pgp_version.to_f >= 2.1
    command << " --passphrase \"#{signer_passphrase}\""
  end
  command << " -z #{compress_level}" if compress_level != 6
  command << " --compress-algo #{compression}" unless compression == :none
  recipients.each { |address| command << " --recipient \"#{address}\"" }
  command << " -o \"#{file_name}\""

  IOStreams::Pgp.logger&.debug { "IOStreams::Pgp::Writer.open: #{command}" }

  result = nil
  Open3.popen2e(command) do |stdin, out, waith_thr|
    begin
      stdin.binmode
      result = yield(stdin)
      stdin.close
    rescue Errno::EPIPE
      # Ignore broken pipe because gpg terminates early due to an error
      ::File.delete(file_name) if ::File.exist?(file_name)
      raise(Pgp::Failure, "GPG Failed writing to encrypted file: #{file_name}: #{out.read.chomp}")
    end
    unless waith_thr.value.success?
      ::File.delete(file_name) if ::File.exist?(file_name)
      raise(Pgp::Failure, "GPG Failed to create encrypted file: #{file_name}: #{out.read.chomp}")
    end
  end
  result
end