Class: OmfCommon::Auth::SSHPubKeyConvert

Inherits:
Object
  • Object
show all
Defined in:
omf_common/lib/omf_common/auth/ssh_pub_key_convert.rb

Overview

This file provides a converter that accepts an SSH public key string and converts it to an OpenSSL::PKey::RSA object for use in verifying received messages. (DSA support pending).

Class Method Summary (collapse)

Class Method Details

+ (Object) convert(keystring)

Convert a string in SSH public key format to a key object suitable for use with OpenSSL. If the key is an RSA key then an OpenSSL::PKey::RSA object is returned. If the key is a DSA key then an OpenSSL::PKey::DSA object is returned. In either case, the object returned is suitable for encrypting data or verifying signatures, but cannot be used for decrypting or signing.

The keystring should be a single line, as per an SSH public key file as generated by ssh-keygen, or a line from an SSH authorized_keys file.

Raises:

  • (ArgumentError)


48
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
77
78
79
80
81
82
83
84
85
# File 'omf_common/lib/omf_common/auth/ssh_pub_key_convert.rb', line 48

def self.convert(keystring)
  (type, b64, id) = keystring.split(' ')
  raise ArgumentError, "Invalid SSH public key '#{keystring}'" if b64.nil?

  decoded_key = Base64.decode64(b64)
  (n, bytes) = unpack_u32(decoded_key)
  (keytype, bytes) = unpack_string(bytes, n)

  if keytype == "ssh-rsa"
    (n, bytes) = unpack_u32(bytes)
    (estr, bytes) = unpack_string(bytes, n)
    (n, bytes) = unpack_u32(bytes)
    (nstr, bytes) = unpack_string(bytes, n)

    key = OpenSSL::PKey::RSA.new
    key.n = OpenSSL::BN.new(nstr, 2)
    key.e = OpenSSL::BN.new(estr, 2)
    key
  elsif keytype == 'ssh-dss'
    (n, bytes) = unpack_u32(bytes)
    (pstr, bytes) = unpack_string(bytes, n)
    (n, bytes) = unpack_u32(bytes)
    (qstr, bytes) = unpack_string(bytes, n)
    (n, bytes) = unpack_u32(bytes)
    (gstr, bytes) = unpack_string(bytes, n)
    (n, bytes) = unpack_u32(bytes)
    (pkstr, bytes) = unpack_string(bytes, n)

    key = OpenSSL::PKey::DSA.new
    key.p = OpenSSL::BN.new(pstr, 2)
    key.q = OpenSSL::BN.new(qstr, 2)
    key.g = OpenSSL::BN.new(gstr, 2)
    key.pub_key = OpenSSL::BN.new(pkstr, 2)
    key
  else
    raise ArgumentError, "Unknown key type '#{keytype}'"
  end
end

+ (Object) unpack_string(bytes, len)

Unpack a string from the bytes array. Exactly len bytes will be extracted.

Returns a pair (string, bytes), where string is the extracted string (of length len), and bytes is the remainder of the original bytes array that follows string.



33
34
35
# File 'omf_common/lib/omf_common/auth/ssh_pub_key_convert.rb', line 33

def self.unpack_string(bytes, len)
  return bytes.unpack("A#{len}")[0], bytes[len..-1]
end

+ (Object) unpack_u32(bytes)

Unpack a 4-byte unsigned integer from the bytes array.

Returns a pair (u32, bytes), where u32 is the extracted unsigned integer, and bytes is the remainder of the original bytes array that follows u32.



22
23
24
# File 'omf_common/lib/omf_common/auth/ssh_pub_key_convert.rb', line 22

def self.unpack_u32(bytes)
  return bytes.unpack("N")[0], bytes[4..-1]
end