Class: SSHData::Certificate
- Inherits:
-
Object
- Object
- SSHData::Certificate
- Defined in:
- lib/ssh_data/certificate.rb
Constant Summary collapse
- BEGINNING_OF_TIME =
Special values for valid_before and valid_after.
Time.at(0)
- END_OF_TIME =
Time.at((2**64)-1)
- TYPE_USER =
Integer certificate types
1
- TYPE_HOST =
2
- ALGO_RSA =
Certificate algorithm identifiers
"[email protected]"
- ALGO_DSA =
"[email protected]"
- ALGO_ECDSA256 =
"[email protected]"
- ALGO_ECDSA384 =
"[email protected]"
- ALGO_ECDSA521 =
"[email protected]"
- ALGO_ED25519 =
"[email protected]"
- ALGO_SKECDSA256 =
"[email protected]"
- ALGO_SKED25519 =
"[email protected]"
- ALGOS =
[ ALGO_RSA, ALGO_DSA, ALGO_ECDSA256, ALGO_ECDSA384, ALGO_ECDSA521, ALGO_ED25519, ALGO_SKECDSA256, ALGO_SKED25519 ]
- CRITICAL_OPTION_FORCE_COMMAND =
"force-command"
- CRITICAL_OPTION_SOURCE_ADDRESS =
"source-address"
Instance Attribute Summary collapse
-
#algo ⇒ Object
readonly
Returns the value of attribute algo.
-
#ca_key ⇒ Object
readonly
Returns the value of attribute ca_key.
-
#critical_options ⇒ Object
readonly
Returns the value of attribute critical_options.
-
#extensions ⇒ Object
readonly
Returns the value of attribute extensions.
-
#key_id ⇒ Object
readonly
Returns the value of attribute key_id.
-
#nonce ⇒ Object
readonly
Returns the value of attribute nonce.
-
#public_key ⇒ Object
readonly
Returns the value of attribute public_key.
-
#reserved ⇒ Object
readonly
Returns the value of attribute reserved.
-
#serial ⇒ Object
readonly
Returns the value of attribute serial.
-
#signature ⇒ Object
readonly
Returns the value of attribute signature.
-
#type ⇒ Object
readonly
Returns the value of attribute type.
-
#valid_after ⇒ Object
readonly
Returns the value of attribute valid_after.
-
#valid_before ⇒ Object
readonly
Returns the value of attribute valid_before.
-
#valid_principals ⇒ Object
readonly
Returns the value of attribute valid_principals.
Class Method Summary collapse
-
.parse_openssh(cert, unsafe_no_verify: false) ⇒ Object
Parse an OpenSSH certificate in authorized_keys format (see sshd(8) manual page).
-
.parse_rfc4253(raw, unsafe_no_verify: false) ⇒ Object
Parse an RFC 4253 binary SSH certificate.
Instance Method Summary collapse
-
#allowed_source_address?(address) ⇒ Boolean
Check if the given IP address is allowed for use with this certificate.
-
#force_command ⇒ Object
The force-command critical option, if present.
-
#initialize(public_key:, key_id:, algo: nil, nonce: nil, serial: 0, type: TYPE_USER, valid_principals: [], valid_after: BEGINNING_OF_TIME, valid_before: END_OF_TIME, critical_options: {}, extensions: {}, reserved: "", ca_key: nil, signature: "") ⇒ Certificate
constructor
Intialize a new Certificate instance.
-
#openssh(comment: nil) ⇒ Object
OpenSSH certificate in authorized_keys format (see sshd(8) manual page).
-
#rfc4253 ⇒ Object
RFC4253 binary encoding of the certificate.
-
#sign(private_key, algo: nil) ⇒ Object
Sign this certificate with a private key.
-
#source_address ⇒ Object
The source-address critical option, if present.
-
#verify ⇒ Object
Verify the certificate’s signature.
Constructor Details
#initialize(public_key:, key_id:, algo: nil, nonce: nil, serial: 0, type: TYPE_USER, valid_principals: [], valid_after: BEGINNING_OF_TIME, valid_before: END_OF_TIME, critical_options: {}, extensions: {}, reserved: "", ca_key: nil, signature: "") ⇒ Certificate
Intialize a new Certificate instance.
algo: - The certificate’s String algorithm id (one of ALGO_RSA,
ALGO_DSA, ALGO_ECDSA256, ALGO_ECDSA384, ALGO_ECDSA521,
or ALGO_ED25519)
nonce: - The certificate’s String nonce field. public_key: - The certificate’s public key as an PublicKey::Base
subclass instance.
serial: - The certificate’s Integer serial field. type: - The certificate’s Integer type field (one of TYPE_USER
or TYPE_HOST).
key_id: - The certificate’s String key_id field. valid_principals: - The Array of Strings valid_principles field from the
certificate.
valid_after: - The certificate’s Time valid_after field. valid_before: - The certificate’s Time valid_before field. critical_options: - The Hash critical_options field from the certificate. extensions: - The Hash extensions field from the certificate. reserved: - The certificate’s String reserved field. ca_key: - The issuing CA’s public key as a PublicKey::Base
subclass instance.
signature: - The certificate’s String signature field.
Returns nothing.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/ssh_data/certificate.rb', line 106 def initialize(public_key:, key_id:, algo: nil, nonce: nil, serial: 0, type: TYPE_USER, valid_principals: [], valid_after: BEGINNING_OF_TIME, valid_before: END_OF_TIME, critical_options: {}, extensions: {}, reserved: "", ca_key: nil, signature: "") @algo = algo || Encoding::CERT_ALGO_BY_PUBLIC_KEY_ALGO[public_key.algo] @nonce = nonce || SecureRandom.random_bytes(32) @public_key = public_key @serial = serial @type = type @key_id = key_id @valid_principals = valid_principals @valid_after = valid_after @valid_before = valid_before @critical_options = @extensions = extensions @reserved = reserved @ca_key = ca_key @signature = signature end |
Instance Attribute Details
#algo ⇒ Object (readonly)
Returns the value of attribute algo.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def algo @algo end |
#ca_key ⇒ Object (readonly)
Returns the value of attribute ca_key.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def ca_key @ca_key end |
#critical_options ⇒ Object (readonly)
Returns the value of attribute critical_options.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def @critical_options end |
#extensions ⇒ Object (readonly)
Returns the value of attribute extensions.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def extensions @extensions end |
#key_id ⇒ Object (readonly)
Returns the value of attribute key_id.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def key_id @key_id end |
#nonce ⇒ Object (readonly)
Returns the value of attribute nonce.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def nonce @nonce end |
#public_key ⇒ Object (readonly)
Returns the value of attribute public_key.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def public_key @public_key end |
#reserved ⇒ Object (readonly)
Returns the value of attribute reserved.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def reserved @reserved end |
#serial ⇒ Object (readonly)
Returns the value of attribute serial.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def serial @serial end |
#signature ⇒ Object (readonly)
Returns the value of attribute signature.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def signature @signature end |
#type ⇒ Object (readonly)
Returns the value of attribute type.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def type @type end |
#valid_after ⇒ Object (readonly)
Returns the value of attribute valid_after.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def valid_after @valid_after end |
#valid_before ⇒ Object (readonly)
Returns the value of attribute valid_before.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def valid_before @valid_before end |
#valid_principals ⇒ Object (readonly)
Returns the value of attribute valid_principals.
32 33 34 |
# File 'lib/ssh_data/certificate.rb', line 32 def valid_principals @valid_principals end |
Class Method Details
.parse_openssh(cert, unsafe_no_verify: false) ⇒ Object
Parse an OpenSSH certificate in authorized_keys format (see sshd(8) manual page).
cert - An OpenSSH formatted certificate, including key algo,
base64 encoded key and optional comment.
unsafe_no_verify: - Bool of whether to skip verifying certificate signature
(Default false)
Returns a Certificate instance.
45 46 47 48 49 50 51 52 53 54 |
# File 'lib/ssh_data/certificate.rb', line 45 def self.parse_openssh(cert, unsafe_no_verify: false) algo, raw, _ = SSHData.key_parts(cert) parsed = parse_rfc4253(raw, unsafe_no_verify: unsafe_no_verify) if parsed.algo != algo raise DecodeError, "algo mismatch: #{parsed.algo.inspect}!=#{algo.inspect}" end parsed end |
.parse_rfc4253(raw, unsafe_no_verify: false) ⇒ Object
Parse an RFC 4253 binary SSH certificate.
cert - A RFC 4253 binary certificate String. unsafe_no_verify: - Bool of whether to skip verifying certificate
signature (Default false)
Returns a Certificate instance.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/ssh_data/certificate.rb', line 66 def self.parse_rfc4253(raw, unsafe_no_verify: false) data, read = Encoding.decode_certificate(raw) if read != raw.bytesize raise DecodeError, "unexpected trailing data" end # Parse data into better types, where possible. public_key = PublicKey.from_data(data.delete(:public_key)) ca_key = PublicKey.from_data(data.delete(:signature_key)) new(**data.merge(public_key: public_key, ca_key: ca_key)).tap do |cert| raise VerifyError unless unsafe_no_verify || cert.verify end end |
Instance Method Details
#allowed_source_address?(address) ⇒ Boolean
Check if the given IP address is allowed for use with this certificate.
address - A String IP address.
Returns boolean.
213 214 215 216 217 218 219 |
# File 'lib/ssh_data/certificate.rb', line 213 def allowed_source_address?(address) return true if source_address.nil? parsed_addr = IPAddr.new(address) source_address.any? { |a| a.include?(parsed_addr) } rescue IPAddr::InvalidAddressError return false end |
#force_command ⇒ Object
The force-command critical option, if present.
Returns a String or nil.
175 176 177 178 179 180 181 182 |
# File 'lib/ssh_data/certificate.rb', line 175 def force_command case value = [CRITICAL_OPTION_FORCE_COMMAND] when String, NilClass value else raise DecodeError, "bad force-request" end end |
#openssh(comment: nil) ⇒ Object
OpenSSH certificate in authorized_keys format (see sshd(8) manual page).
comment - Optional String comment to append.
Returns a String key.
128 129 130 |
# File 'lib/ssh_data/certificate.rb', line 128 def openssh(comment: nil) [algo, Base64.strict_encode64(rfc4253), comment].compact.join(" ") end |
#rfc4253 ⇒ Object
RFC4253 binary encoding of the certificate.
Returns a binary String.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/ssh_data/certificate.rb', line 135 def rfc4253 Encoding.encode_fields( [:string, algo], [:string, nonce], [:raw, public_key_without_algo], [:uint64, serial], [:uint32, type], [:string, key_id], [:list, valid_principals], [:time, valid_after], [:time, valid_before], [:options, ], [:options, extensions], [:string, reserved], [:string, ca_key.rfc4253], [:string, signature], ) end |
#sign(private_key, algo: nil) ⇒ Object
Sign this certificate with a private key.
private_key - An SSHData::PrivateKey::Base subclass instance. algo: - Optionally specify the signature algorithm to use.
Returns nothing.
160 161 162 163 |
# File 'lib/ssh_data/certificate.rb', line 160 def sign(private_key, algo: nil) @ca_key = private_key.public_key @signature = private_key.sign(signed_data, algo: algo) end |
#source_address ⇒ Object
The source-address critical option, if present.
Returns an Array of IPAddr instances or nil.
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/ssh_data/certificate.rb', line 187 def source_address return @source_address if defined?(@source_address) value = [CRITICAL_OPTION_SOURCE_ADDRESS] @source_address = case value when String value.split(",").map do |str_addr| begin IPAddr.new(str_addr.strip) rescue IPAddr::InvalidAddressError => e raise DecodeError, "bad source-address: #{e.}" end end when NilClass nil else raise DecodeError, "bad source-address" end end |
#verify ⇒ Object
Verify the certificate’s signature.
Returns boolean.
168 169 170 |
# File 'lib/ssh_data/certificate.rb', line 168 def verify ca_key.verify(signed_data, signature) end |