Support SK-ED25519 public key parsing.

This commit is contained in:
Kevin Jones 2021-03-01 10:12:18 -05:00
Родитель a44e9de1d0
Коммит 9c646e3c53
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: A521BED5353FDD4E
10 изменённых файлов: 148 добавлений и 3 удалений

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

@ -67,6 +67,12 @@ module SSHData
[:pk, :string]
]
# Fields in a SK-ED25519 public key
SKED25519_KEY_FIELDS = [
[:pk, :string],
[:application, :string]
]
PUBLIC_KEY_ALGO_BY_CERT_ALGO = {
Certificate::ALGO_RSA => PublicKey::ALGO_RSA,
Certificate::ALGO_DSA => PublicKey::ALGO_DSA,
@ -92,6 +98,7 @@ module SSHData
PublicKey::ALGO_ECDSA384 => ECDSA_KEY_FIELDS,
PublicKey::ALGO_ECDSA521 => ECDSA_KEY_FIELDS,
PublicKey::ALGO_ED25519 => ED25519_KEY_FIELDS,
PublicKey::ALGO_SK_ED25519 => SKED25519_KEY_FIELDS,
}
KEY_FIELDS_BY_PRIVATE_KEY_ALGO = {

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

@ -4,4 +4,5 @@ module SSHData
VerifyError = Class.new(Error)
AlgorithmError = Class.new(Error)
DecryptError = Class.new(Error)
UnsupportedError = Class.new(Error)
end

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

@ -7,6 +7,8 @@ module SSHData
ALGO_ECDSA384 = "ecdsa-sha2-nistp384"
ALGO_ECDSA521 = "ecdsa-sha2-nistp521"
ALGO_ED25519 = "ssh-ed25519"
ALGO_SK_ED25519 = "sk-ssh-ed25519@openssh.com"
ALGO_SK_ECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com"
# RSA SHA2 *signature* algorithms used with ALGO_RSA keys.
# https://tools.ietf.org/html/draft-rsa-dsa-sha2-256-02
@ -15,7 +17,7 @@ module SSHData
ALGOS = [
ALGO_RSA, ALGO_DSA, ALGO_ECDSA256, ALGO_ECDSA384, ALGO_ECDSA521,
ALGO_ED25519
ALGO_ED25519, ALGO_SK_ECDSA256, ALGO_SK_ED25519
]
# Parse an OpenSSH public key in authorized_keys format (see sshd(8) manual
@ -64,6 +66,8 @@ module SSHData
ECDSA.new(**data)
when ALGO_ED25519
ED25519.new(**data)
when ALGO_SK_ED25519
SKED25519.new(**data)
else
raise DecodeError, "unkown algo: #{data[:algo].inspect}"
end
@ -76,3 +80,4 @@ require "ssh_data/public_key/rsa"
require "ssh_data/public_key/dsa"
require "ssh_data/public_key/ecdsa"
require "ssh_data/public_key/ed25519"
require "ssh_data/public_key/sked25519"

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

@ -16,8 +16,12 @@ module SSHData
raise AlgorithmError, "the ed25519 gem is not loaded" unless enabled?
end
def self.algorithm_identifier
ALGO_ED25519
end
def initialize(algo:, pk:)
unless algo == ALGO_ED25519
unless algo == self.class.algorithm_identifier
raise DecodeError, "bad algorithm: #{algo.inspect}"
end
@ -40,7 +44,7 @@ module SSHData
self.class.ed25519_gem_required!
sig_algo, raw_sig, _ = Encoding.decode_signature(signature)
if sig_algo != ALGO_ED25519
if sig_algo != self.class.algorithm_identifier
raise DecodeError, "bad signature algorithm: #{sig_algo.inspect}"
end

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

@ -0,0 +1,32 @@
module SSHData
module PublicKey
class SKED25519 < ED25519
attr_reader :application
def initialize(algo:, pk:, application:)
@application = application
super(algo: algo, pk: pk)
end
def self.algorithm_identifier
ALGO_SK_ED25519
end
def rfc4253
Encoding.encode_fields(
[:string, algo],
[:string, pk],
[:string, application],
)
end
def verify(signed_data, signature)
raise UnsupportedError, "SK-Ed25519 verification is not supported."
end
def ==(other)
super && other.application == application
end
end
end
end

17
spec/fixtures/gen.sh поставляемый
Просмотреть файл

@ -1,5 +1,13 @@
#!/bin/bash
generate_security_keys=0
read -p "Generated security key-backed keys (Requires key and user interaction)? [yN] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
generate_security_keys=1
fi
ssh-keygen -trsa -N "passw0rd" -f ./encrypted_rsa
ssh-keygen -trsa -N "" -f ./rsa_ca
@ -34,6 +42,15 @@ ssh-keygen -s rsa_ca -z 123 -n p1,p2 -O clear -I my-ident -O critical:foo=bar -O
ssh-keygen -ted25519 -N "" -f ./ed25519_leaf_for_rsa_ca
ssh-keygen -s rsa_ca -z 123 -n p1,p2 -O clear -I my-ident -O critical:foo=bar -O extension:baz=qwer -O permit-X11-forwarding ed25519_leaf_for_rsa_ca.pub
if [[ $generate_security_keys -eq 1 ]]
then
ssh-keygen -t ed25519-sk -N "" -f ./sked25519_leaf_for_rsa_ca
ssh-keygen -s rsa_ca -z 123 -n p1,p2 -O clear -I my-ident -O critical:foo=bar -O extension:baz=qwer -O permit-X11-forwarding sked25519_leaf_for_rsa_ca.pub
ssh-keygen -trsa -N "" -f ./rsa_leaf_for_sked25519_ca
ssh-keygen -s sked25519_ca -z 123 -n p1,p2 -O clear -I my-ident -O critical:foo=bar -O extension:baz=qwer -O permit-X11-forwarding rsa_leaf_for_sked25519_ca.pub
fi
# critical opts
ssh-keygen -trsa -N "" -f ./valid_force_command
ssh-keygen -s rsa_ca -z 123 -O clear -I my-ident -O force-command=asdf valid_force_command.pub

10
spec/fixtures/sked25519_leaf_for_rsa_ca поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAASgAAABpzay1zc2
gtZWQyNTUxOUBvcGVuc3NoLmNvbQAAACA3xPtT9yVKAyJr3fhB105GFoG3NInJdsfe91aN
GHBqhgAAAARzc2g6AAAA+NhG/FXYRvxVAAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY2
9tAAAAIDfE+1P3JUoDImvd+EHXTkYWgbc0icl2x973Vo0YcGqGAAAABHNzaDoBAAAAgPM8
JGbyftt6rqAO8cPWw0rXW394+heb5h07rtW/bkxM7SpTYbuKS/Z2ETwv9iX6u3NIqxQDlj
71iWawf/VFsBYGT4GBf2dVsmH5Bd2yAl7kuljFzqkWPbWlENwScPjlfK2ZfgtcWMJz2wU1
CLUNNhqorCTvRUZbsb7Dw0aOh9gjAAAAAAAAABN2Y3Nqb25lc0BLZXZpbnMtTUJQAQIDBA
UG
-----END OPENSSH PRIVATE KEY-----

1
spec/fixtures/sked25519_leaf_for_rsa_ca-cert.pub поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
sk-ssh-ed25519-cert-v01@openssh.com AAAAI3NrLXNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIA9W0s0HknrDboFqbQQ8bqPF78qPEyB5fAGrTRufG/dsAAAAIDfE+1P3JUoDImvd+EHXTkYWgbc0icl2x973Vo0YcGqGAAAABHNzaDoAAAAAAAAAewAAAAEAAAAIbXktaWRlbnQAAAAMAAAAAnAxAAAAAnAyAAAAAAAAAAD//////////wAAABIAAAADZm9vAAAABwAAAANiYXIAAAAwAAAAA2JhegAAAAgAAAAEcXdlcgAAABVwZXJtaXQtWDExLWZvcndhcmRpbmcAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAM8HbRJLhHLRqFUkYh/lphFTzU/C1SIMuPYKFScx9i0Jh6a5whGOR9NSq4fN49t5xRpbH80dfQYdG/tzg075NjH9Q8MLp7ZmZGENHL+lzmq3JG7t+oFKyuEEC8B2/XcXkvMyVG/6hlcgQF40zxl3c0iBqnO0x3GQEX4uw2SxuKyD2LFMlw5veJJlXNA/i+ZAfXC+I7T9YViP6tLdOuhPqA/FS5p/NOFxcW3EtYBcAz5/1ss/1wkdbcAAZ+iHKVEpNxWzFLvHtiWOsrQTB8CHgq+NMCeTmClt0sdo/B5Gs3rZ5h8hFnEK5t150NW5nc9WVSZBYCGe0dSQicH6aWQ/8e8AAAEUAAAADHJzYS1zaGEyLTUxMgAAAQCoT7uBIJWX3Hs/ofiCB/p/XaVGbLq3unStZ7h+Goy6VhT0GcRl/CkJER0P5wbrCvf2KQQL9u6TgcXjs+JQzMk/yEdXUfNsIisMFh/KgF7XB08Rs/Gkralggz2aCUOCnCS4h323fwNpsbSf5SMfqWnwx8qGe7wgOkhxvgYZGQ8P10+46JpZMjRkVAevJU/toWL5VdvtO99OUtDZ/RJ+bx4j4/zh4xcuCCiq2e/iE7HFZjuiVOSYTQbNIb/KQT1M+8aJQyMQz/lble2ZOXG0Q3VrlWsZzgNQUZtqjFxIf2p8ghjUir4nCbCZdihJIl5/Uc0kVGdulGrFJt1OHKWPJijs vcsjones@Kevins-MBP

1
spec/fixtures/sked25519_leaf_for_rsa_ca.pub поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDfE+1P3JUoDImvd+EHXTkYWgbc0icl2x973Vo0YcGqGAAAABHNzaDo= vcsjones@Kevins-MBP

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

@ -0,0 +1,67 @@
require_relative "../spec_helper"
describe SSHData::PublicKey::SKED25519 do
let(:signing_key) { Ed25519::SigningKey.generate }
let(:verify_key) { signing_key.verify_key }
let(:msg) { "hello, world!" }
let(:raw_sig) { signing_key.sign(msg) }
let(:sig) { SSHData::Encoding.encode_signature(SSHData::PublicKey::ALGO_SK_ED25519, raw_sig) }
let(:application) { "ssh:" }
let(:openssh_key) { SSHData::PublicKey.parse_openssh(fixture("sked25519_leaf_for_rsa_ca.pub")) }
subject do
described_class.new(
algo: SSHData::PublicKey::ALGO_SK_ED25519,
pk: verify_key.to_bytes,
application: application
)
end
it "is equal to keys with the same params" do
expect(subject).to eq(described_class.new(
algo: SSHData::PublicKey::ALGO_SK_ED25519,
pk: verify_key.to_bytes,
application: application
))
end
it "isnt equal to keys with different params" do
expect(subject).not_to eq(described_class.new(
algo: SSHData::PublicKey::ALGO_SK_ED25519,
pk: verify_key.to_bytes.reverse,
application: application
))
expect(subject).not_to eq(described_class.new(
algo: SSHData::PublicKey::ALGO_SK_ED25519,
pk: verify_key.to_bytes,
application: "something else"
))
end
it "has an algo" do
expect(subject.algo).to eq(SSHData::PublicKey::ALGO_SK_ED25519)
end
it "has parameters" do
expect(subject.pk).to eq(verify_key.to_bytes)
end
it "has application" do
expect(subject.application).to eq(application)
end
it "has an Ed25519 representation" do
expect(subject.ed25519_key).to be_a(Ed25519::VerifyKey)
expect(subject.ed25519_key.to_bytes).to eq(verify_key.to_bytes)
end
it "can not verify signatures" do
expect { subject.verify(msg, sig) }.to raise_error(SSHData::UnsupportedError)
end
it "can be rencoded" do
expect(openssh_key.rfc4253).to eq(fixture("sked25519_leaf_for_rsa_ca.pub", binary: true))
end
end