Class: Net::SSH::KeyFactory

Inherits:
Object
  • Object
show all
Defined in:
lib/net/ssh/key_factory.rb

Overview

A factory class for returning new Key classes. It is used for obtaining OpenSSL key instances via their SSH names, and for loading both public and private keys. It used used primarily by Net::SSH itself, internally, and will rarely (if ever) be directly used by consumers of the library.

klass = Net::SSH::KeyFactory.get("rsa")
assert klass.is_a?(OpenSSL::PKey::RSA)

key = Net::SSH::KeyFactory.load_public_key("~/.ssh/id_dsa.pub")

Defined Under Namespace

Classes: KeyType, OpenSSHPrivateKeyType, OpenSSLDSAKeyType, OpenSSLECKeyType, OpenSSLKeyTypeBase, OpenSSLPKeyType, OpenSSLRSAKeyType

Constant Summary collapse

MAP =

Specifies the mapping of SSH names to OpenSSL key classes.

{
  'dh' => OpenSSL::PKey::DH,
  'rsa' => OpenSSL::PKey::RSA,
  'dsa' => OpenSSL::PKey::DSA,
  'ecdsa' => OpenSSL::PKey::EC
}

Class Method Summary collapse

Class Method Details

.get(name) ⇒ Object

Fetch an OpenSSL key instance by its SSH name. It will be a new, empty key of the given type.



30
31
32
# File 'lib/net/ssh/key_factory.rb', line 30

def get(name)
  MAP.fetch(name).new
end

.load_data_private_key(data, passphrase = nil, ask_passphrase = true, filename = "", prompt = Prompt.default) ⇒ Object

Loads a private key. It will correctly determine whether the file describes an RSA or DSA key, and will load it appropriately. The new key is returned. If the key itself is encrypted (requiring a passphrase to use), the user will be prompted to enter their password unless passphrase works.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/net/ssh/key_factory.rb', line 49

def load_data_private_key(data, passphrase = nil, ask_passphrase = true, filename = "", prompt = Prompt.default)
  key_type = classify_key(data, filename)

  encrypted_key = nil
  tries = 0

  prompter = nil
  result =
    begin
      key_type.read(data, passphrase || 'invalid')
    rescue *key_type.error_classes => e
      encrypted_key = !!key_type.encrypted_key?(data, e) if encrypted_key.nil?
      if encrypted_key && ask_passphrase
        tries += 1
        if tries <= 3
          prompter ||= prompt.start(type: 'private_key', filename: filename, sha: Digest::SHA256.digest(data))
          passphrase = prompter.ask("Enter passphrase for #{filename}:", false)
          retry
        else
          raise
        end
      else
        raise
      end
    end
  prompter.success if prompter
  result
end

.load_data_public_key(data, filename = "") ⇒ Object

Loads a public key. It will correctly determine whether the file describes an RSA or DSA key, and will load it appropriately. The new public key is returned.



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/net/ssh/key_factory.rb', line 89

def load_data_public_key(data, filename = "")
  fields = data.split(/ /)

  blob = nil
  begin
    blob = fields.shift
  end while !blob.nil? && !/^(ssh-(rsa|dss|ed25519)|ecdsa-sha2-nistp\d+)(-cert-v01@openssh\.com)?$/.match(blob)
  blob = fields.shift

  raise Net::SSH::Exception, "public key at #{filename} is not valid" if blob.nil?

  blob = blob.unpack("m*").first
  reader = Net::SSH::Buffer.new(blob)
  reader.read_key or raise OpenSSL::PKey::PKeyError, "not a public key #{filename.inspect}"
end

.load_private_key(filename, passphrase = nil, ask_passphrase = true, prompt = Prompt.default) ⇒ Object

Loads a private key from a file. It will correctly determine whether the file describes an RSA or DSA key, and will load it appropriately. The new key is returned. If the key itself is encrypted (requiring a passphrase to use), the user will be prompted to enter their password unless passphrase works.



39
40
41
42
# File 'lib/net/ssh/key_factory.rb', line 39

def load_private_key(filename, passphrase = nil, ask_passphrase = true, prompt = Prompt.default)
  data = File.read(File.expand_path(filename))
  load_data_private_key(data, passphrase, ask_passphrase, filename, prompt)
end

.load_public_key(filename) ⇒ Object

Loads a public key from a file. It will correctly determine whether the file describes an RSA or DSA key, and will load it appropriately. The new public key is returned.



81
82
83
84
# File 'lib/net/ssh/key_factory.rb', line 81

def load_public_key(filename)
  data = File.read(File.expand_path(filename))
  load_data_public_key(data, filename)
end