Module: Puttygen

Defined in:
lib/puttygen.rb,
lib/puttygen/version.rb

Defined Under Namespace

Classes: Keypair

Constant Summary collapse

PRIVATE_OUTPUT_FORMATS =
{
  putty: 'private',
  openssh: 'private-openssh',
  sshcom: 'private-sshcom',
}
PUBLIC_OUTPUT_FORMATS =
{
  standard: 'public',
  sshcom: 'public',
  openssh: 'public-openssh',
}
VERSION =
'0.1.0'

Class Method Summary collapse

Class Method Details

.convert_private_key(private_key_path, output_format: :putty) ⇒ String

Convert an existing private key to another key format.

Parameters:

  • private_key_path (String)

    path to private key

  • output_format (Symbol) (defaults to: :putty)

    output format of private key to generate, one of :putty, :openssh or :sshcom

Returns:

  • (String)

    private key contents



34
35
36
37
38
39
40
41
42
# File 'lib/puttygen.rb', line 34

def self.convert_private_key(private_key_path, output_format: :putty)
  outfile = Dir::Tmpname.make_tmpname(Dir.tmpdir, nil)
  outflag = PRIVATE_OUTPUT_FORMATS.fetch(output_format, 'private')
  out, status = Open3.capture2e("puttygen #{private_key_path} -q -O #{outflag} -o #{outfile}")
  process_exit_status(out, status)
  File.read(outfile)
ensure
  FileUtils.rm_f(outfile)
end

.create_public_from_private(private_key_path, output_format: :standard) ⇒ String

Create a public key from a private key.

Parameters:

  • private_key_path (String)

    path to private key

  • output_format (Symbol) (defaults to: :standard)

    output format of public key to generate, one of :standard, :openssh or :sshcom

Returns:

  • (String)

    public key contents



49
50
51
52
53
54
# File 'lib/puttygen.rb', line 49

def self.create_public_from_private(private_key_path, output_format: :standard)
  outflag = PUBLIC_OUTPUT_FORMATS.fetch(output_format, 'public')
  out, status = Open3.capture2e("puttygen #{private_key_path} -q -O #{outflag}")
  process_exit_status(out, status)
  out.strip
end

.fingerprint(private_key_path) ⇒ String

Fingerprint a private key.

Parameters:

  • private_key_path (String)

    path to private key

Returns:

  • (String)

    fingerprint of private key



91
92
93
94
95
# File 'lib/puttygen.rb', line 91

def self.fingerprint(private_key_path)
  out, status = Open3.capture2e("puttygen #{private_key_path} -q -l")
  process_exit_status(out, status)
  out.strip
end

.generate_keypair(type: :rsa, bits: 2048, comment: nil, passphrase: nil, private_format: :putty, public_format: :standard) ⇒ Keypair

Generate a new public/private key pair.

Parameters:

  • type (Symbol) (defaults to: :rsa)

    type of key to generate, one of :rsa, :dsa or :rsa1

  • bits (Integer) (defaults to: 2048)

    number of bits for key

  • passphrase (String) (defaults to: nil)

    passphrase to use for key (can be nil or empty for no passphrase)

  • private_format (Symbol) (defaults to: :putty)

    output format of private key to generate, one of :putty, :openssh or :sshcom

  • public_format (Symbol) (defaults to: :standard)

    output format of public key to generate, one of :standard, :openssh or :sshcom

Returns:

  • (Keypair)

    public and private keys



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/puttygen.rb', line 64

def self.generate_keypair(type: :rsa, bits: 2048, comment: nil, passphrase: nil, private_format: :putty, public_format: :standard)
  outfile = Dir::Tmpname.make_tmpname(Dir.tmpdir, nil)
  outflag = PRIVATE_OUTPUT_FORMATS.fetch(private_format, 'private')
  line = "puttygen -q -t #{type} -b #{bits} -C '#{comment}' -O #{outflag} -o #{outfile}"

  cmd = RubyExpect::Expect.spawn(line)
  cmd.procedure do
    each do
      expect 'Enter passphrase to save key:' do
        send passphrase
      end
      expect 'Re-enter passphrase to verify:' do
        send passphrase
      end
    end
  end

  public = create_public_from_private(outfile, output_format: public_format)
  Keypair.new(public, File.read(outfile))
ensure
  FileUtils.rm_f(outfile)
end

.process_exit_status(output, status) ⇒ Object



99
100
101
102
103
# File 'lib/puttygen.rb', line 99

def self.process_exit_status(output, status)
  unless(status.success?)
    raise "Command failed (#{output.strip})"
  end
end