module Rgpg::GpgHelper

Public Class Methods

decrypt_file(public_key_file_name, private_key_file_name, input_file_name, output_file_name, passphrase=nil) click to toggle source
# File lib/rgpg/gpg_helper.rb, line 43
def self.decrypt_file(public_key_file_name, private_key_file_name, input_file_name, output_file_name, passphrase=nil)
  raise ArgumentError.new("Public key file \"#{public_key_file_name}\" does not exist") unless File.exist?(public_key_file_name)
  raise ArgumentError.new("Private key file \"#{private_key_file_name}\" does not exist") unless File.exist?(private_key_file_name)
  raise ArgumentError.new("Input file \"#{input_file_name}\" does not exist") unless File.exist?(input_file_name)

  recipient = get_recipient(private_key_file_name)
  with_temporary_decrypt_keyrings(public_key_file_name, private_key_file_name) do |keyring_file_name, secret_keyring_file_name|
    args = '--keyring', keyring_file_name,
           '--secret-keyring', secret_keyring_file_name,
           '--output', output_file_name,
           '--decrypt',
           '--yes',
           '--trust-model', 'always',
           '--no-tty',
           input_file_name
    args.unshift '--passphrase', passphrase unless passphrase.nil?
    run_gpg_capture(*args)
  end
end
encrypt_file(public_key_file_name, input_file_name, output_file_name) click to toggle source
# File lib/rgpg/gpg_helper.rb, line 24
def self.encrypt_file(public_key_file_name, input_file_name, output_file_name)
  raise ArgumentError.new("Public key file \"#{public_key_file_name}\" does not exist") unless File.exist?(public_key_file_name)
  raise ArgumentError.new("Input file \"#{input_file_name}\" does not exist") unless File.exist?(input_file_name)

  recipient = get_recipient(public_key_file_name)
  with_temporary_encrypt_keyring(public_key_file_name) do |keyring_file_name|
    run_gpg_capture(
      '--keyring', keyring_file_name,
      '--output', output_file_name,
      '--encrypt',
      '--recipient', recipient,
      '--yes',
      '--trust-model', 'always',
      '--no-tty',
      input_file_name
    )
  end
end
generate_key_pair(key_base_name, recipient, real_name) click to toggle source
# File lib/rgpg/gpg_helper.rb, line 6
def self.generate_key_pair(key_base_name, recipient, real_name)
  public_key_file_name = "#{key_base_name}.pub"
  private_key_file_name = "#{key_base_name}.sec"
  script = generate_key_script(public_key_file_name, private_key_file_name, recipient, real_name)
  script_file = Tempfile.new('gpg-script')
  begin
    script_file.write(script)
    script_file.close
    run_gpg_no_capture(
      '--batch',
      '--gen-key', script_file.path
    )
  ensure
    script_file.close
    script_file.unlink
  end
end

Private Class Methods

build_safe_command_line(home_dir, *args) click to toggle source
# File lib/rgpg/gpg_helper.rb, line 71
def self.build_safe_command_line(home_dir, *args)
  fragments = [
    'gpg',
    '--homedir', home_dir,
    '--no-default-keyring'
  ] + args
  fragments.collect { |fragment| Shellwords.escape(fragment) }.join(' ')
end
generate_key_script(public_key_file_name, private_key_file_name, recipient, real_name) click to toggle source
# File lib/rgpg/gpg_helper.rb, line 110
    def self.generate_key_script(public_key_file_name, private_key_file_name, recipient, real_name)
      <<-EOS
  %echo Generating a standard key
  Key-Type: DSA
  Key-Length: 1024
  Subkey-Type: ELG-E
  Subkey-Length: 1024
  Name-Real: #{real_name}
  Name-Comment: Key automatically generated by rgpg
  Name-Email: #{recipient}
  Expire-Date: 0
  %pubring #{public_key_file_name}
  %secring #{private_key_file_name}
  # Do a commit here, so that we can later print "done" :-)
  %commit
  %echo done
      EOS
    end
get_recipient(key_file_name) click to toggle source
# File lib/rgpg/gpg_helper.rb, line 129
def self.get_recipient(key_file_name)
  lines = run_gpg_capture(key_file_name)
  result = lines.detect { |line| line =~ /^(pub|sec)\s+\d+(D|R)\/([0-9a-fA-F]{8}).+<(.+)>/ }
  raise RuntimeError.new('Invalid output') unless result
  key_id = $2
  recipient = $3
end
run_gpg_capture(*args) click to toggle source
# File lib/rgpg/gpg_helper.rb, line 88
def self.run_gpg_capture(*args)
  with_temp_home_dir do |home_dir|
    command_line = build_safe_command_line(home_dir, *args)

    output_file = Tempfile.new('gpg-output')
    begin
      output_file.close
      result = system("#{command_line} > #{Shellwords.escape(output_file.path)} 2>&1")

      output = nil
      File.open(output_file.path) do |f|
        output = f.read
      end
      raise RuntimeError.new("gpg failed: #{output}") unless result

      output.lines.collect(&:chomp)
    ensure
      output_file.unlink
    end
  end
end
run_gpg_no_capture(*args) click to toggle source
# File lib/rgpg/gpg_helper.rb, line 80
def self.run_gpg_no_capture(*args)
  with_temp_home_dir do |home_dir|
    command_line = build_safe_command_line(home_dir, *args)
    result = system(command_line)
    raise RuntimeError.new('gpg failed') unless result
  end
end
with_temp_home_dir() { |home_dir| ... } click to toggle source
# File lib/rgpg/gpg_helper.rb, line 65
def self.with_temp_home_dir
  Dir.mktmpdir('.rgpg-tmp-', ENV['HOME']) do |home_dir|
    yield home_dir
  end
end
with_temporary_decrypt_keyrings(public_key_file_name, private_key_file_name) { |keyring_file_name, secret_keyring_file_name| ... } click to toggle source
# File lib/rgpg/gpg_helper.rb, line 147
def self.with_temporary_decrypt_keyrings(public_key_file_name, private_key_file_name)
  with_temporary_keyring_file do |keyring_file_name|
    with_temporary_keyring_file do |secret_keyring_file_name|
      run_gpg_capture(
        '--keyring', keyring_file_name,
        '--secret-keyring', secret_keyring_file_name,
        '--import', private_key_file_name
      )
      yield keyring_file_name, secret_keyring_file_name
    end
  end
end
with_temporary_encrypt_keyring(public_key_file_name) { |keyring_file_name| ... } click to toggle source
# File lib/rgpg/gpg_helper.rb, line 137
def self.with_temporary_encrypt_keyring(public_key_file_name)
  with_temporary_keyring_file do |keyring_file_name|
    run_gpg_capture(
      '--keyring', keyring_file_name,
      '--import', public_key_file_name
    )
    yield keyring_file_name
  end
end
with_temporary_keyring_file() { |keyring_file_name| ... } click to toggle source
# File lib/rgpg/gpg_helper.rb, line 160
def self.with_temporary_keyring_file
  keyring_file = Tempfile.new('gpg-key-ring')
  begin
    keyring_file_name = keyring_file.path
    keyring_file.close
    keyring_file.unlink
    yield keyring_file_name
  ensure
    File.unlink(keyring_file_name) if File.exist?(keyring_file_name)
    backup_keyring_file_name = "#{keyring_file_name}~"
    File.unlink(backup_keyring_file_name) if File.exist?(backup_keyring_file_name)
  end
end