decode public keys
This commit is contained in:
Родитель
d970afb4d8
Коммит
212f3fd997
|
@ -3,4 +3,5 @@ end
|
|||
|
||||
require "ssh_data/error"
|
||||
require "ssh_data/certificate"
|
||||
require "ssh_data/public_key"
|
||||
require "ssh_data/encoding"
|
||||
|
|
|
@ -1,45 +1,62 @@
|
|||
class SSHData::Certificate
|
||||
# Integer certificate types (denotes host vs. user)
|
||||
# Integer certificate types
|
||||
TYPE_USER = 1
|
||||
TYPE_HOST = 2
|
||||
|
||||
# String certificate types (denotes key type).
|
||||
RSA_CERT_TYPE = "ssh-rsa-cert-v01@openssh.com"
|
||||
DSA_CERT_TYPE = "ssh-dss-cert-v01@openssh.com"
|
||||
ECDSA_SHA2_NISTP256_CERT_TYPE = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
|
||||
ECDSA_SHA2_NISTP384_CERT_TYPE = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
|
||||
ECDSA_SHA2_NISTP521_CERT_TYPE = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
|
||||
ED25519_CERT_TYPE = "ssh-ed25519-cert-v01@openssh.com"
|
||||
# Certificate algorithm identifiers
|
||||
ALGO_RSA = "ssh-rsa-cert-v01@openssh.com"
|
||||
ALGO_DSA = "ssh-dss-cert-v01@openssh.com"
|
||||
ALGO_ECDSA256 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
|
||||
ALGO_ECDSA384 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
|
||||
ALGO_ECDSA521 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
|
||||
ALGO_ED25519 = "ssh-ed25519-cert-v01@openssh.com"
|
||||
|
||||
attr_reader :type_string, :nonce, :key_data, :serial, :type, :key_id,
|
||||
attr_reader :algo, :nonce, :key_data, :serial, :type, :key_id,
|
||||
:valid_principals, :valid_after, :valid_before, :critical_options,
|
||||
:extensions, :reserved, :signature_key, :signature, :signed_data
|
||||
|
||||
# Parse an SSH certificate.
|
||||
#
|
||||
# cert - An SSH formatted certificate, including key type, encoded key and
|
||||
# cert - An SSH formatted certificate, including key algo, encoded key and
|
||||
# optional user/host names.
|
||||
#
|
||||
# Returns a Certificate instance.
|
||||
def self.parse(cert)
|
||||
data = SSHData::Encoding.parse_certificate(cert)
|
||||
algo, b64, _ = cert.split(" ", 3)
|
||||
if algo.nil? || b64.nil?
|
||||
raise SSHData::DecodeError, "bad certificate format"
|
||||
end
|
||||
|
||||
raw = Base64.decode64(b64)
|
||||
data, read = SSHData::Encoding.decode_certificate(raw)
|
||||
|
||||
if read != raw.bytesize
|
||||
raise SSHData::DecodeError, "unexpected trailing data"
|
||||
end
|
||||
|
||||
if data[:algo] != algo
|
||||
raise SSHData::DecodeError, "algo mismatch: #{data[:algo].inspect}!=#{algo.inspect}"
|
||||
end
|
||||
|
||||
# Parse data into better types, where possible.
|
||||
data[:valid_after] = Time.at(data[:valid_after])
|
||||
data[:valid_before] = Time.at(data[:valid_before])
|
||||
|
||||
# TODO: parse more fields, where possible
|
||||
# The signature is the last field. The signature is calculated over all
|
||||
# preceding data.
|
||||
signed_data_len = raw.bytesize - data[:signature].bytesize
|
||||
data[:signed_data] = raw.byteslice(0, signed_data_len)
|
||||
|
||||
new(**data)
|
||||
end
|
||||
|
||||
# Intialize a new Certificate instance.
|
||||
#
|
||||
# type_string: - The certificate's String type (one of RSA_CERT_TYPE,
|
||||
# DSA_CERT_TYPE, ECDSA_SHA2_NISTP256_CERT_TYPE,
|
||||
# ECDSA_SHA2_NISTP384_CERT_TYPE,
|
||||
# ECDSA_SHA2_NISTP521_CERT_TYPE, or ED25519_CERT_TYPE)
|
||||
# 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.
|
||||
# key_data: - Hash of key-type-speciric data for public key.
|
||||
# key_data: - Hash of key-type-specific data for public key.
|
||||
# serial: - The certificate's Integer serial field.
|
||||
# type: - The certificate's Integer type field (one of TYPE_USER
|
||||
# or TYPE_HOST).
|
||||
|
@ -57,8 +74,8 @@ class SSHData::Certificate
|
|||
# calculated during parsing.
|
||||
#
|
||||
# Returns nothing.
|
||||
def initialize(type_string:, nonce:, key_data:, serial:, type:, key_id:, valid_principals:, valid_after:, valid_before:, critical_options:, extensions:, reserved:, signature_key:, signature:, signed_data:)
|
||||
@type_string = type_string
|
||||
def initialize(algo:, nonce:, key_data:, serial:, type:, key_id:, valid_principals:, valid_after:, valid_before:, critical_options:, extensions:, reserved:, signature_key:, signature:, signed_data:)
|
||||
@algo = algo
|
||||
@nonce = nonce
|
||||
@key_data = key_data
|
||||
@serial = serial
|
||||
|
|
|
@ -2,100 +2,118 @@ require "openssl"
|
|||
require "base64"
|
||||
|
||||
module SSHData::Encoding
|
||||
# Certificate fields that come before the public key.
|
||||
CERT_HEADER_FIELDS = [
|
||||
[:type_string, :string],
|
||||
[:nonce, :string],
|
||||
# Fields in an RSA public key
|
||||
RSA_KEY_FIELDS = [
|
||||
[:e, :mpint],
|
||||
[:n, :mpint]
|
||||
]
|
||||
|
||||
# Certificate fields that come after the public key.
|
||||
CERT_TRAILER_FIELDS = [
|
||||
[:serial, :uint64],
|
||||
[:type, :uint32],
|
||||
[:key_id, :string],
|
||||
[:valid_principals, :string],
|
||||
[:valid_after, :uint64],
|
||||
[:valid_before, :uint64],
|
||||
[:critical_options, :string],
|
||||
[:extensions, :string],
|
||||
[:reserved, :string],
|
||||
[:signature_key, :string],
|
||||
# Fields in a DSA public key
|
||||
DSA_KEY_FIELDS = [
|
||||
[:p, :mpint],
|
||||
[:q, :mpint],
|
||||
[:g, :mpint],
|
||||
[:y, :mpint]
|
||||
]
|
||||
|
||||
# The fields describing the public key for each type of certificate.
|
||||
KEY_FIELDS_BY_CERT_TYPE = {
|
||||
SSHData::Certificate::RSA_CERT_TYPE => [
|
||||
[:e, :mpint],
|
||||
[:n, :mpint]
|
||||
],
|
||||
SSHData::Certificate::DSA_CERT_TYPE => [
|
||||
[:p, :mpint],
|
||||
[:q, :mpint],
|
||||
[:g, :mpint],
|
||||
[:y, :mpint]
|
||||
],
|
||||
SSHData::Certificate::ECDSA_SHA2_NISTP256_CERT_TYPE => [
|
||||
[:curve, :string],
|
||||
[:public_key, :string]
|
||||
],
|
||||
SSHData::Certificate::ECDSA_SHA2_NISTP384_CERT_TYPE => [
|
||||
[:curve, :string],
|
||||
[:public_key, :string]
|
||||
],
|
||||
SSHData::Certificate::ECDSA_SHA2_NISTP521_CERT_TYPE => [
|
||||
[:curve, :string],
|
||||
[:public_key, :string]
|
||||
],
|
||||
SSHData::Certificate::ED25519_CERT_TYPE => [
|
||||
[:pk, :string]
|
||||
]
|
||||
# Fields in an ECDSA public key
|
||||
ECDSA_KEY_FIELDS = [
|
||||
[:curve, :string],
|
||||
[:public_key, :string]
|
||||
]
|
||||
|
||||
# Fields in a ED25519 public key
|
||||
ED25519_KEY_FIELDS = [
|
||||
[:pk, :string]
|
||||
]
|
||||
|
||||
PUBLIC_KEY_ALGO_BY_CERT_ALGO = {
|
||||
SSHData::Certificate::ALGO_RSA => SSHData::PublicKey::ALGO_RSA,
|
||||
SSHData::Certificate::ALGO_DSA => SSHData::PublicKey::ALGO_DSA,
|
||||
SSHData::Certificate::ALGO_ECDSA256 => SSHData::PublicKey::ALGO_ECDSA256,
|
||||
SSHData::Certificate::ALGO_ECDSA384 => SSHData::PublicKey::ALGO_ECDSA384,
|
||||
SSHData::Certificate::ALGO_ECDSA521 => SSHData::PublicKey::ALGO_ECDSA521,
|
||||
SSHData::Certificate::ALGO_ED25519 => SSHData::PublicKey::ALGO_ED25519,
|
||||
}
|
||||
|
||||
KEY_FIELDS_BY_PUBLIC_KEY_ALGO = {
|
||||
SSHData::PublicKey::ALGO_RSA => RSA_KEY_FIELDS,
|
||||
SSHData::PublicKey::ALGO_DSA => DSA_KEY_FIELDS,
|
||||
SSHData::PublicKey::ALGO_ECDSA256 => ECDSA_KEY_FIELDS,
|
||||
SSHData::PublicKey::ALGO_ECDSA384 => ECDSA_KEY_FIELDS,
|
||||
SSHData::PublicKey::ALGO_ECDSA521 => ECDSA_KEY_FIELDS,
|
||||
SSHData::PublicKey::ALGO_ED25519 => ED25519_KEY_FIELDS,
|
||||
}
|
||||
|
||||
# Decode the fields in a public key.
|
||||
#
|
||||
# raw - Binary String public key as described by RFC4253 section 6.6.
|
||||
# algo - String public key algorithm identifier (optional).
|
||||
# offset - Integer number of bytes into `raw` at which we should start
|
||||
# reading.
|
||||
#
|
||||
# Returns an Array containing a Hash describing the public key and the
|
||||
# Integer number of bytes read.
|
||||
def self.decode_public_key(raw, algo=nil, offset=0)
|
||||
total_read = 0
|
||||
|
||||
if algo.nil?
|
||||
algo, read = read_string(raw, offset + total_read)
|
||||
total_read += read
|
||||
end
|
||||
|
||||
unless fields = KEY_FIELDS_BY_PUBLIC_KEY_ALGO[algo]
|
||||
raise SSHData::DecodeError, "unknown key algo: #{algo.inspect}"
|
||||
end
|
||||
|
||||
data, read = decode_all(raw, fields, offset + total_read)
|
||||
total_read += read
|
||||
|
||||
data[:algo] = algo
|
||||
|
||||
[data, total_read]
|
||||
end
|
||||
|
||||
# Decode the fields in a certificate.
|
||||
#
|
||||
# cert - An SSH formatted certificate, including key type, encoded key and
|
||||
# optional user/host names.
|
||||
# raw - Binary String certificate as described by RFC4253 section 6.6.
|
||||
# offset - Integer number of bytes into `raw` at which we should start
|
||||
# reading.
|
||||
#
|
||||
# Returns a Hash of the certificate's fields.
|
||||
def self.parse_certificate(cert)
|
||||
type, cert_b64, _ = cert.split(" ")
|
||||
if cert_b64.nil?
|
||||
raise SSHData::DecodeError
|
||||
elsif !KEY_FIELDS_BY_CERT_TYPE.key?(type)
|
||||
raise SSHData::DecodeError, "unknown certificate type: #{type.inspect}"
|
||||
# Returns an Array containing a Hash describing the certificate and the
|
||||
# Integer number of bytes read.
|
||||
def self.decode_certificate(raw, offset=0)
|
||||
total_read = 0
|
||||
|
||||
data, read = decode_all(raw, [
|
||||
[:algo, :string],
|
||||
[:nonce, :string],
|
||||
], offset + total_read)
|
||||
total_read += read
|
||||
|
||||
unless key_algo = PUBLIC_KEY_ALGO_BY_CERT_ALGO[data[:algo]]
|
||||
raise SSHData::DecodeError, "unknown cert algo: #{data[:algo].inspect}"
|
||||
end
|
||||
|
||||
cert_raw = Base64.decode64(cert_b64)
|
||||
offset = 0
|
||||
data = {}
|
||||
data[:key_data], read = decode_public_key(raw, key_algo, offset + total_read)
|
||||
total_read += read
|
||||
|
||||
header_data, read = decode_all(cert_raw, CERT_HEADER_FIELDS, 0)
|
||||
offset += read
|
||||
data.merge!(header_data)
|
||||
trailer, read = decode_all(raw, [
|
||||
[:serial, :uint64],
|
||||
[:type, :uint32],
|
||||
[:key_id, :string],
|
||||
[:valid_principals, :string],
|
||||
[:valid_after, :uint64],
|
||||
[:valid_before, :uint64],
|
||||
[:critical_options, :string],
|
||||
[:extensions, :string],
|
||||
[:reserved, :string],
|
||||
[:signature_key, :string],
|
||||
[:signature, :string],
|
||||
], offset + total_read)
|
||||
total_read += read
|
||||
|
||||
if type != data[:type_string]
|
||||
raise SSHData::DecodeError, "type mismatch: #{type.inspect}!=#{data[:type_string].inspect}"
|
||||
end
|
||||
|
||||
key_fields = KEY_FIELDS_BY_CERT_TYPE[type]
|
||||
data[:key_data], read = decode_all(cert_raw, key_fields, offset)
|
||||
offset += read
|
||||
|
||||
trailer_data, read = decode_all(cert_raw, CERT_TRAILER_FIELDS, offset)
|
||||
offset += read
|
||||
data.merge!(trailer_data)
|
||||
|
||||
# The signature is over all data up to the signature field. This isn't its
|
||||
# own field, but we parse it out here so we don't have to do it later.
|
||||
data[:signed_data] = cert_raw.byteslice(0, read)
|
||||
data[:signature], read = read_string(cert_raw, offset)
|
||||
offset += read
|
||||
|
||||
if cert_raw.bytesize != offset
|
||||
raise SSHData::DecodeError, "bad data length"
|
||||
end
|
||||
|
||||
data
|
||||
[data.merge(trailer), total_read]
|
||||
end
|
||||
|
||||
# Decode all of the given fields from data.
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
class SSHData::PublicKey
|
||||
# Public key algorithm identifiers
|
||||
ALGO_RSA = "ssh-rsa"
|
||||
ALGO_DSA = "ssh-dss"
|
||||
ALGO_ECDSA256 = "ecdsa-sha2-nistp256"
|
||||
ALGO_ECDSA384 = "ecdsa-sha2-nistp384"
|
||||
ALGO_ECDSA521 = "ecdsa-sha2-nistp521"
|
||||
ALGO_ED25519 = "ssh-ed25519"
|
||||
end
|
|
@ -14,8 +14,38 @@ describe SSHData::Certificate do
|
|||
let(:min_time) { Time.at(0) }
|
||||
let(:max_time) { Time.at((2**64)-1) }
|
||||
|
||||
it "raises on trailing data" do
|
||||
algo, b64, host = fixture("rsa_leaf_for_rsa_ca-cert.pub").split(" ", 3)
|
||||
raw = Base64.decode64(b64)
|
||||
raw += "foobar"
|
||||
b64 = Base64.strict_encode64(raw)
|
||||
cert = [algo, b64, host].join(" ")
|
||||
|
||||
expect {
|
||||
described_class.parse(cert)
|
||||
}.to raise_error(SSHData::DecodeError)
|
||||
end
|
||||
|
||||
it "raises on type mismatch" do
|
||||
_, b64, host = fixture("rsa_leaf_for_rsa_ca-cert.pub").split(" ", 3)
|
||||
cert = [SSHData::Certificate::ALGO_ED25519, b64, host].join(" ")
|
||||
|
||||
expect {
|
||||
described_class.parse(cert)
|
||||
}.to raise_error(SSHData::DecodeError)
|
||||
end
|
||||
|
||||
it "doesn't require the user/host names" do
|
||||
type, b64, _ = fixture("rsa_leaf_for_rsa_ca-cert.pub").split(" ", 3)
|
||||
cert = [type, b64].join(" ")
|
||||
|
||||
expect {
|
||||
described_class.parse(cert)
|
||||
}.not_to raise_error
|
||||
end
|
||||
|
||||
it "parses RSA certs" do
|
||||
expect(rsa_cert.type_string).to eq(SSHData::Certificate::RSA_CERT_TYPE)
|
||||
expect(rsa_cert.algo).to eq(SSHData::Certificate::ALGO_RSA)
|
||||
expect(rsa_cert.nonce).to be_a(String)
|
||||
expect(rsa_cert.key_data).to be_a(Hash)
|
||||
expect(rsa_cert.serial).to eq(123)
|
||||
|
@ -29,11 +59,10 @@ describe SSHData::Certificate do
|
|||
expect(rsa_cert.reserved).to eq("")
|
||||
expect(rsa_cert.signature_key).to be_a(String)
|
||||
expect(rsa_cert.signature).to be_a(String)
|
||||
expect(rsa_cert.signed_data).to be_a(String)
|
||||
end
|
||||
|
||||
it "parses DSA certs" do
|
||||
expect(dsa_cert.type_string).to eq(SSHData::Certificate::DSA_CERT_TYPE)
|
||||
expect(dsa_cert.algo).to eq(SSHData::Certificate::ALGO_DSA)
|
||||
expect(dsa_cert.nonce).to be_a(String)
|
||||
expect(dsa_cert.key_data).to be_a(Hash)
|
||||
expect(dsa_cert.serial).to eq(123)
|
||||
|
@ -47,11 +76,10 @@ describe SSHData::Certificate do
|
|||
expect(dsa_cert.reserved).to eq("")
|
||||
expect(dsa_cert.signature_key).to be_a(String)
|
||||
expect(dsa_cert.signature).to be_a(String)
|
||||
expect(dsa_cert.signed_data).to be_a(String)
|
||||
end
|
||||
|
||||
it "parses ECDSA certs" do
|
||||
expect(ecdsa_cert.type_string).to eq(SSHData::Certificate::ECDSA_SHA2_NISTP256_CERT_TYPE)
|
||||
expect(ecdsa_cert.algo).to eq(SSHData::Certificate::ALGO_ECDSA256)
|
||||
expect(ecdsa_cert.nonce).to be_a(String)
|
||||
expect(ecdsa_cert.key_data).to be_a(Hash)
|
||||
expect(ecdsa_cert.serial).to eq(123)
|
||||
|
@ -65,11 +93,10 @@ describe SSHData::Certificate do
|
|||
expect(ecdsa_cert.reserved).to eq("")
|
||||
expect(ecdsa_cert.signature_key).to be_a(String)
|
||||
expect(ecdsa_cert.signature).to be_a(String)
|
||||
expect(ecdsa_cert.signed_data).to be_a(String)
|
||||
end
|
||||
|
||||
it "parses ED25519 certs" do
|
||||
expect(ed25519_cert.type_string).to eq(SSHData::Certificate::ED25519_CERT_TYPE)
|
||||
expect(ed25519_cert.algo).to eq(SSHData::Certificate::ALGO_ED25519)
|
||||
expect(ed25519_cert.nonce).to be_a(String)
|
||||
expect(ed25519_cert.key_data).to be_a(Hash)
|
||||
expect(ed25519_cert.serial).to eq(123)
|
||||
|
@ -83,11 +110,10 @@ describe SSHData::Certificate do
|
|||
expect(ed25519_cert.reserved).to eq("")
|
||||
expect(ed25519_cert.signature_key).to be_a(String)
|
||||
expect(ed25519_cert.signature).to be_a(String)
|
||||
expect(ed25519_cert.signed_data).to be_a(String)
|
||||
end
|
||||
|
||||
it "parses certs issued by RSA CAs" do
|
||||
expect(rsa_ca_cert.type_string).to eq(SSHData::Certificate::RSA_CERT_TYPE)
|
||||
expect(rsa_ca_cert.algo).to eq(SSHData::Certificate::ALGO_RSA)
|
||||
expect(rsa_ca_cert.nonce).to be_a(String)
|
||||
expect(rsa_ca_cert.key_data).to be_a(Hash)
|
||||
expect(rsa_ca_cert.serial).to eq(123)
|
||||
|
@ -101,11 +127,10 @@ describe SSHData::Certificate do
|
|||
expect(rsa_ca_cert.reserved).to eq("")
|
||||
expect(rsa_ca_cert.signature_key).to be_a(String)
|
||||
expect(rsa_ca_cert.signature).to be_a(String)
|
||||
expect(rsa_ca_cert.signed_data).to be_a(String)
|
||||
end
|
||||
|
||||
it "parses certs issued by DSA CAs" do
|
||||
expect(dsa_ca_cert.type_string).to eq(SSHData::Certificate::RSA_CERT_TYPE)
|
||||
expect(dsa_ca_cert.algo).to eq(SSHData::Certificate::ALGO_RSA)
|
||||
expect(dsa_ca_cert.nonce).to be_a(String)
|
||||
expect(dsa_ca_cert.key_data).to be_a(Hash)
|
||||
expect(dsa_ca_cert.serial).to eq(123)
|
||||
|
@ -119,11 +144,10 @@ describe SSHData::Certificate do
|
|||
expect(dsa_ca_cert.reserved).to eq("")
|
||||
expect(dsa_ca_cert.signature_key).to be_a(String)
|
||||
expect(dsa_ca_cert.signature).to be_a(String)
|
||||
expect(dsa_ca_cert.signed_data).to be_a(String)
|
||||
end
|
||||
|
||||
it "parses certs issued by ECDSA CAs" do
|
||||
expect(ecdsa_ca_cert.type_string).to eq(SSHData::Certificate::RSA_CERT_TYPE)
|
||||
expect(ecdsa_ca_cert.algo).to eq(SSHData::Certificate::ALGO_RSA)
|
||||
expect(ecdsa_ca_cert.nonce).to be_a(String)
|
||||
expect(ecdsa_ca_cert.key_data).to be_a(Hash)
|
||||
expect(ecdsa_ca_cert.serial).to eq(123)
|
||||
|
@ -137,11 +161,10 @@ describe SSHData::Certificate do
|
|||
expect(ecdsa_ca_cert.reserved).to eq("")
|
||||
expect(ecdsa_ca_cert.signature_key).to be_a(String)
|
||||
expect(ecdsa_ca_cert.signature).to be_a(String)
|
||||
expect(ecdsa_ca_cert.signed_data).to be_a(String)
|
||||
end
|
||||
|
||||
it "parses certs issued by ED25519 CAs" do
|
||||
expect(ed25519_ca_cert.type_string).to eq(SSHData::Certificate::RSA_CERT_TYPE)
|
||||
expect(ed25519_ca_cert.algo).to eq(SSHData::Certificate::ALGO_RSA)
|
||||
expect(ed25519_ca_cert.nonce).to be_a(String)
|
||||
expect(ed25519_ca_cert.key_data).to be_a(Hash)
|
||||
expect(ed25519_ca_cert.serial).to eq(123)
|
||||
|
@ -155,6 +178,5 @@ describe SSHData::Certificate do
|
|||
expect(ed25519_ca_cert.reserved).to eq("")
|
||||
expect(ed25519_ca_cert.signature_key).to be_a(String)
|
||||
expect(ed25519_ca_cert.signature).to be_a(String)
|
||||
expect(ed25519_ca_cert.signed_data).to be_a(String)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,174 +1,192 @@
|
|||
require_relative "./spec_helper"
|
||||
|
||||
describe SSHData::Encoding do
|
||||
let(:rsa_data) { described_class.parse_certificate(fixture("rsa_leaf_for_rsa_ca-cert.pub")) }
|
||||
let(:dsa_data) { described_class.parse_certificate(fixture("dsa_leaf_for_rsa_ca-cert.pub")) }
|
||||
let(:ecdsa_data) { described_class.parse_certificate(fixture("ecdsa_leaf_for_rsa_ca-cert.pub")) }
|
||||
let(:ed25519_data) { described_class.parse_certificate(fixture("ed25519_leaf_for_rsa_ca-cert.pub")) }
|
||||
let(:rsa_key_data) { described_class.decode_public_key(fixture("rsa_leaf_for_rsa_ca.pub", binary: true)).first }
|
||||
let(:dsa_key_data) { described_class.decode_public_key(fixture("dsa_leaf_for_rsa_ca.pub", binary: true)).first }
|
||||
let(:ecdsa_key_data) { described_class.decode_public_key(fixture("ecdsa_leaf_for_rsa_ca.pub", binary: true)).first }
|
||||
let(:ed25519_key_data) { described_class.decode_public_key(fixture("ed25519_leaf_for_rsa_ca.pub", binary: true)).first }
|
||||
|
||||
let(:rsa_ca_data) { described_class.parse_certificate(fixture("rsa_leaf_for_rsa_ca-cert.pub")) }
|
||||
let(:dsa_ca_data) { described_class.parse_certificate(fixture("rsa_leaf_for_dsa_ca-cert.pub")) }
|
||||
let(:ecdsa_ca_data) { described_class.parse_certificate(fixture("rsa_leaf_for_ecdsa_ca-cert.pub")) }
|
||||
let(:ed25519_ca_data) { described_class.parse_certificate(fixture("rsa_leaf_for_ed25519_ca-cert.pub")) }
|
||||
let(:rsa_cert_data) { described_class.decode_certificate(fixture("rsa_leaf_for_rsa_ca-cert.pub", binary: true)).first }
|
||||
let(:dsa_cert_data) { described_class.decode_certificate(fixture("dsa_leaf_for_rsa_ca-cert.pub", binary: true)).first }
|
||||
let(:ecdsa_cert_data) { described_class.decode_certificate(fixture("ecdsa_leaf_for_rsa_ca-cert.pub", binary: true)).first }
|
||||
let(:ed25519_cert_data) { described_class.decode_certificate(fixture("ed25519_leaf_for_rsa_ca-cert.pub", binary: true)).first }
|
||||
|
||||
it "raises on type mismatch" do
|
||||
_, cert, host = fixture("rsa_leaf_for_rsa_ca-cert.pub").split(" ", 3)
|
||||
bad_type_cert = [SSHData::Certificate::ED25519_CERT_TYPE, cert, host].join(" ")
|
||||
expect {
|
||||
described_class.parse_certificate(bad_type_cert)
|
||||
}.to raise_error(SSHData::DecodeError)
|
||||
let(:rsa_ca_data) { described_class.decode_certificate(fixture("rsa_leaf_for_rsa_ca-cert.pub", binary: true)).first }
|
||||
let(:dsa_ca_data) { described_class.decode_certificate(fixture("rsa_leaf_for_dsa_ca-cert.pub", binary: true)).first }
|
||||
let(:ecdsa_ca_data) { described_class.decode_certificate(fixture("rsa_leaf_for_ecdsa_ca-cert.pub", binary: true)).first }
|
||||
let(:ed25519_ca_data) { described_class.decode_certificate(fixture("rsa_leaf_for_ed25519_ca-cert.pub", binary: true)).first }
|
||||
|
||||
it "can decode a public key at an offset" do
|
||||
prefix = "foobar"
|
||||
raw = fixture("rsa_leaf_for_rsa_ca.pub", binary: true)
|
||||
with_prefix = [prefix, raw].join
|
||||
|
||||
data, _ = described_class.decode_public_key(with_prefix, nil, prefix.bytesize).first
|
||||
|
||||
expect(data).to eq(rsa_key_data)
|
||||
end
|
||||
|
||||
it "doesn't require the user/host names" do
|
||||
type, cert, _ = fixture("rsa_leaf_for_rsa_ca-cert.pub").split(" ", 3)
|
||||
no_host_cert = [type, cert].join(" ")
|
||||
expect {
|
||||
described_class.parse_certificate(no_host_cert)
|
||||
}.not_to raise_error
|
||||
it "can skip the algo when decoding a public key" do
|
||||
raw = fixture("rsa_leaf_for_rsa_ca.pub", binary: true)
|
||||
algo, offset = described_class.read_string(raw)
|
||||
data, _ = described_class.decode_public_key(raw, algo, offset)
|
||||
|
||||
expect(data).to eq(rsa_key_data)
|
||||
end
|
||||
|
||||
it "can decode an RSA public key" do
|
||||
expect(rsa_key_data[:algo]).to eq(SSHData::PublicKey::ALGO_RSA)
|
||||
expect(rsa_key_data[:e]).to be_a(OpenSSL::BN)
|
||||
expect(rsa_key_data[:n]).to be_a(OpenSSL::BN)
|
||||
end
|
||||
|
||||
it "can decode an DSA public key" do
|
||||
expect(dsa_key_data[:algo]).to eq(SSHData::PublicKey::ALGO_DSA)
|
||||
expect(dsa_key_data[:p]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_key_data[:q]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_key_data[:g]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_key_data[:y]).to be_a(OpenSSL::BN)
|
||||
end
|
||||
|
||||
it "can decode an ECDSA public key" do
|
||||
expect(ecdsa_key_data[:algo]).to eq(SSHData::PublicKey::ALGO_ECDSA256)
|
||||
expect(ecdsa_key_data[:curve]).to eq("nistp256")
|
||||
expect(ecdsa_key_data[:public_key]).to be_a(String)
|
||||
end
|
||||
|
||||
it "can decode an ED25519 public key" do
|
||||
expect(ed25519_key_data[:algo]).to eq(SSHData::PublicKey::ALGO_ED25519)
|
||||
expect(ed25519_key_data[:pk]).to be_a(String)
|
||||
end
|
||||
|
||||
it "can decode a certificate at an offset" do
|
||||
prefix = "foobar"
|
||||
raw = fixture("rsa_leaf_for_rsa_ca-cert.pub", binary: true)
|
||||
with_prefix = [prefix, raw].join
|
||||
|
||||
data = described_class.decode_certificate(with_prefix, prefix.bytesize).first
|
||||
|
||||
expect(data).to eq(rsa_cert_data)
|
||||
end
|
||||
|
||||
it "can decode RSA certificates" do
|
||||
expect(rsa_data[:type_string]).to eq(SSHData::Certificate::RSA_CERT_TYPE)
|
||||
expect(rsa_cert_data[:algo]).to eq(SSHData::Certificate::ALGO_RSA)
|
||||
|
||||
expect(rsa_data[:nonce]).to be_a(String)
|
||||
expect(rsa_data[:nonce].length).to eq(32)
|
||||
expect(rsa_cert_data[:nonce]).to be_a(String)
|
||||
expect(rsa_cert_data[:nonce].length).to eq(32)
|
||||
|
||||
expect(rsa_data[:key_data][:e]).to be_a(OpenSSL::BN)
|
||||
expect(rsa_data[:key_data][:e]).not_to eq(OpenSSL::BN.new(0))
|
||||
expect(rsa_cert_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_RSA)
|
||||
expect(rsa_cert_data[:key_data][:e]).to be_a(OpenSSL::BN)
|
||||
expect(rsa_cert_data[:key_data][:n]).to be_a(OpenSSL::BN)
|
||||
|
||||
expect(rsa_data[:key_data][:n]).to be_a(OpenSSL::BN)
|
||||
expect(rsa_data[:key_data][:n]).not_to eq(OpenSSL::BN.new(0))
|
||||
expect(rsa_cert_data[:serial]).to eq(123)
|
||||
expect(rsa_cert_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
expect(rsa_cert_data[:key_id]).to eq("my-ident")
|
||||
expect(rsa_cert_data[:valid_principals]).to eq("\x00\x00\x00\x0Cmy-principal")
|
||||
expect(rsa_cert_data[:valid_after]).to eq(0)
|
||||
expect(rsa_cert_data[:valid_before]).to eq((2**64)-1)
|
||||
expect(rsa_cert_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
|
||||
expect(rsa_cert_data[:extensions]).to eq("\x00\x00\x00\x03baz\x00\x00\x00\x08\x00\x00\x00\x04qwer")
|
||||
expect(rsa_cert_data[:reserved]).to eq("")
|
||||
|
||||
expect(rsa_data[:serial]).to eq(123)
|
||||
expect(rsa_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
expect(rsa_data[:key_id]).to eq("my-ident")
|
||||
expect(rsa_data[:valid_principals]).to eq("\x00\x00\x00\x0Cmy-principal")
|
||||
expect(rsa_data[:valid_after]).to eq(0)
|
||||
expect(rsa_data[:valid_before]).to eq((2**64)-1)
|
||||
expect(rsa_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
|
||||
expect(rsa_data[:extensions]).to eq("\x00\x00\x00\x03baz\x00\x00\x00\x08\x00\x00\x00\x04qwer")
|
||||
expect(rsa_data[:reserved]).to eq("")
|
||||
expect(rsa_cert_data[:signature_key]).to be_a(String)
|
||||
expect(rsa_cert_data[:signature_key].bytesize).to eq(279)
|
||||
|
||||
expect(rsa_data[:signature_key]).to be_a(String)
|
||||
expect(rsa_data[:signature_key].bytesize).to eq(279)
|
||||
|
||||
expect(rsa_data[:signed_data]).to be_a(String)
|
||||
expect(rsa_data[:signed_data].bytesize).to eq(392)
|
||||
|
||||
expect(rsa_data[:signature]).to be_a(String)
|
||||
expect(rsa_data[:signature].bytesize).to eq(271)
|
||||
expect(rsa_cert_data[:signature]).to be_a(String)
|
||||
expect(rsa_cert_data[:signature].bytesize).to eq(271)
|
||||
end
|
||||
|
||||
it "can decode DSA certificates" do
|
||||
expect(dsa_data[:type_string]).to eq(SSHData::Certificate::DSA_CERT_TYPE)
|
||||
expect(dsa_cert_data[:algo]).to eq(SSHData::Certificate::ALGO_DSA)
|
||||
|
||||
expect(dsa_data[:nonce]).to be_a(String)
|
||||
expect(dsa_data[:nonce].length).to eq(32)
|
||||
expect(dsa_cert_data[:nonce]).to be_a(String)
|
||||
expect(dsa_cert_data[:nonce].length).to eq(32)
|
||||
|
||||
expect(dsa_data[:key_data][:p]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_data[:key_data][:p]).not_to eq(OpenSSL::BN.new(0))
|
||||
expect(dsa_cert_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_DSA)
|
||||
expect(dsa_cert_data[:key_data][:p]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_cert_data[:key_data][:q]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_cert_data[:key_data][:g]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_cert_data[:key_data][:y]).to be_a(OpenSSL::BN)
|
||||
|
||||
expect(dsa_data[:key_data][:q]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_data[:key_data][:q]).not_to eq(OpenSSL::BN.new(0))
|
||||
expect(dsa_cert_data[:serial]).to eq(123)
|
||||
expect(dsa_cert_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
expect(dsa_cert_data[:key_id]).to eq("my-ident")
|
||||
expect(dsa_cert_data[:valid_principals]).to eq("\x00\x00\x00\x0Cmy-principal")
|
||||
expect(dsa_cert_data[:valid_after]).to eq(0)
|
||||
expect(dsa_cert_data[:valid_before]).to eq((2**64)-1)
|
||||
expect(dsa_cert_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
|
||||
expect(dsa_cert_data[:extensions]).to eq("\x00\x00\x00\x03baz\x00\x00\x00\x08\x00\x00\x00\x04qwer")
|
||||
expect(dsa_cert_data[:reserved]).to eq("")
|
||||
|
||||
expect(dsa_data[:key_data][:g]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_data[:key_data][:g]).not_to eq(OpenSSL::BN.new(0))
|
||||
expect(dsa_cert_data[:signature_key]).to be_a(String)
|
||||
expect(dsa_cert_data[:signature_key].bytesize).to eq(279)
|
||||
|
||||
expect(dsa_data[:key_data][:y]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_data[:key_data][:y]).not_to eq(OpenSSL::BN.new(0))
|
||||
|
||||
expect(dsa_data[:serial]).to eq(123)
|
||||
expect(dsa_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
expect(dsa_data[:key_id]).to eq("my-ident")
|
||||
expect(dsa_data[:valid_principals]).to eq("\x00\x00\x00\x0Cmy-principal")
|
||||
expect(dsa_data[:valid_after]).to eq(0)
|
||||
expect(dsa_data[:valid_before]).to eq((2**64)-1)
|
||||
expect(dsa_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
|
||||
expect(dsa_data[:extensions]).to eq("\x00\x00\x00\x03baz\x00\x00\x00\x08\x00\x00\x00\x04qwer")
|
||||
expect(dsa_data[:reserved]).to eq("")
|
||||
|
||||
expect(dsa_data[:signature_key]).to be_a(String)
|
||||
expect(dsa_data[:signature_key].bytesize).to eq(279)
|
||||
|
||||
expect(dsa_data[:signed_data]).to be_a(String)
|
||||
expect(dsa_data[:signed_data].bytesize).to eq(392)
|
||||
|
||||
expect(dsa_data[:signature]).to be_a(String)
|
||||
expect(dsa_data[:signature].bytesize).to eq(271)
|
||||
expect(dsa_cert_data[:signature]).to be_a(String)
|
||||
expect(dsa_cert_data[:signature].bytesize).to eq(271)
|
||||
end
|
||||
|
||||
it "can decode ECDSA certificates" do
|
||||
expect(ecdsa_data[:type_string]).to eq(SSHData::Certificate::ECDSA_SHA2_NISTP256_CERT_TYPE)
|
||||
expect(ecdsa_cert_data[:algo]).to eq(SSHData::Certificate::ALGO_ECDSA256)
|
||||
|
||||
expect(ecdsa_data[:nonce]).to be_a(String)
|
||||
expect(ecdsa_data[:nonce].length).to eq(32)
|
||||
expect(ecdsa_cert_data[:nonce]).to be_a(String)
|
||||
expect(ecdsa_cert_data[:nonce].length).to eq(32)
|
||||
|
||||
expect(ecdsa_data[:key_data][:curve]).to be_a(String)
|
||||
expect(ecdsa_data[:key_data][:curve]).to eq("nistp256")
|
||||
expect(ecdsa_cert_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_ECDSA256)
|
||||
expect(ecdsa_cert_data[:key_data][:curve]).to eq("nistp256")
|
||||
expect(ecdsa_cert_data[:key_data][:public_key]).to be_a(String)
|
||||
|
||||
expect(ecdsa_data[:key_data][:public_key]).to be_a(String)
|
||||
expect(ecdsa_data[:key_data][:public_key].length).to eq(65)
|
||||
expect(ecdsa_cert_data[:serial]).to eq(123)
|
||||
expect(ecdsa_cert_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
expect(ecdsa_cert_data[:key_id]).to eq("my-ident")
|
||||
expect(ecdsa_cert_data[:valid_principals]).to eq("\x00\x00\x00\x0Cmy-principal")
|
||||
expect(ecdsa_cert_data[:valid_after]).to eq(0)
|
||||
expect(ecdsa_cert_data[:valid_before]).to eq((2**64)-1)
|
||||
expect(ecdsa_cert_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
|
||||
expect(ecdsa_cert_data[:extensions]).to eq("\x00\x00\x00\x03baz\x00\x00\x00\x08\x00\x00\x00\x04qwer")
|
||||
expect(ecdsa_cert_data[:reserved]).to eq("")
|
||||
|
||||
expect(ecdsa_data[:serial]).to eq(123)
|
||||
expect(ecdsa_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
expect(ecdsa_data[:key_id]).to eq("my-ident")
|
||||
expect(ecdsa_data[:valid_principals]).to eq("\x00\x00\x00\x0Cmy-principal")
|
||||
expect(ecdsa_data[:valid_after]).to eq(0)
|
||||
expect(ecdsa_data[:valid_before]).to eq((2**64)-1)
|
||||
expect(ecdsa_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
|
||||
expect(ecdsa_data[:extensions]).to eq("\x00\x00\x00\x03baz\x00\x00\x00\x08\x00\x00\x00\x04qwer")
|
||||
expect(ecdsa_data[:reserved]).to eq("")
|
||||
expect(ecdsa_cert_data[:signature_key]).to be_a(String)
|
||||
expect(ecdsa_cert_data[:signature_key].bytesize).to eq(279)
|
||||
|
||||
expect(ecdsa_data[:signature_key]).to be_a(String)
|
||||
expect(ecdsa_data[:signature_key].bytesize).to eq(279)
|
||||
|
||||
expect(ecdsa_data[:signed_data]).to be_a(String)
|
||||
expect(ecdsa_data[:signed_data].bytesize).to eq(392)
|
||||
|
||||
expect(ecdsa_data[:signature]).to be_a(String)
|
||||
expect(ecdsa_data[:signature].bytesize).to eq(271)
|
||||
expect(ecdsa_cert_data[:signature]).to be_a(String)
|
||||
expect(ecdsa_cert_data[:signature].bytesize).to eq(271)
|
||||
end
|
||||
|
||||
it "can decode ED25519 certificates" do
|
||||
expect(ed25519_data[:type_string]).to eq(SSHData::Certificate::ED25519_CERT_TYPE)
|
||||
expect(ed25519_cert_data[:algo]).to eq(SSHData::Certificate::ALGO_ED25519)
|
||||
|
||||
expect(ed25519_data[:nonce]).to be_a(String)
|
||||
expect(ed25519_data[:nonce].length).to eq(32)
|
||||
expect(ed25519_cert_data[:nonce]).to be_a(String)
|
||||
expect(ed25519_cert_data[:nonce].length).to eq(32)
|
||||
|
||||
expect(ed25519_data[:key_data][:pk]).to be_a(String)
|
||||
expect(ed25519_data[:key_data][:pk].length).to eq(32)
|
||||
expect(ed25519_cert_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_ED25519)
|
||||
expect(ed25519_cert_data[:key_data][:pk]).to be_a(String)
|
||||
|
||||
expect(ed25519_data[:serial]).to eq(123)
|
||||
expect(ed25519_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
expect(ed25519_data[:key_id]).to eq("my-ident")
|
||||
expect(ed25519_data[:valid_principals]).to eq("\x00\x00\x00\x0Cmy-principal")
|
||||
expect(ed25519_data[:valid_after]).to eq(0)
|
||||
expect(ed25519_data[:valid_before]).to eq((2**64)-1)
|
||||
expect(ed25519_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
|
||||
expect(ed25519_data[:extensions]).to eq("\x00\x00\x00\x03baz\x00\x00\x00\x08\x00\x00\x00\x04qwer")
|
||||
expect(ed25519_data[:reserved]).to eq("")
|
||||
expect(ed25519_cert_data[:serial]).to eq(123)
|
||||
expect(ed25519_cert_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
expect(ed25519_cert_data[:key_id]).to eq("my-ident")
|
||||
expect(ed25519_cert_data[:valid_principals]).to eq("\x00\x00\x00\x0Cmy-principal")
|
||||
expect(ed25519_cert_data[:valid_after]).to eq(0)
|
||||
expect(ed25519_cert_data[:valid_before]).to eq((2**64)-1)
|
||||
expect(ed25519_cert_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
|
||||
expect(ed25519_cert_data[:extensions]).to eq("\x00\x00\x00\x03baz\x00\x00\x00\x08\x00\x00\x00\x04qwer")
|
||||
expect(ed25519_cert_data[:reserved]).to eq("")
|
||||
|
||||
expect(ed25519_data[:signature_key]).to be_a(String)
|
||||
expect(ed25519_data[:signature_key].bytesize).to eq(279)
|
||||
expect(ed25519_cert_data[:signature_key]).to be_a(String)
|
||||
expect(ed25519_cert_data[:signature_key].bytesize).to eq(279)
|
||||
|
||||
expect(ed25519_data[:signed_data]).to be_a(String)
|
||||
expect(ed25519_data[:signed_data].bytesize).to eq(392)
|
||||
|
||||
expect(ed25519_data[:signature]).to be_a(String)
|
||||
expect(ed25519_data[:signature].bytesize).to eq(271)
|
||||
expect(ed25519_cert_data[:signature]).to be_a(String)
|
||||
expect(ed25519_cert_data[:signature].bytesize).to eq(271)
|
||||
end
|
||||
|
||||
it "can decode certs from RSA CAs" do
|
||||
expect(rsa_ca_data[:type_string]).to eq(SSHData::Certificate::RSA_CERT_TYPE)
|
||||
expect(rsa_ca_data[:algo]).to eq(SSHData::Certificate::ALGO_RSA)
|
||||
|
||||
expect(rsa_ca_data[:nonce]).to be_a(String)
|
||||
expect(rsa_ca_data[:nonce].length).to eq(32)
|
||||
|
||||
expect(rsa_ca_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_RSA)
|
||||
expect(rsa_ca_data[:key_data][:e]).to be_a(OpenSSL::BN)
|
||||
expect(rsa_ca_data[:key_data][:e]).not_to eq(OpenSSL::BN.new(0))
|
||||
|
||||
expect(rsa_ca_data[:key_data][:n]).to be_a(OpenSSL::BN)
|
||||
expect(rsa_ca_data[:key_data][:n]).not_to eq(OpenSSL::BN.new(0))
|
||||
|
||||
expect(rsa_ca_data[:serial]).to eq(123)
|
||||
expect(rsa_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
|
@ -183,24 +201,19 @@ describe SSHData::Encoding do
|
|||
expect(rsa_ca_data[:signature_key]).to be_a(String)
|
||||
expect(rsa_ca_data[:signature_key].bytesize).to eq(279)
|
||||
|
||||
expect(rsa_ca_data[:signed_data]).to be_a(String)
|
||||
expect(rsa_ca_data[:signed_data].bytesize).to eq(392)
|
||||
|
||||
expect(rsa_ca_data[:signature]).to be_a(String)
|
||||
expect(rsa_ca_data[:signature].bytesize).to eq(271)
|
||||
end
|
||||
|
||||
it "can decode certs from DSA CAs" do
|
||||
expect(dsa_ca_data[:type_string]).to eq(SSHData::Certificate::RSA_CERT_TYPE)
|
||||
expect(dsa_ca_data[:algo]).to eq(SSHData::Certificate::ALGO_RSA)
|
||||
|
||||
expect(dsa_ca_data[:nonce]).to be_a(String)
|
||||
expect(dsa_ca_data[:nonce].length).to eq(32)
|
||||
|
||||
expect(dsa_ca_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_RSA)
|
||||
expect(dsa_ca_data[:key_data][:e]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_ca_data[:key_data][:e]).not_to eq(OpenSSL::BN.new(0))
|
||||
|
||||
expect(dsa_ca_data[:key_data][:n]).to be_a(OpenSSL::BN)
|
||||
expect(dsa_ca_data[:key_data][:n]).not_to eq(OpenSSL::BN.new(0))
|
||||
|
||||
expect(dsa_ca_data[:serial]).to eq(123)
|
||||
expect(dsa_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
|
@ -213,21 +226,18 @@ describe SSHData::Encoding do
|
|||
expect(dsa_ca_data[:reserved]).to eq("")
|
||||
|
||||
expect(dsa_ca_data[:signature_key]).to be_a(String)
|
||||
expect(dsa_ca_data[:signed_data]).to be_a(String)
|
||||
expect(dsa_ca_data[:signature]).to be_a(String)
|
||||
end
|
||||
|
||||
it "can decode certs from ECDSA CAs" do
|
||||
expect(ecdsa_ca_data[:type_string]).to eq(SSHData::Certificate::RSA_CERT_TYPE)
|
||||
expect(ecdsa_ca_data[:algo]).to eq(SSHData::Certificate::ALGO_RSA)
|
||||
|
||||
expect(ecdsa_ca_data[:nonce]).to be_a(String)
|
||||
expect(ecdsa_ca_data[:nonce].length).to eq(32)
|
||||
|
||||
expect(ecdsa_ca_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_RSA)
|
||||
expect(ecdsa_ca_data[:key_data][:e]).to be_a(OpenSSL::BN)
|
||||
expect(ecdsa_ca_data[:key_data][:e]).not_to eq(OpenSSL::BN.new(0))
|
||||
|
||||
expect(ecdsa_ca_data[:key_data][:n]).to be_a(OpenSSL::BN)
|
||||
expect(ecdsa_ca_data[:key_data][:n]).not_to eq(OpenSSL::BN.new(0))
|
||||
|
||||
expect(ecdsa_ca_data[:serial]).to eq(123)
|
||||
expect(ecdsa_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
|
@ -240,21 +250,18 @@ describe SSHData::Encoding do
|
|||
expect(ecdsa_ca_data[:reserved]).to eq("")
|
||||
|
||||
expect(ecdsa_ca_data[:signature_key]).to be_a(String)
|
||||
expect(ecdsa_ca_data[:signed_data]).to be_a(String)
|
||||
expect(ecdsa_ca_data[:signature]).to be_a(String)
|
||||
end
|
||||
|
||||
it "can decode certs from ED25519 CAs" do
|
||||
expect(ed25519_ca_data[:type_string]).to eq(SSHData::Certificate::RSA_CERT_TYPE)
|
||||
expect(ed25519_ca_data[:algo]).to eq(SSHData::Certificate::ALGO_RSA)
|
||||
|
||||
expect(ed25519_ca_data[:nonce]).to be_a(String)
|
||||
expect(ed25519_ca_data[:nonce].length).to eq(32)
|
||||
|
||||
expect(ed25519_ca_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_RSA)
|
||||
expect(ed25519_ca_data[:key_data][:e]).to be_a(OpenSSL::BN)
|
||||
expect(ed25519_ca_data[:key_data][:e]).not_to eq(OpenSSL::BN.new(0))
|
||||
|
||||
expect(ed25519_ca_data[:key_data][:n]).to be_a(OpenSSL::BN)
|
||||
expect(ed25519_ca_data[:key_data][:n]).not_to eq(OpenSSL::BN.new(0))
|
||||
|
||||
expect(ed25519_ca_data[:serial]).to eq(123)
|
||||
expect(ed25519_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
|
||||
|
@ -267,7 +274,6 @@ describe SSHData::Encoding do
|
|||
expect(ed25519_ca_data[:reserved]).to eq("")
|
||||
|
||||
expect(ed25519_ca_data[:signature_key]).to be_a(String)
|
||||
expect(ed25519_ca_data[:signed_data]).to be_a(String)
|
||||
expect(ed25519_ca_data[:signature]).to be_a(String)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,6 +3,9 @@ require "ssh_data"
|
|||
REPO_PATH = File.expand_path(File.join(__FILE__, "..", ".."))
|
||||
FIXTURE_PATH = File.expand_path(File.join(REPO_PATH, "spec", "fixtures"))
|
||||
|
||||
def fixture(name)
|
||||
File.read(File.join(FIXTURE_PATH, name))
|
||||
def fixture(name, binary: false)
|
||||
data = File.read(File.join(FIXTURE_PATH, name))
|
||||
return data unless binary
|
||||
_, b64, _ = data.split(" ", 3)
|
||||
Base64.decode64(b64)
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче