class SSHCertParser::SSHCertificate

Attributes

ca[RW]
cert_type[RW]
crits[RW]
exts[RW]
key_id[RW]
principals[RW]
serial[RW]
signature[RW]
valid_after[RW]
valid_before[RW]

Public Class Methods

from_bytes(byte_array) click to toggle source
# File lib/ssh_cert_parser/ssh_certificate.rb, line 32
  def from_bytes(byte_array)
    blob = if byte_array.include? ' '
             byte_array.split(' ')[1]
           else
             byte_array
           end
    blob = Base64.decode64(blob)
    key_type, blob = take_pascal_string(blob)
    if key_type != 'ssh-rsa-cert-v01@openssh.com'
      raise "Cannot parse certificate of type #{key_type}"
    end
    nonce, blob = take_pascal_bytestring(blob)
    public_n, blob = take_pascal_bytestring(blob)
    public_e, blob = take_pascal_bytestring(blob)
    serial, blob = take_u64(blob)
    cert_type, blob = take_u32(blob)
    cert_type = if cert_type == 1
                  'user'
                else
                  'host'
      end
    key_id, blob = take_pascal_string(blob)
    principals, blob = take_list(blob, method(:take_pascal_string))
    valid_after, blob = take_u64(blob)
    begin
      valid_after = Time.at(valid_after).utc
    rescue StandardError
    end
    valid_before, blob = take_u64(blob)
    begin
      valid_before = Time.at(valid_before).utc
    rescue StandardError
      valid_before = "forever"
    end

    crits, blob = take_list(blob, method(:take_pascal_string))
    exts, blob = take_list(blob, method(:take_pascal_string))
    unknown, blob = take_pascal_bytestring(blob)
    raw_ca, blob = take_pascal_bytestring(blob)
    ca_cert_type, raw_ca_rest = take_pascal_string(raw_ca)
    if ca_cert_type == 'ssh-rsa'
      ca_cert = take_rsa_cert(raw_ca, raw_ca_rest)
    else
      raise "Unsupported cert type #{ca_cert_type}"
    end
    signature = blob
    new(
      serial, cert_type, key_id, principals, valid_after, valid_before,
      crits, exts, ca_cert, signature
    )
end
new(*args) click to toggle source
# File lib/ssh_cert_parser/ssh_certificate.rb, line 11
def initialize(*args)
  @serial, @cert_type, @key_id, @principals, @valid_after, @valid_before,
  @crits, @exts, @ca, @signature = args
end
take_list(string, per_item_callback) click to toggle source
# File lib/ssh_cert_parser/ssh_certificate.rb, line 103
def take_list(string, per_item_callback)
  overall, rest = take_pascal_bytestring(string)
  overall = overall.strip!
  l = []
  while overall && overall != ''
    item, overall = per_item_callback.call(overall)
    l << item if item != ''
  end
  [l, rest]
end
take_pascal_bytestring(string) click to toggle source
# File lib/ssh_cert_parser/ssh_certificate.rb, line 92
def take_pascal_bytestring(string)
  string_len, rest = take_u32(string)
  [rest[0..string_len], rest[string_len..-1]]
end
take_pascal_string(string) click to toggle source
# File lib/ssh_cert_parser/ssh_certificate.rb, line 97
def take_pascal_string(string)
  string_len, rest = take_u32(string)
  p string if string_len.nil?
  [rest[0..string_len].encode('utf-8').strip, rest[string_len..-1]]
end
take_rsa_cert(raw_pubkey, byte_array) click to toggle source
# File lib/ssh_cert_parser/ssh_certificate.rb, line 114
def take_rsa_cert(raw_pubkey, byte_array)
  modulus_len, byte_array = take_u32(byte_array)
  modulus = byte_array[0..modulus_len]
  byte_array = byte_array[modulus_len..-1]
  exponent_len, byte_array = take_u32(byte_array)
  exponent = byte_array[0..exponent_len]
  PublicKeys::RSAPublicKey.new(modulus = modulus, exponent = exponent, raw = raw_pubkey)
end
take_u32(string) click to toggle source
# File lib/ssh_cert_parser/ssh_certificate.rb, line 84
def take_u32(string)
  [string[0..4].unpack('L>')[0], string[4..-1]]
end
take_u64(string) click to toggle source
# File lib/ssh_cert_parser/ssh_certificate.rb, line 88
def take_u64(string)
  [string[0..8].unpack('Q>')[0], string[8..-1]]
end

Public Instance Methods

as_hash() click to toggle source
# File lib/ssh_cert_parser/ssh_certificate.rb, line 16
def as_hash
  {
    serial: serial,
    cert_type: cert_type,
    key_id: key_id,
    principals: principals,
    valid_after: valid_after,
    valid_before: valid_before,
    crits: crits,
    exts: exts,
    ca_fingerprint: ca.fingerprint,
    signature: Base64.encode64(signature)
  }
end