This commit is contained in:
Ben Toews 2019-01-29 16:01:07 -07:00
Родитель 2cd906306b
Коммит 7f2268a7c5
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E9C423BE17EFEE70
3 изменённых файлов: 576 добавлений и 325 удалений

Просмотреть файл

@ -111,7 +111,11 @@ module SSHData
raise DecodeError, "bad PEM footer"
end
Base64.strict_decode64(lines.join)
begin
Base64.strict_decode64(lines.join)
rescue ArgumentError
raise DecodeError, "bad PEM data"
end
end
# Decode an OpenSSH private key.
@ -145,13 +149,13 @@ module SSHData
privs_read = 0
checkint1, read = decode_uint32(privs, privs_read)
data[:checkint1], read = decode_uint32(privs, privs_read)
privs_read += read
checkint2, read = decode_uint32(privs, privs_read)
data[:checkint2], read = decode_uint32(privs, privs_read)
privs_read += read
unless checkint1 == checkint2
unless data[:checkint1] == data[:checkint2]
raise DecryptError, "bad private key checksum"
end
@ -173,9 +177,9 @@ module SSHData
end
# padding at end is bytes 1, 2, 3, 4, etc...
padding = privs.byteslice(privs_read..-1)
unless padding.bytes.each_with_index.all? { |b, i| b == (i + 1) % 255 }
raise DecodeError, "bad padding: #{padding.inspect}"
data[:padding] = privs.byteslice(privs_read..-1)
unless data[:padding].bytes.each_with_index.all? { |b, i| b == (i + 1) % 255 }
raise DecodeError, "bad padding: #{data[:padding].inspect}"
end
[data, total_read]

Просмотреть файл

@ -2,344 +2,587 @@ require "securerandom"
require_relative "./spec_helper"
describe SSHData::Encoding do
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 }
describe "#decode_pem" do
let(:type) { "FOO BAR" }
let(:head) { "-----BEGIN #{type}-----" }
let(:foot) { "-----END #{type}-----" }
let(:data) { "foobarbaz" }
let(:b64) { Base64.strict_encode64(data) }
let(:pem) { [head, b64, foot].join("\n") }
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 }
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 "raises on unknown public key algorithms" do
raw = fixture("rsa_leaf_for_rsa_ca.pub", binary: true)
# first four bytes are lenth for algo field. flip bits in first byte of algo
raw[5] = (raw[5].ord ^ 0xff).chr
expect {
described_class.decode_public_key(raw)
}.to raise_error(SSHData::AlgorithmError)
end
it "raises on unknown certificate algorithms" do
raw = fixture("rsa_leaf_for_rsa_ca-cert.pub", binary: true)
# first four bytes are lenth for algo field. flip bits in first byte of algo
raw[5] = (raw[5].ord ^ 0xff).chr
expect {
described_class.decode_certificate(raw)
}.to raise_error(SSHData::AlgorithmError)
end
it "can decode options" do
opts = {"k1" => "v1", "k2" => "v2"}
encoded = opts.reduce("") do |cum, (k, v)|
cum + [
described_class.encode_string(k),
described_class.encode_string(described_class.encode_string(v))
].join
it "works" do
expect(described_class.decode_pem(pem, type)).to eq(data)
end
decoded, read = described_class.decode_options(encoded)
expect(decoded).to eq(opts)
expect(read).to eq(encoded.bytesize)
describe "bad header" do
let(:head) { "----BEGIN #{type}-----" }
decoded, read = described_class.decode_options("")
expect(decoded).to eq({})
expect(read).to eq(0)
it "blows up" do
expect{ described_class.decode_pem(pem, type) }.to raise_error(SSHData::DecodeError)
end
end
describe "bad header type" do
let(:head) { "-----BEGIN SOMETHING ELSE-----" }
it "blows up" do
expect{ described_class.decode_pem(pem, type) }.to raise_error(SSHData::DecodeError)
end
end
describe "bad footer" do
let(:foot) { "-----END #{type}----" }
it "blows up" do
expect{ described_class.decode_pem(pem, type) }.to raise_error(SSHData::DecodeError)
end
end
describe "bad footer type" do
let(:foot) { "-----END SOMETHING ELSE-----" }
it "blows up" do
expect{ described_class.decode_pem(pem, type) }.to raise_error(SSHData::DecodeError)
end
end
describe "bad b64" do
let(:b64) { "foo" }
it "blows up" do
expect{ described_class.decode_pem(pem, type) }.to raise_error(SSHData::DecodeError)
end
end
end
it "can decode a series of strings" do
strs = %w(one two three)
encoded = strs.map { |s| described_class.encode_string(s) }.join
decoded, read = described_class.decode_strings(encoded)
expect(decoded).to eq(strs)
expect(read).to eq(encoded.bytesize)
describe "#decode_openssh_private_key" do
let(:rsa_data) { described_class.decode_openssh_private_key(fixture("rsa_leaf_for_rsa_ca", binary: true, pem: true)).first }
let(:dsa_data) { described_class.decode_openssh_private_key(fixture("dsa_leaf_for_rsa_ca", binary: true, pem: true)).first }
let(:ecdsa_data) { described_class.decode_openssh_private_key(fixture("ecdsa_leaf_for_rsa_ca", binary: true, pem: true)).first }
let(:ed25519_data) { described_class.decode_openssh_private_key(fixture("ed25519_leaf_for_rsa_ca", binary: true, pem: true)).first }
decoded, read = described_class.decode_strings("")
expect(decoded).to eq([])
expect(read).to eq(0)
it "can decode rsa" do
expect { rsa_data }.not_to raise_error
expect(rsa_data[:ciphername]).to eq("none")
expect(rsa_data[:kdfname]).to eq("none")
expect(rsa_data[:kdfoptions]).to eq("")
expect(rsa_data[:nkeys]).to eq(1)
expect(rsa_data[:public_keys]).to be_a(Array)
expect(rsa_data[:public_keys].length).to eq(1)
expect {
SSHData::PublicKey.parse_raw(rsa_data[:public_keys].first)
}.not_to raise_error
expect(rsa_data[:checkint1]).to be_a(Integer)
expect(rsa_data[:checkint2]).to be_a(Integer)
expect(rsa_data[:checkint1]).to eq(rsa_data[:checkint2])
expect(rsa_data[:private_keys]).to be_a(Array)
expect(rsa_data[:private_keys].length).to eq(1)
expect(rsa_data[:padding]).to eq("\x01\x02\x03\x04")
end
it "can decode dsa" do
expect { dsa_data }.not_to raise_error
expect(dsa_data[:ciphername]).to eq("none")
expect(dsa_data[:kdfname]).to eq("none")
expect(dsa_data[:kdfoptions]).to eq("")
expect(dsa_data[:nkeys]).to eq(1)
expect(dsa_data[:public_keys]).to be_a(Array)
expect(dsa_data[:public_keys].length).to eq(1)
expect {
SSHData::PublicKey.parse_raw(dsa_data[:public_keys].first)
}.not_to raise_error
expect(dsa_data[:checkint1]).to be_a(Integer)
expect(dsa_data[:checkint2]).to be_a(Integer)
expect(dsa_data[:checkint1]).to eq(dsa_data[:checkint2])
expect(dsa_data[:private_keys]).to be_a(Array)
expect(dsa_data[:private_keys].length).to eq(1)
expect(dsa_data[:padding]).to eq("\x01\x02\x03\x04")
end
it "can decode ecdsa" do
expect { ecdsa_data }.not_to raise_error
expect(ecdsa_data[:ciphername]).to eq("none")
expect(ecdsa_data[:kdfname]).to eq("none")
expect(ecdsa_data[:kdfoptions]).to eq("")
expect(ecdsa_data[:nkeys]).to eq(1)
expect(ecdsa_data[:public_keys]).to be_a(Array)
expect(ecdsa_data[:public_keys].length).to eq(1)
expect {
SSHData::PublicKey.parse_raw(ecdsa_data[:public_keys].first)
}.not_to raise_error
expect(ecdsa_data[:checkint1]).to be_a(Integer)
expect(ecdsa_data[:checkint2]).to be_a(Integer)
expect(ecdsa_data[:checkint1]).to eq(ecdsa_data[:checkint2])
expect(ecdsa_data[:private_keys]).to be_a(Array)
expect(ecdsa_data[:private_keys].length).to eq(1)
expect(ecdsa_data[:padding]).to eq("\x01")
end
it "can decode ed25519" do
expect { ed25519_data }.not_to raise_error
expect(ed25519_data[:ciphername]).to eq("none")
expect(ed25519_data[:kdfname]).to eq("none")
expect(ed25519_data[:kdfoptions]).to eq("")
expect(ed25519_data[:nkeys]).to eq(1)
expect(ed25519_data[:public_keys]).to be_a(Array)
expect(ed25519_data[:public_keys].length).to eq(1)
expect {
SSHData::PublicKey.parse_raw(ed25519_data[:public_keys].first)
}.not_to raise_error
expect(ed25519_data[:checkint1]).to be_a(Integer)
expect(ed25519_data[:checkint2]).to be_a(Integer)
expect(ed25519_data[:checkint1]).to eq(ed25519_data[:checkint2])
expect(ed25519_data[:private_keys]).to be_a(Array)
expect(ed25519_data[:private_keys].length).to eq(1)
expect(ed25519_data[:padding]).to eq("\x01\x02\x03\x04\x05\x06\07")
end
it "raises on bad magic bytes" do
raw = fixture("rsa_leaf_for_rsa_ca", binary: true, pem: true)
# magic bytes come first
offset = 0
raw[offset] = (raw[offset].ord ^ 0xff).chr
expect {
described_class.decode_openssh_private_key(raw)
}.to raise_error(SSHData::DecodeError)
end
it "raises on unsupported encryption algos" do
raw = fixture("rsa_leaf_for_rsa_ca", binary: true, pem: true)
# ciphername comes right after TLV after magic bytes
offset = described_class::OPENSSH_PRIVATE_KEY_MAGIC.bytesize + 4
raw[offset] = (raw[offset].ord ^ 0xff).chr
expect {
described_class.decode_openssh_private_key(raw)
}.to raise_error(SSHData::DecryptError)
end
it "raises on unsupported kdf algos" do
raw = fixture("rsa_leaf_for_rsa_ca", binary: true, pem: true)
# ciphername comes right after TLV after magic bytes
offset = described_class::OPENSSH_PRIVATE_KEY_MAGIC.bytesize + 4
# kdfname comes right after TLV of ciphername "none"
offset += 8
raw[offset] = (raw[offset].ord ^ 0xff).chr
expect {
described_class.decode_openssh_private_key(raw)
}.to raise_error(SSHData::DecryptError)
end
it "raises on bad checkint" do
raw = fixture("rsa_leaf_for_rsa_ca", binary: true, pem: true)
check = [rsa_data[:checkint1]].pack("L>")
raw2 = raw.sub(check, "asdf")
expect(raw).not_to eq(raw2)
expect {
described_class.decode_openssh_private_key(raw2)
}.to raise_error(SSHData::DecryptError)
end
it "raises on bad padding" do
raw = fixture("rsa_leaf_for_rsa_ca", binary: true, pem: true)
raw[-1] = (raw[-1].ord ^ 0xff).chr
expect {
described_class.decode_openssh_private_key(raw)
}.to raise_error(SSHData::DecodeError)
end
end
it "can round trip a string" do
s1 = "foobar"
s2, read = described_class.decode_string(described_class.encode_string(s1))
expect(s2).to eq(s1)
expect(read).to eq(s1.length + 4)
describe("#decode_public_key") do
let(:rsa_data) { described_class.decode_public_key(fixture("rsa_leaf_for_rsa_ca.pub", binary: true)).first }
let(:dsa_data) { described_class.decode_public_key(fixture("dsa_leaf_for_rsa_ca.pub", binary: true)).first }
let(:ecdsa_data) { described_class.decode_public_key(fixture("ecdsa_leaf_for_rsa_ca.pub", binary: true)).first }
let(:ed25519_data) { described_class.decode_public_key(fixture("ed25519_leaf_for_rsa_ca.pub", binary: true)).first }
it "raises on unknown public key algorithms" do
raw = fixture("rsa_leaf_for_rsa_ca.pub", binary: true)
# first four bytes are lenth for algo field. flip bits in first byte of algo
raw[5] = (raw[5].ord ^ 0xff).chr
expect {
described_class.decode_public_key(raw)
}.to raise_error(SSHData::AlgorithmError)
end
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_data)
end
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.decode_string(raw)
data, _ = described_class.decode_public_key(raw, algo, offset)
expect(data).to eq(rsa_data)
end
it "can decode an RSA public key" do
expect(rsa_data[:algo]).to eq(SSHData::PublicKey::ALGO_RSA)
expect(rsa_data[:e]).to be_a(OpenSSL::BN)
expect(rsa_data[:n]).to be_a(OpenSSL::BN)
end
it "can decode an DSA public key" do
expect(dsa_data[:algo]).to eq(SSHData::PublicKey::ALGO_DSA)
expect(dsa_data[:p]).to be_a(OpenSSL::BN)
expect(dsa_data[:q]).to be_a(OpenSSL::BN)
expect(dsa_data[:g]).to be_a(OpenSSL::BN)
expect(dsa_data[:y]).to be_a(OpenSSL::BN)
end
it "can decode an ECDSA public key" do
expect(ecdsa_data[:algo]).to eq(SSHData::PublicKey::ALGO_ECDSA256)
expect(ecdsa_data[:curve]).to eq("nistp256")
expect(ecdsa_data[:public_key]).to be_a(String)
end
it "can decode an ED25519 public key" do
expect(ed25519_data[:algo]).to eq(SSHData::PublicKey::ALGO_ED25519)
expect(ed25519_data[:pk]).to be_a(String)
end
end
it "can round trip an mpint" do
i1 = OpenSSL::BN.new(SecureRandom.bytes((rand * 100).to_i), 2)
i2, read = described_class.decode_mpint(described_class.encode_mpint(i1))
expect(i2).to eq(i1)
describe("#decode_certificate") do
let(:rsa_data) { described_class.decode_certificate(fixture("rsa_leaf_for_rsa_ca-cert.pub", binary: true)).first }
let(:dsa_data) { described_class.decode_certificate(fixture("dsa_leaf_for_rsa_ca-cert.pub", binary: true)).first }
let(:ecdsa_data) { described_class.decode_certificate(fixture("ecdsa_leaf_for_rsa_ca-cert.pub", binary: true)).first }
let(:ed25519_data) { described_class.decode_certificate(fixture("ed25519_leaf_for_rsa_ca-cert.pub", binary: true)).first }
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 "raises on unknown certificate algorithms" do
raw = fixture("rsa_leaf_for_rsa_ca-cert.pub", binary: true)
# first four bytes are lenth for algo field. flip bits in first byte of algo
raw[5] = (raw[5].ord ^ 0xff).chr
expect {
described_class.decode_certificate(raw)
}.to raise_error(SSHData::AlgorithmError)
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_data)
end
it "can decode RSA certificates" do
expect(rsa_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_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_RSA)
expect(rsa_data[:key_data][:e]).to be_a(OpenSSL::BN)
expect(rsa_data[:key_data][:n]).to be_a(OpenSSL::BN)
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\x02p1\x00\x00\x00\x02p2")
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\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(rsa_data[:reserved]).to eq("")
expect(rsa_data[:signature_key]).to be_a(String)
expect(rsa_data[:signature_key].bytesize).to eq(279)
expect(rsa_data[:signature]).to be_a(String)
expect(rsa_data[:signature].bytesize).to eq(271)
end
it "can decode DSA certificates" do
expect(dsa_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_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_DSA)
expect(dsa_data[:key_data][:p]).to be_a(OpenSSL::BN)
expect(dsa_data[:key_data][:q]).to be_a(OpenSSL::BN)
expect(dsa_data[:key_data][:g]).to be_a(OpenSSL::BN)
expect(dsa_data[:key_data][:y]).to be_a(OpenSSL::BN)
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\x02p1\x00\x00\x00\x02p2")
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\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\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[:signature]).to be_a(String)
expect(dsa_data[:signature].bytesize).to eq(271)
end
it "can decode ECDSA certificates" do
expect(ecdsa_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_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_ECDSA256)
expect(ecdsa_data[:key_data][:curve]).to eq("nistp256")
expect(ecdsa_data[:key_data][:public_key]).to be_a(String)
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\x02p1\x00\x00\x00\x02p2")
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\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(ecdsa_data[:reserved]).to eq("")
expect(ecdsa_data[:signature_key]).to be_a(String)
expect(ecdsa_data[:signature_key].bytesize).to eq(279)
expect(ecdsa_data[:signature]).to be_a(String)
expect(ecdsa_data[:signature].bytesize).to eq(271)
end
it "can decode ED25519 certificates" do
expect(ed25519_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_data[:key_data][:algo]).to eq(SSHData::PublicKey::ALGO_ED25519)
expect(ed25519_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\x02p1\x00\x00\x00\x02p2")
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\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(ed25519_data[:reserved]).to eq("")
expect(ed25519_data[:signature_key]).to be_a(String)
expect(ed25519_data[:signature_key].bytesize).to eq(279)
expect(ed25519_data[:signature]).to be_a(String)
expect(ed25519_data[:signature].bytesize).to eq(271)
end
it "can decode certs from RSA CAs" do
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][:n]).to be_a(OpenSSL::BN)
expect(rsa_ca_data[:serial]).to eq(123)
expect(rsa_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
expect(rsa_ca_data[:key_id]).to eq("my-ident")
expect(rsa_ca_data[:valid_principals]).to eq("\x00\x00\x00\x02p1\x00\x00\x00\x02p2")
expect(rsa_ca_data[:valid_after]).to eq(0)
expect(rsa_ca_data[:valid_before]).to eq((2**64)-1)
expect(rsa_ca_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
expect(rsa_ca_data[:extensions]).to eq("\x00\x00\x00\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(rsa_ca_data[:reserved]).to eq("")
expect(rsa_ca_data[:signature_key]).to be_a(String)
expect(rsa_ca_data[:signature_key].bytesize).to eq(279)
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[: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][:n]).to be_a(OpenSSL::BN)
expect(dsa_ca_data[:serial]).to eq(123)
expect(dsa_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
expect(dsa_ca_data[:key_id]).to eq("my-ident")
expect(dsa_ca_data[:valid_principals]).to eq("\x00\x00\x00\x02p1\x00\x00\x00\x02p2")
expect(dsa_ca_data[:valid_after]).to eq(0)
expect(dsa_ca_data[:valid_before]).to eq((2**64)-1)
expect(dsa_ca_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
expect(dsa_ca_data[:extensions]).to eq("\x00\x00\x00\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(dsa_ca_data[:reserved]).to eq("")
expect(dsa_ca_data[:signature_key]).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[: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][:n]).to be_a(OpenSSL::BN)
expect(ecdsa_ca_data[:serial]).to eq(123)
expect(ecdsa_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
expect(ecdsa_ca_data[:key_id]).to eq("my-ident")
expect(ecdsa_ca_data[:valid_principals]).to eq("\x00\x00\x00\x02p1\x00\x00\x00\x02p2")
expect(ecdsa_ca_data[:valid_after]).to eq(0)
expect(ecdsa_ca_data[:valid_before]).to eq((2**64)-1)
expect(ecdsa_ca_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
expect(ecdsa_ca_data[:extensions]).to eq("\x00\x00\x00\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(ecdsa_ca_data[:reserved]).to eq("")
expect(ecdsa_ca_data[:signature_key]).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[: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][:n]).to be_a(OpenSSL::BN)
expect(ed25519_ca_data[:serial]).to eq(123)
expect(ed25519_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
expect(ed25519_ca_data[:key_id]).to eq("my-ident")
expect(ed25519_ca_data[:valid_principals]).to eq("\x00\x00\x00\x02p1\x00\x00\x00\x02p2")
expect(ed25519_ca_data[:valid_after]).to eq(0)
expect(ed25519_ca_data[:valid_before]).to eq((2**64)-1)
expect(ed25519_ca_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
expect(ed25519_ca_data[:extensions]).to eq("\x00\x00\x00\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(ed25519_ca_data[:reserved]).to eq("")
expect(ed25519_ca_data[:signature_key]).to be_a(String)
expect(ed25519_ca_data[:signature]).to be_a(String)
end
end
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
describe("#decode_options") do
it "can decode options" do
opts = {"k1" => "v1", "k2" => "v2"}
encoded = opts.reduce("") do |cum, (k, v)|
cum + [
described_class.encode_string(k),
described_class.encode_string(described_class.encode_string(v))
].join
end
data, _ = described_class.decode_public_key(with_prefix, nil, prefix.bytesize).first
decoded, read = described_class.decode_options(encoded)
expect(decoded).to eq(opts)
expect(read).to eq(encoded.bytesize)
expect(data).to eq(rsa_key_data)
decoded, read = described_class.decode_options("")
expect(decoded).to eq({})
expect(read).to eq(0)
end
end
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.decode_string(raw)
data, _ = described_class.decode_public_key(raw, algo, offset)
describe("#decode_strings") do
it "can decode a series of strings" do
strs = %w(one two three)
encoded = strs.map { |s| described_class.encode_string(s) }.join
decoded, read = described_class.decode_strings(encoded)
expect(decoded).to eq(strs)
expect(read).to eq(encoded.bytesize)
expect(data).to eq(rsa_key_data)
decoded, read = described_class.decode_strings("")
expect(decoded).to eq([])
expect(read).to eq(0)
end
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)
describe("#decode_n_strings") do
it "can decode a series of strings" do
strs = %w(one two three)
encoded = strs.map { |s| described_class.encode_string(s) }.join
decoded, read = described_class.decode_n_strings(encoded, 2)
expect(decoded).to eq(strs[0..1])
expect(read).to eq(encoded.bytesize - 9)
decoded, read = described_class.decode_n_strings("", 0)
expect(decoded).to eq([])
expect(read).to eq(0)
end
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)
describe("#decode_string") do
it "can round trip" do
s1 = "foobar"
s2, read = described_class.decode_string(described_class.encode_string(s1))
expect(s2).to eq(s1)
expect(read).to eq(s1.length + 4)
end
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_cert_data[:algo]).to eq(SSHData::Certificate::ALGO_RSA)
expect(rsa_cert_data[:nonce]).to be_a(String)
expect(rsa_cert_data[:nonce].length).to eq(32)
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_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\x02p1\x00\x00\x00\x02p2")
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\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(rsa_cert_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_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_cert_data[:algo]).to eq(SSHData::Certificate::ALGO_DSA)
expect(dsa_cert_data[:nonce]).to be_a(String)
expect(dsa_cert_data[:nonce].length).to eq(32)
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_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\x02p1\x00\x00\x00\x02p2")
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\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(dsa_cert_data[:reserved]).to eq("")
expect(dsa_cert_data[:signature_key]).to be_a(String)
expect(dsa_cert_data[:signature_key].bytesize).to eq(279)
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_cert_data[:algo]).to eq(SSHData::Certificate::ALGO_ECDSA256)
expect(ecdsa_cert_data[:nonce]).to be_a(String)
expect(ecdsa_cert_data[:nonce].length).to eq(32)
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_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\x02p1\x00\x00\x00\x02p2")
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\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(ecdsa_cert_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_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_cert_data[:algo]).to eq(SSHData::Certificate::ALGO_ED25519)
expect(ed25519_cert_data[:nonce]).to be_a(String)
expect(ed25519_cert_data[:nonce].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_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\x02p1\x00\x00\x00\x02p2")
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\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(ed25519_cert_data[:reserved]).to eq("")
expect(ed25519_cert_data[:signature_key]).to be_a(String)
expect(ed25519_cert_data[:signature_key].bytesize).to eq(279)
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[: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][:n]).to be_a(OpenSSL::BN)
expect(rsa_ca_data[:serial]).to eq(123)
expect(rsa_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
expect(rsa_ca_data[:key_id]).to eq("my-ident")
expect(rsa_ca_data[:valid_principals]).to eq("\x00\x00\x00\x02p1\x00\x00\x00\x02p2")
expect(rsa_ca_data[:valid_after]).to eq(0)
expect(rsa_ca_data[:valid_before]).to eq((2**64)-1)
expect(rsa_ca_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
expect(rsa_ca_data[:extensions]).to eq("\x00\x00\x00\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(rsa_ca_data[:reserved]).to eq("")
expect(rsa_ca_data[:signature_key]).to be_a(String)
expect(rsa_ca_data[:signature_key].bytesize).to eq(279)
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[: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][:n]).to be_a(OpenSSL::BN)
expect(dsa_ca_data[:serial]).to eq(123)
expect(dsa_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
expect(dsa_ca_data[:key_id]).to eq("my-ident")
expect(dsa_ca_data[:valid_principals]).to eq("\x00\x00\x00\x02p1\x00\x00\x00\x02p2")
expect(dsa_ca_data[:valid_after]).to eq(0)
expect(dsa_ca_data[:valid_before]).to eq((2**64)-1)
expect(dsa_ca_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
expect(dsa_ca_data[:extensions]).to eq("\x00\x00\x00\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(dsa_ca_data[:reserved]).to eq("")
expect(dsa_ca_data[:signature_key]).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[: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][:n]).to be_a(OpenSSL::BN)
expect(ecdsa_ca_data[:serial]).to eq(123)
expect(ecdsa_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
expect(ecdsa_ca_data[:key_id]).to eq("my-ident")
expect(ecdsa_ca_data[:valid_principals]).to eq("\x00\x00\x00\x02p1\x00\x00\x00\x02p2")
expect(ecdsa_ca_data[:valid_after]).to eq(0)
expect(ecdsa_ca_data[:valid_before]).to eq((2**64)-1)
expect(ecdsa_ca_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
expect(ecdsa_ca_data[:extensions]).to eq("\x00\x00\x00\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(ecdsa_ca_data[:reserved]).to eq("")
expect(ecdsa_ca_data[:signature_key]).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[: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][:n]).to be_a(OpenSSL::BN)
expect(ed25519_ca_data[:serial]).to eq(123)
expect(ed25519_ca_data[:type]).to eq(SSHData::Certificate::TYPE_USER)
expect(ed25519_ca_data[:key_id]).to eq("my-ident")
expect(ed25519_ca_data[:valid_principals]).to eq("\x00\x00\x00\x02p1\x00\x00\x00\x02p2")
expect(ed25519_ca_data[:valid_after]).to eq(0)
expect(ed25519_ca_data[:valid_before]).to eq((2**64)-1)
expect(ed25519_ca_data[:critical_options]).to eq("\x00\x00\x00\x03foo\x00\x00\x00\x07\x00\x00\x00\x03bar")
expect(ed25519_ca_data[:extensions]).to eq("\x00\x00\x00\x15permit-X11-forwarding\x00\x00\x00\x00\x00\x00\x00\x03baz\x00\x00\x00\b\x00\x00\x00\x04qwer")
expect(ed25519_ca_data[:reserved]).to eq("")
expect(ed25519_ca_data[:signature_key]).to be_a(String)
expect(ed25519_ca_data[:signature]).to be_a(String)
describe("#decode_mpint") do
it "can round trip" do
i1 = OpenSSL::BN.new(SecureRandom.bytes((rand * 100).to_i), 2)
i2, read = described_class.decode_mpint(described_class.encode_mpint(i1))
expect(i2).to eq(i1)
end
end
end

Просмотреть файл

@ -4,11 +4,15 @@ require "ed25519"
REPO_PATH = File.expand_path(File.join(__FILE__, "..", ".."))
FIXTURE_PATH = File.expand_path(File.join(REPO_PATH, "spec", "fixtures"))
def fixture(name, binary: false)
def fixture(name, binary: false, pem: false)
data = File.read(File.join(FIXTURE_PATH, name))
return data unless binary
_, b64, _ = data.split(" ", 3)
Base64.decode64(b64)
if pem
SSHData::Encoding.decode_pem(data, "OPENSSH PRIVATE KEY")
else
SSHData.key_parts(data)[1]
end
end
def ssh_keygen_fingerprint(name, algo)