class Net::SSH::Authentication::Certificate
Class for representing an SSH
certificate.
Attributes
critical_options[RW]
extensions[RW]
key[RW]
key_id[RW]
nonce[RW]
reserved[RW]
serial[RW]
signature[RW]
signature_key[RW]
type[RW]
valid_after[RW]
valid_before[RW]
valid_principals[RW]
Public Class Methods
read_certblob(buffer, type)
click to toggle source
Read a certificate blob associated with a key of the given type.
# File lib/net/ssh/authentication/certificate.rb, line 25 def self.read_certblob(buffer, type) cert = Certificate.new cert.nonce = buffer.read_string cert.key = buffer.read_keyblob(type) cert.serial = buffer.read_int64 cert.type = type_symbol(buffer.read_long) cert.key_id = buffer.read_string cert.valid_principals = buffer.read_buffer.read_all(&:read_string) cert.valid_after = Time.at(buffer.read_int64) cert.valid_before = if RUBY_PLATFORM == "java" # 0x20c49ba5e353f7 = 0x7fffffffffffffff/1000, the largest value possible for JRuby # JRuby Time.at multiplies the arg by 1000, and then stores it in a signed long. # 0x20c49ba2d52500 = 292278993-01-01 00:00:00 +0000 # JRuby 9.1 does not accept the year 292278994 because of edge cases (https://github.com/JodaOrg/joda-time/issues/190) Time.at([0x20c49ba2d52500, buffer.read_int64].min) else Time.at(buffer.read_int64) end cert.critical_options = read_options(buffer) cert.extensions = read_options(buffer) cert.reserved = buffer.read_string cert.signature_key = buffer.read_buffer.read_key cert.signature = buffer.read_string cert end
Private Class Methods
read_options(buffer)
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 109 def self.read_options(buffer) names = [] options = buffer.read_buffer.read_all do |b| name = b.read_string names << name data = b.read_string data = Buffer.new(data).read_string unless data.empty? [name, data] end raise ArgumentError, "option/extension names must be in sorted order" if names.sort != names Hash[options] end
type_symbol(type)
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 125 def self.type_symbol(type) types = { 1 => :user, 2 => :host } raise ArgumentError("unsupported type: #{type}") unless types.include?(type) types.fetch(type) end
Public Instance Methods
fingerprint()
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 81 def fingerprint key.fingerprint end
sign(key, sign_nonce = nil)
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 97 def sign(key, sign_nonce = nil) cert = clone cert.sign!(key, sign_nonce) end
sign!(key, sign_nonce = nil)
click to toggle source
Signs the certificate with key.
# File lib/net/ssh/authentication/certificate.rb, line 86 def sign!(key, sign_nonce = nil) # ssh-keygen uses 32 bytes of nonce. self.nonce = sign_nonce || SecureRandom.random_bytes(32) self.signature_key = key self.signature = Net::SSH::Buffer.from( :string, key.ssh_signature_type, :mstring, key.ssh_do_sign(to_blob_without_signature) ).to_s self end
signature_valid?()
click to toggle source
Checks whether the certificate’s signature was signed by signature key.
# File lib/net/ssh/authentication/certificate.rb, line 103 def signature_valid? buffer = Buffer.new(signature) sig_format = buffer.read_string signature_key.ssh_do_verify(buffer.read_string, to_blob_without_signature, host_key: sig_format) end
ssh_do_sign(data, sig_alg = nil)
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 69 def ssh_do_sign(data, sig_alg = nil) key.ssh_do_sign(data, sig_alg) end
ssh_do_verify(sig, data, options = {})
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 73 def ssh_do_verify(sig, data, options = {}) key.ssh_do_verify(sig, data, options) end
ssh_signature_type()
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 57 def ssh_signature_type key.ssh_type end
ssh_type()
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 53 def ssh_type key.ssh_type + "-cert-v01@openssh.com" end
to_blob()
click to toggle source
Serializes the certificate (and key).
# File lib/net/ssh/authentication/certificate.rb, line 62 def to_blob Buffer.from( :raw, to_blob_without_signature, :string, signature ).to_s end
to_pem()
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 77 def to_pem key.to_pem end
Private Instance Methods
key_without_type()
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 165 def key_without_type # key.to_blob gives us e.g. "ssh-rsa,<key>" but we just want "<key>". tmp = Buffer.new(key.to_blob) tmp.read_string # skip the underlying key type tmp.read end
options_to_blob(options)
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 172 def options_to_blob(options) options.keys.sort.inject(Buffer.new) do |b, name| b.write_string(name) data = options.fetch(name) data = Buffer.from(:string, data).to_s unless data.empty? b.write_string(data) end.to_s end
ssh_time(t)
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 142 def ssh_time(t) # Times in certificates are represented as a uint64. [[t.to_i, 0].max, 2 << 64 - 1].min end
to_blob_without_signature()
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 147 def to_blob_without_signature Buffer.from( :string, ssh_type, :string, nonce, :raw, key_without_type, :int64, serial, :long, type_value(type), :string, key_id, :string, valid_principals.inject(Buffer.new) { |acc, elem| acc.write_string(elem) }.to_s, :int64, ssh_time(valid_after), :int64, ssh_time(valid_before), :string, options_to_blob(critical_options), :string, options_to_blob(extensions), :string, reserved, :string, signature_key.to_blob ).to_s end
type_value(type)
click to toggle source
# File lib/net/ssh/authentication/certificate.rb, line 135 def type_value(type) types = { user: 1, host: 2 } raise ArgumentError("unsupported type: #{type}") unless types.include?(type) types.fetch(type) end