Module: OpenSSHKeyConverter
- Defined in:
- lib/zold/key.rb
Overview
Stolen from: gist.github.com/tombh/f66de84fd3a63e670ad9
Constant Summary collapse
- RSA_COMPONENTS =
The components in a openssh .pub / known_host RSA public key.
['ssh-rsa', :e, :n].freeze
- DSA_COMPONENTS =
The components in a openssh .pub / known_host DSA public key.
['ssh-dss', :p, :q, :g, :pub_key].freeze
Class Method Summary collapse
-
.decode_mpi(mpi_str) ⇒ Object
Decodes an openssh-mpi-encoded integer.
-
.decode_pubkey(string) ⇒ Object
Decodes an openssh public key from the format of .pub & known_hosts files.
-
.encode_mpi(n) ⇒ Object
Encodes an openssh-mpi-encoded integer.
-
.encode_pubkey(key) ⇒ Object
Encodes a key’s public part in the format found in .pub & known_hosts files.
-
.first_line(string) ⇒ Object
Extracts the first line of a string.
-
.key_from_string(serialized_key) ⇒ Object
Reads a serialized key from a string.
-
.load_key(io) ⇒ Object
Loads a serialized key from an IO instance (File, StringIO).
-
.pack_pubkey_components(strings) ⇒ Object
Packs string components into an openssh-encoded pubkey.
-
.unpack_pubkey_components(str) ⇒ Object
Unpacks the string components in an openssh-encoded pubkey.
Class Method Details
.decode_mpi(mpi_str) ⇒ Object
Decodes an openssh-mpi-encoded integer.
146 147 148 |
# File 'lib/zold/key.rb', line 146 def self.decode_mpi(mpi_str) mpi_str.unpack('C*').inject(0) { |a, e| (a << 8) | e } end |
.decode_pubkey(string) ⇒ Object
Decodes an openssh public key from the format of .pub & known_hosts files.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
# File 'lib/zold/key.rb', line 87 def self.decode_pubkey(string) components = unpack_pubkey_components Base64.decode64(string) case components.first when RSA_COMPONENTS.first ops = RSA_COMPONENTS.zip components key = OpenSSL::PKey::RSA.new when DSA_COMPONENTS.first ops = DSA_COMPONENTS.zip components key = OpenSSL::PKey::DSA.new else raise "Unsupported key type #{components.first}" end ops.each do |o| next unless o.first.is_a? Symbol key.send "#{o.first}=", decode_mpi(o.last) end key end |
.encode_mpi(n) ⇒ Object
Encodes an openssh-mpi-encoded integer.
151 152 153 154 155 156 157 |
# File 'lib/zold/key.rb', line 151 def self.encode_mpi(n) chars = [] n = n.to_i chars << (n & 0xff) && n >>= 8 while n != 0 chars << 0 if chars.empty? || chars.last >= 0x80 chars.reverse.pack('C*') end |
.encode_pubkey(key) ⇒ Object
Encodes a key’s public part in the format found in .pub & known_hosts files.
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/zold/key.rb', line 72 def self.encode_pubkey(key) case key when OpenSSL::PKey::RSA components = RSA_COMPONENTS when OpenSSL::PKey::DSA components = DSA_COMPONENTS else raise "Unsupported key type #{key.class.name}" end components.map! { |c| c.is_a?(Symbol) ? encode_mpi(key.send(c)) : c } # ruby tries to be helpful and adds new lines every 60 bytes :( [pack_pubkey_components(components)].pack('m').delete("\n") end |
.first_line(string) ⇒ Object
Extracts the first line of a string.
124 125 126 |
# File 'lib/zold/key.rb', line 124 def self.first_line(string) string[0, string.index(/\r|\n/) || string.len] end |
.key_from_string(serialized_key) ⇒ Object
Reads a serialized key from a string.
112 113 114 115 116 117 118 119 120 121 |
# File 'lib/zold/key.rb', line 112 def self.key_from_string(serialized_key) header = first_line serialized_key if header.index 'RSA' OpenSSL::PKey::RSA.new serialized_key elsif header.index 'DSA' OpenSSL::PKey::DSA.new serialized_key else raise 'Unknown key type' end end |
.load_key(io) ⇒ Object
Loads a serialized key from an IO instance (File, StringIO).
107 108 109 |
# File 'lib/zold/key.rb', line 107 def self.load_key(io) key_from_string io.read end |
.pack_pubkey_components(strings) ⇒ Object
Packs string components into an openssh-encoded pubkey.
141 142 143 |
# File 'lib/zold/key.rb', line 141 def self.pack_pubkey_components(strings) (strings.map { |s| [s.length].pack('N') }).zip(strings).flatten.join end |
.unpack_pubkey_components(str) ⇒ Object
Unpacks the string components in an openssh-encoded pubkey.
129 130 131 132 133 134 135 136 137 138 |
# File 'lib/zold/key.rb', line 129 def self.unpack_pubkey_components(str) cs = [] i = 0 while i < str.length len = str[i, 4].unpack('N').first cs << str[i + 4, len] i += 4 + len end cs end |