Class: SSHKey

Inherits:
Object
  • Object
show all
Defined in:
lib/sshkey.rb,
lib/sshkey/version.rb

Constant Summary collapse

SSH_TYPES =
{"rsa" => "ssh-rsa", "dsa" => "ssh-dss"}
SSH_CONVERSION =
{"rsa" => ["e", "n"], "dsa" => ["p", "q", "g", "pub_key"]}
VERSION =
"1.2.0"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(private_key, options = {}) ⇒ SSHKey

Returns a new instance of SSHKey.



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/sshkey.rb', line 56

def initialize(private_key, options = {})
  begin
    @key_object = OpenSSL::PKey::RSA.new(private_key)
    @type = "rsa"
  rescue
    @key_object = OpenSSL::PKey::DSA.new(private_key)
    @type = "dsa"
  end

  @comment = options[:comment] || ""
end

Instance Attribute Details

#commentObject (readonly)

Returns the value of attribute comment.



9
10
11
# File 'lib/sshkey.rb', line 9

def comment
  @comment
end

#key_objectObject (readonly)

Returns the value of attribute key_object.



9
10
11
# File 'lib/sshkey.rb', line 9

def key_object
  @key_object
end

#typeObject (readonly)

Returns the value of attribute type.



9
10
11
# File 'lib/sshkey.rb', line 9

def type
  @type
end

Class Method Details

.from_byte_array(byte_array, expected_size = nil) ⇒ Object



47
48
49
50
51
52
53
54
# File 'lib/sshkey.rb', line 47

def self.from_byte_array(byte_array, expected_size = nil)
  num = 0
  raise "Byte array too short" if !expected_size.nil? && expected_size != byte_array.size
  byte_array.reverse.each_with_index do |item, index|
    num += item * 256**(index)
  end
  num
end

.generate(options = {}) ⇒ Object



11
12
13
14
15
16
17
18
19
# File 'lib/sshkey.rb', line 11

def self.generate(options = {})
  type = options[:type] || "rsa"
  case type
  when "rsa" then SSHKey.new(OpenSSL::PKey::RSA.generate(2048).to_pem, options)
  when "dsa" then SSHKey.new(OpenSSL::PKey::DSA.generate(2048).to_pem, options)
  else
    raise "Unknown key type #{type}"
  end
end

.valid?(ssh_key) ⇒ Boolean

Returns:

  • (Boolean)


21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/sshkey.rb', line 21

def self.valid?(ssh_key)
  ssh_type, encoded_key = ssh_key.split(" ")
  type = SSH_TYPES.invert[ssh_type]
  prefix = [0,0,0,7].pack("C*")
  decoded = Base64.decode64(encoded_key)

  # Base64 decoding is too permissive, so we should validate if encoding is correct
  return false unless Base64.encode64(decoded).gsub("\n", "") == encoded_key
  return false unless decoded.sub!(/^#{prefix}#{ssh_type}/, "")

  unpacked = decoded.unpack("C*")
  data = []
  index = 0
  until unpacked[index].nil?
    datum_size = from_byte_array unpacked[index..index+4-1], 4
    index = index + 4
    datum = from_byte_array unpacked[index..index+datum_size-1], datum_size
    data << datum
    index = index + datum_size
  end

  SSH_CONVERSION[type].size == data.size
rescue
  false
end

Instance Method Details

#dsa_private_keyObject



86
87
88
# File 'lib/sshkey.rb', line 86

def dsa_private_key
  private_key if type == "dsa"
end

#dsa_public_keyObject



90
91
92
# File 'lib/sshkey.rb', line 90

def dsa_public_key
  public_key if type == "dsa"
end

#fingerprintObject



99
100
101
# File 'lib/sshkey.rb', line 99

def fingerprint
  Digest::MD5.hexdigest(ssh_public_key_conversion).gsub(/(.{2})(?=.)/, '\1:\2')
end

#private_keyObject



68
69
70
# File 'lib/sshkey.rb', line 68

def private_key
  key_object.to_pem
end

#public_keyObject



72
73
74
# File 'lib/sshkey.rb', line 72

def public_key
  key_object.public_key.to_pem
end

#rsa_private_keyObject

Backward compatibility



78
79
80
# File 'lib/sshkey.rb', line 78

def rsa_private_key
  private_key if type == "rsa"
end

#rsa_public_keyObject



82
83
84
# File 'lib/sshkey.rb', line 82

def rsa_public_key
  public_key if type == "rsa"
end

#ssh_public_keyObject



95
96
97
# File 'lib/sshkey.rb', line 95

def ssh_public_key
  [SSH_TYPES[type], Base64.encode64(ssh_public_key_conversion).gsub("\n", ""), comment].join(" ").strip
end