This commit is contained in:
Kevin Jones 2021-12-19 11:43:30 -05:00
Родитель b4b7cb649a
Коммит c16b90ac63
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: A521BED5353FDD4E
5 изменённых файлов: 73 добавлений и 48 удалений

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

@ -20,6 +20,14 @@ module SSHData
ALGO_ED25519, ALGO_SKECDSA256, ALGO_SKED25519
]
DEFAULT_SK_VERIFY_OPTS = {
user_presence_required: true,
user_verification_required: false
}
SK_FLAG_USER_PRESENCE = 0b001
SK_FLAG_USER_VERIFICATION = 0b100
# Parse an OpenSSH public key in authorized_keys format (see sshd(8) manual
# page).
#
@ -78,6 +86,7 @@ module SSHData
end
require "ssh_data/public_key/base"
require "ssh_data/public_key/security_key"
require "ssh_data/public_key/rsa"
require "ssh_data/public_key/dsa"
require "ssh_data/public_key/ecdsa"

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

@ -0,0 +1,30 @@
module SSHData
module PublicKey
module SecurityKey
def build_signing_blob(application, signed_data, signature)
read = 0
sig_algo, raw_sig, signature_read = Encoding.decode_signature(signature)
read += signature_read
sk_flags, sk_flags_read = Encoding.decode_uint8(signature, read)
read += sk_flags_read
counter, counter_read = Encoding.decode_uint32(signature, read)
read += counter_read
if read != signature.bytesize
raise DecodeError, "unexpected trailing data"
end
application_hash = OpenSSL::Digest::SHA256.digest(application)
message_hash = OpenSSL::Digest::SHA256.digest(signed_data)
blob =
application_hash +
Encoding.encode_uint8(sk_flags) +
Encoding.encode_uint32(counter) +
message_hash
[sig_algo, raw_sig, sk_flags, blob]
end
end
end
end

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

@ -1,6 +1,7 @@
module SSHData
module PublicKey
class SKECDSA < ECDSA
include SecurityKey
attr_reader :application
OPENSSL_CURVE_NAME_FOR_CURVE = {
@ -34,34 +35,25 @@ module SSHData
)
end
def verify(signed_data, signature)
def verify(signed_data, signature, **opts)
opts = DEFAULT_SK_VERIFY_OPTS.merge(opts)
read = 0
sig_algo, raw_sig, signature_read = Encoding.decode_signature(signature)
read += signature_read
sk_flags, sk_flags_read = Encoding.decode_uint8(signature, read)
read += sk_flags_read
counter, counter_read = Encoding.decode_uint32(signature, read)
read += counter_read
if read != signature.bytesize
raise DecodeError, "unexpected trailing data"
end
sig_algo, raw_sig, sk_flags, blob = build_signing_blob(application, signed_data, signature)
self.class.check_algorithm!(sig_algo, curve)
application_hash = OpenSSL::Digest::SHA256.digest(application)
message_hash = OpenSSL::Digest::SHA256.digest(signed_data)
blob =
application_hash +
Encoding.encode_uint8(sk_flags) +
Encoding.encode_uint32(counter) +
message_hash
openssl_sig = self.class.openssl_signature(raw_sig)
digest = DIGEST_FOR_CURVE[curve]
openssl.verify(digest.new, openssl_sig, blob)
result = openssl.verify(digest.new, openssl_sig, blob)
if opts[:user_presence_required] && (sk_flags & SK_FLAG_USER_PRESENCE != SK_FLAG_USER_PRESENCE)
false
elsif opts[:user_verification_required] && (sk_flags & SK_FLAG_USER_VERIFICATION != SK_FLAG_USER_VERIFICATION)
false
else
result
end
end
def ==(other)

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

@ -1,6 +1,7 @@
module SSHData
module PublicKey
class SKED25519 < ED25519
include SecurityKey
attr_reader :application
def initialize(algo:, pk:, application:)
@ -23,38 +24,27 @@ module SSHData
)
end
def verify(signed_data, signature)
def verify(signed_data, signature, **opts)
self.class.ed25519_gem_required!
read = 0
sig_algo, raw_sig, signature_read = Encoding.decode_signature(signature)
read += signature_read
sk_flags, sk_flags_read = Encoding.decode_uint8(signature, read)
read += sk_flags_read
counter, counter_read = Encoding.decode_uint32(signature, read)
read += counter_read
if read != signature.bytesize
raise DecodeError, "unexpected trailing data"
end
opts = DEFAULT_SK_VERIFY_OPTS.merge(opts)
sig_algo, raw_sig, sk_flags, blob = build_signing_blob(application, signed_data, signature)
if sig_algo != self.class.algorithm_identifier
raise DecodeError, "bad signature algorithm: #{sig_algo.inspect}"
end
application_hash = OpenSSL::Digest::SHA256.digest(application)
message_hash = OpenSSL::Digest::SHA256.digest(signed_data)
result = begin
ed25519_key.verify(raw_sig, blob)
rescue Ed25519::VerifyError
false
end
blob =
application_hash +
Encoding.encode_uint8(sk_flags) +
Encoding.encode_uint32(counter) +
message_hash
begin
ed25519_key.verify(raw_sig, blob)
rescue Ed25519::VerifyError
if opts[:user_presence_required] && (sk_flags & SK_FLAG_USER_PRESENCE != SK_FLAG_USER_PRESENCE)
false
elsif opts[:user_verification_required] && (sk_flags & SK_FLAG_USER_VERIFICATION != SK_FLAG_USER_VERIFICATION)
false
else
result
end
end

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

@ -70,7 +70,7 @@ module SSHData
@signature = signature
end
def verify(signed_data)
def verify(signed_data, **opts)
key = public_key
digest_algorithm = SUPPORTED_HASH_ALGORITHMS[@hash_algorithm]
@ -93,7 +93,11 @@ module SSHData
Encoding.encode_string(@hash_algorithm) +
Encoding.encode_string(message_digest)
key.verify(blob, @signature)
if key.class.include?(::SSHData::PublicKey::SecurityKey)
key.verify(blob, @signature, **opts)
else
key.verify(blob, @signature)
end
end
def public_key