webauthn 2.1.0 → 2.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +113 -13
- data/.travis.yml +21 -18
- data/Appraisals +4 -0
- data/CHANGELOG.md +41 -0
- data/CONTRIBUTING.md +0 -5
- data/README.md +70 -8
- data/SECURITY.md +6 -4
- data/gemfiles/openssl_2_2.gemfile +7 -0
- data/lib/cose/rsapkcs1_algorithm.rb +50 -0
- data/lib/webauthn/attestation_object.rb +43 -0
- data/lib/webauthn/attestation_statement.rb +20 -20
- data/lib/webauthn/attestation_statement/android_key.rb +28 -30
- data/lib/webauthn/attestation_statement/android_safetynet.rb +27 -7
- data/lib/webauthn/attestation_statement/base.rb +108 -10
- data/lib/webauthn/attestation_statement/fido_u2f.rb +8 -6
- data/lib/webauthn/attestation_statement/none.rb +7 -1
- data/lib/webauthn/attestation_statement/packed.rb +13 -41
- data/lib/webauthn/attestation_statement/tpm.rb +38 -75
- data/lib/webauthn/authenticator_assertion_response.rb +3 -7
- data/lib/webauthn/authenticator_attestation_response.rb +19 -84
- data/lib/webauthn/authenticator_data.rb +51 -51
- data/lib/webauthn/authenticator_data/attested_credential_data.rb +29 -50
- data/lib/webauthn/authenticator_response.rb +3 -0
- data/lib/webauthn/credential_creation_options.rb +2 -0
- data/lib/webauthn/credential_request_options.rb +2 -0
- data/lib/webauthn/fake_authenticator.rb +7 -3
- data/lib/webauthn/fake_authenticator/attestation_object.rb +7 -3
- data/lib/webauthn/fake_authenticator/authenticator_data.rb +2 -4
- data/lib/webauthn/fake_client.rb +19 -5
- data/lib/webauthn/public_key.rb +21 -2
- data/lib/webauthn/public_key_credential.rb +13 -3
- data/lib/webauthn/u2f_migrator.rb +5 -4
- data/lib/webauthn/version.rb +1 -1
- data/script/ci/install-openssl +7 -0
- data/script/ci/install-ruby +13 -0
- data/webauthn.gemspec +13 -9
- metadata +54 -41
- data/lib/android_safetynet/attestation_response.rb +0 -116
- data/lib/cose/rsassa_algorithm.rb +0 -10
- data/lib/tpm/constants.rb +0 -44
- data/lib/tpm/s_attest.rb +0 -26
- data/lib/tpm/s_attest/s_certify_info.rb +0 -14
- data/lib/tpm/sized_buffer.rb +0 -13
- data/lib/tpm/t_public.rb +0 -32
- data/lib/tpm/t_public/s_ecc_parms.rb +0 -17
- data/lib/tpm/t_public/s_rsa_parms.rb +0 -17
- data/lib/webauthn/attestation_statement/android_key/authorization_list.rb +0 -39
- data/lib/webauthn/attestation_statement/android_key/key_description.rb +0 -37
- data/lib/webauthn/attestation_statement/tpm/cert_info.rb +0 -44
- data/lib/webauthn/attestation_statement/tpm/pub_area.rb +0 -85
- data/lib/webauthn/signature_verifier.rb +0 -77
@@ -1,10 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "cose"
|
4
|
-
|
5
|
-
RSASSAAlgorithm = Struct.new(:id, :name, :hash_function, :kty)
|
6
|
-
|
7
|
-
COSE::Algorithm.register(RSASSAAlgorithm.new(-257, "RS256", "SHA256", COSE::Key::RSA::KTY_RSA))
|
8
|
-
COSE::Algorithm.register(RSASSAAlgorithm.new(-258, "RS384", "SHA384", COSE::Key::RSA::KTY_RSA))
|
9
|
-
COSE::Algorithm.register(RSASSAAlgorithm.new(-259, "RS512", "SHA512", COSE::Key::RSA::KTY_RSA))
|
10
|
-
COSE::Algorithm.register(RSASSAAlgorithm.new(-65535, "RS1", "SHA1", COSE::Key::RSA::KTY_RSA))
|
data/lib/tpm/constants.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module TPM
|
4
|
-
# Section 6 in https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
|
5
|
-
|
6
|
-
GENERATED_VALUE = 0xFF544347
|
7
|
-
|
8
|
-
ST_ATTEST_CERTIFY = 0x8017
|
9
|
-
|
10
|
-
# Algorithms
|
11
|
-
ALG_RSA = 0x0001
|
12
|
-
ALG_SHA1 = 0x0004
|
13
|
-
ALG_SHA256 = 0x000B
|
14
|
-
ALG_NULL = 0x0010
|
15
|
-
ALG_RSASSA = 0x0014
|
16
|
-
ALG_RSAPSS = 0x0016
|
17
|
-
ALG_ECDSA = 0x0018
|
18
|
-
ALG_ECC = 0x0023
|
19
|
-
|
20
|
-
# ECC curves
|
21
|
-
ECC_NIST_P256 = 0x0003
|
22
|
-
|
23
|
-
# https://trustedcomputinggroup.org/resource/vendor-id-registry/ section 2 "TPM Capabilities Vendor ID (CAP_VID)"
|
24
|
-
VENDOR_IDS = {
|
25
|
-
"id:414D4400" => "AMD",
|
26
|
-
"id:41544D4C" => "Atmel",
|
27
|
-
"id:4252434D" => "Broadcom",
|
28
|
-
"id:49424D00" => "IBM",
|
29
|
-
"id:49465800" => "Infineon",
|
30
|
-
"id:494E5443" => "Intel",
|
31
|
-
"id:4C454E00" => "Lenovo",
|
32
|
-
"id:4E534D20" => "National Semiconductor",
|
33
|
-
"id:4E545A00" => "Nationz",
|
34
|
-
"id:4E544300" => "Nuvoton Technology",
|
35
|
-
"id:51434F4D" => "Qualcomm",
|
36
|
-
"id:534D5343" => "SMSC",
|
37
|
-
"id:53544D20" => "ST Microelectronics",
|
38
|
-
"id:534D534E" => "Samsung",
|
39
|
-
"id:534E5300" => "Sinosun",
|
40
|
-
"id:54584E00" => "Texas Instruments",
|
41
|
-
"id:57454300" => "Winbond",
|
42
|
-
"id:524F4343" => "Fuzhou Rockchip",
|
43
|
-
}.freeze
|
44
|
-
end
|
data/lib/tpm/s_attest.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "bindata"
|
4
|
-
require "tpm/constants"
|
5
|
-
require "tpm/sized_buffer"
|
6
|
-
require "tpm/s_attest/s_certify_info"
|
7
|
-
|
8
|
-
module TPM
|
9
|
-
# Section 10.12.8 in https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
|
10
|
-
class SAttest < BinData::Record
|
11
|
-
endian :big
|
12
|
-
|
13
|
-
uint32 :magic
|
14
|
-
uint16 :attested_type
|
15
|
-
sized_buffer :qualified_signer
|
16
|
-
sized_buffer :extra_data
|
17
|
-
|
18
|
-
# s_clock_info :clock_info
|
19
|
-
# uint64 :firmware_version
|
20
|
-
skip length: 25
|
21
|
-
|
22
|
-
choice :attested, selection: :attested_type do
|
23
|
-
s_certify_info TPM::ST_ATTEST_CERTIFY
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "bindata"
|
4
|
-
require "tpm/sized_buffer"
|
5
|
-
|
6
|
-
module TPM
|
7
|
-
class SAttest < BinData::Record
|
8
|
-
# Section 10.12.3 in https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
|
9
|
-
class SCertifyInfo < BinData::Record
|
10
|
-
sized_buffer :name
|
11
|
-
sized_buffer :qualified_name
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
data/lib/tpm/sized_buffer.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "bindata"
|
4
|
-
|
5
|
-
module TPM
|
6
|
-
# Section 10.4 in https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
|
7
|
-
class SizedBuffer < BinData::Record
|
8
|
-
endian :big
|
9
|
-
|
10
|
-
uint16 :buffer_size, value: lambda { buffer.size }
|
11
|
-
string :buffer, read_length: :buffer_size
|
12
|
-
end
|
13
|
-
end
|
data/lib/tpm/t_public.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "bindata"
|
4
|
-
require "tpm/constants"
|
5
|
-
require "tpm/sized_buffer"
|
6
|
-
require "tpm/t_public/s_ecc_parms"
|
7
|
-
require "tpm/t_public/s_rsa_parms"
|
8
|
-
|
9
|
-
module TPM
|
10
|
-
# Section 12.2.4 in https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
|
11
|
-
class TPublic < BinData::Record
|
12
|
-
endian :big
|
13
|
-
|
14
|
-
uint16 :alg_type
|
15
|
-
uint16 :name_alg
|
16
|
-
|
17
|
-
# :object_attributes
|
18
|
-
skip length: 4
|
19
|
-
|
20
|
-
sized_buffer :auth_policy
|
21
|
-
|
22
|
-
choice :parameters, selection: :alg_type do
|
23
|
-
s_ecc_parms TPM::ALG_ECC
|
24
|
-
s_rsa_parms TPM::ALG_RSA
|
25
|
-
end
|
26
|
-
|
27
|
-
choice :unique, selection: :alg_type do
|
28
|
-
sized_buffer TPM::ALG_ECC
|
29
|
-
sized_buffer TPM::ALG_RSA
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "bindata"
|
4
|
-
|
5
|
-
module TPM
|
6
|
-
class TPublic < BinData::Record
|
7
|
-
# Section 12.2.3.6 in https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
|
8
|
-
class SEccParms < BinData::Record
|
9
|
-
endian :big
|
10
|
-
|
11
|
-
uint16 :symmetric
|
12
|
-
uint16 :scheme
|
13
|
-
uint16 :curve_id
|
14
|
-
uint16 :kdf
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "bindata"
|
4
|
-
|
5
|
-
module TPM
|
6
|
-
class TPublic < BinData::Record
|
7
|
-
# Section 12.2.3.5 in https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
|
8
|
-
class SRsaParms < BinData::Record
|
9
|
-
endian :big
|
10
|
-
|
11
|
-
uint16 :symmetric
|
12
|
-
uint16 :scheme
|
13
|
-
uint16 :key_bits
|
14
|
-
uint32 :exponent
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "webauthn/attestation_statement/base"
|
4
|
-
|
5
|
-
module WebAuthn
|
6
|
-
module AttestationStatement
|
7
|
-
class AndroidKey < Base
|
8
|
-
class AuthorizationList
|
9
|
-
PURPOSE_TAG = 1
|
10
|
-
ALL_APPLICATIONS_TAG = 600
|
11
|
-
ORIGIN_TAG = 702
|
12
|
-
|
13
|
-
def initialize(sequence)
|
14
|
-
@sequence = sequence
|
15
|
-
end
|
16
|
-
|
17
|
-
def purpose
|
18
|
-
find_by_tag(PURPOSE_TAG)&.value&.at(0)&.value&.at(0)&.value
|
19
|
-
end
|
20
|
-
|
21
|
-
def all_applications
|
22
|
-
find_by_tag(ALL_APPLICATIONS_TAG)&.value
|
23
|
-
end
|
24
|
-
|
25
|
-
def origin
|
26
|
-
find_by_tag(ORIGIN_TAG)&.value&.at(0)&.value
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
attr_reader :sequence
|
32
|
-
|
33
|
-
def find_by_tag(tag)
|
34
|
-
sequence.detect { |data| data.tag == tag }
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "webauthn/attestation_statement/android_key/authorization_list"
|
4
|
-
require "webauthn/attestation_statement/base"
|
5
|
-
|
6
|
-
module WebAuthn
|
7
|
-
module AttestationStatement
|
8
|
-
class AndroidKey < Base
|
9
|
-
class KeyDescription
|
10
|
-
# https://developer.android.com/training/articles/security-key-attestation#certificate_schema
|
11
|
-
ATTESTATION_CHALLENGE_INDEX = 4
|
12
|
-
SOFTWARE_ENFORCED_INDEX = 6
|
13
|
-
TEE_ENFORCED_INDEX = 7
|
14
|
-
|
15
|
-
def initialize(sequence)
|
16
|
-
@sequence = sequence
|
17
|
-
end
|
18
|
-
|
19
|
-
def attestation_challenge
|
20
|
-
sequence[ATTESTATION_CHALLENGE_INDEX].value
|
21
|
-
end
|
22
|
-
|
23
|
-
def tee_enforced
|
24
|
-
@tee_enforced ||= AuthorizationList.new(sequence[TEE_ENFORCED_INDEX].value)
|
25
|
-
end
|
26
|
-
|
27
|
-
def software_enforced
|
28
|
-
@software_enforced ||= AuthorizationList.new(sequence[SOFTWARE_ENFORCED_INDEX].value)
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
attr_reader :sequence
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "openssl"
|
4
|
-
require "tpm/constants"
|
5
|
-
require "tpm/s_attest"
|
6
|
-
require "webauthn/attestation_statement/base"
|
7
|
-
|
8
|
-
module WebAuthn
|
9
|
-
module AttestationStatement
|
10
|
-
class TPM < Base
|
11
|
-
class CertInfo
|
12
|
-
TPM_TO_OPENSSL_HASH_ALG = {
|
13
|
-
::TPM::ALG_SHA1 => "SHA1",
|
14
|
-
::TPM::ALG_SHA256 => "SHA256"
|
15
|
-
}.freeze
|
16
|
-
|
17
|
-
def initialize(data)
|
18
|
-
@data = data
|
19
|
-
end
|
20
|
-
|
21
|
-
def valid?(attested_data, extra_data)
|
22
|
-
s_attest.magic == ::TPM::GENERATED_VALUE &&
|
23
|
-
valid_name?(attested_data) &&
|
24
|
-
s_attest.extra_data.buffer == extra_data
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
attr_reader :data
|
30
|
-
|
31
|
-
def valid_name?(attested_data)
|
32
|
-
name_hash_alg = s_attest.attested.name.buffer[0..1].unpack("n")[0]
|
33
|
-
name = s_attest.attested.name.buffer[2..-1]
|
34
|
-
|
35
|
-
name == OpenSSL::Digest.digest(TPM_TO_OPENSSL_HASH_ALG[name_hash_alg], attested_data)
|
36
|
-
end
|
37
|
-
|
38
|
-
def s_attest
|
39
|
-
@s_attest ||= ::TPM::SAttest.read(data)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,85 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "cose"
|
4
|
-
require "cose/rsassa_algorithm"
|
5
|
-
require "tpm/constants"
|
6
|
-
require "tpm/t_public"
|
7
|
-
require "webauthn/attestation_statement/base"
|
8
|
-
|
9
|
-
module WebAuthn
|
10
|
-
module AttestationStatement
|
11
|
-
class TPM < Base
|
12
|
-
class PubArea
|
13
|
-
BYTE_LENGTH = 8
|
14
|
-
|
15
|
-
COSE_ECC_TO_TPM_ALG = {
|
16
|
-
COSE::Algorithm.by_name("ES256").id => ::TPM::ALG_ECDSA,
|
17
|
-
}.freeze
|
18
|
-
|
19
|
-
COSE_RSA_TO_TPM_ALG = {
|
20
|
-
COSE::Algorithm.by_name("RS256").id => ::TPM::ALG_RSASSA,
|
21
|
-
COSE::Algorithm.by_name("PS256").id => ::TPM::ALG_RSAPSS,
|
22
|
-
}.freeze
|
23
|
-
|
24
|
-
COSE_TO_TPM_CURVE = {
|
25
|
-
COSE::Key::Curve.by_name("P-256").id => ::TPM::ECC_NIST_P256
|
26
|
-
}.freeze
|
27
|
-
|
28
|
-
def initialize(data)
|
29
|
-
@data = data
|
30
|
-
end
|
31
|
-
|
32
|
-
def valid?(public_key)
|
33
|
-
cose_key = COSE::Key.deserialize(public_key)
|
34
|
-
|
35
|
-
case cose_key
|
36
|
-
when COSE::Key::EC2
|
37
|
-
valid_ecc_key?(cose_key)
|
38
|
-
when COSE::Key::RSA
|
39
|
-
valid_rsa_key?(cose_key)
|
40
|
-
else
|
41
|
-
raise "Unsupported or unknown TPM key type"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
attr_reader :data
|
48
|
-
|
49
|
-
def valid_ecc_key?(cose_key)
|
50
|
-
valid_symmetric? &&
|
51
|
-
valid_scheme?(COSE_ECC_TO_TPM_ALG[cose_key.alg]) &&
|
52
|
-
parameters.curve_id == COSE_TO_TPM_CURVE[cose_key.crv] &&
|
53
|
-
unique == cose_key.x + cose_key.y
|
54
|
-
end
|
55
|
-
|
56
|
-
def valid_rsa_key?(cose_key)
|
57
|
-
valid_symmetric? &&
|
58
|
-
valid_scheme?(COSE_RSA_TO_TPM_ALG[cose_key.alg]) &&
|
59
|
-
parameters.key_bits == cose_key.n.size * BYTE_LENGTH &&
|
60
|
-
unique == cose_key.n
|
61
|
-
end
|
62
|
-
|
63
|
-
def valid_symmetric?
|
64
|
-
parameters.symmetric == ::TPM::ALG_NULL
|
65
|
-
end
|
66
|
-
|
67
|
-
def valid_scheme?(scheme)
|
68
|
-
parameters.scheme == ::TPM::ALG_NULL || parameters.scheme == scheme
|
69
|
-
end
|
70
|
-
|
71
|
-
def unique
|
72
|
-
t_public.unique.buffer
|
73
|
-
end
|
74
|
-
|
75
|
-
def parameters
|
76
|
-
t_public.parameters
|
77
|
-
end
|
78
|
-
|
79
|
-
def t_public
|
80
|
-
@t_public = ::TPM::TPublic.read(data)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "cose"
|
4
|
-
require "cose/rsassa_algorithm"
|
5
|
-
require "openssl"
|
6
|
-
require "webauthn/error"
|
7
|
-
|
8
|
-
module WebAuthn
|
9
|
-
class SignatureVerifier
|
10
|
-
class UnsupportedAlgorithm < Error; end
|
11
|
-
|
12
|
-
# This logic contained in this map constant is a candidate to be moved to cose gem domain
|
13
|
-
KTY_MAP = {
|
14
|
-
COSE::Key::EC2::KTY_EC2 => [OpenSSL::PKey::EC, OpenSSL::PKey::EC::Point],
|
15
|
-
COSE::Key::RSA::KTY_RSA => [OpenSSL::PKey::RSA]
|
16
|
-
}.freeze
|
17
|
-
|
18
|
-
def initialize(algorithm, public_key)
|
19
|
-
@algorithm = algorithm
|
20
|
-
@public_key = public_key
|
21
|
-
|
22
|
-
validate
|
23
|
-
end
|
24
|
-
|
25
|
-
def verify(signature, verification_data, rsa_pss_salt_length: :digest)
|
26
|
-
if rsa_pss?
|
27
|
-
public_key.verify_pss(cose_algorithm.hash_function, signature, verification_data,
|
28
|
-
salt_length: rsa_pss_salt_length, mgf1_hash: cose_algorithm.hash_function)
|
29
|
-
else
|
30
|
-
public_key.verify(cose_algorithm.hash_function, signature, verification_data)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
attr_reader :algorithm, :public_key
|
37
|
-
|
38
|
-
def cose_algorithm
|
39
|
-
case algorithm
|
40
|
-
when COSE::Algorithm::Base
|
41
|
-
algorithm
|
42
|
-
else
|
43
|
-
COSE::Algorithm.find(algorithm)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# This logic is a candidate to be moved to cose gem domain
|
48
|
-
def cose_key_type
|
49
|
-
case cose_algorithm
|
50
|
-
when COSE::Algorithm::ECDSA
|
51
|
-
COSE::Key::EC2::KTY_EC2
|
52
|
-
when COSE::Algorithm::RSAPSS, RSASSAAlgorithm
|
53
|
-
COSE::Key::RSA::KTY_RSA
|
54
|
-
else
|
55
|
-
raise UnsupportedAlgorithm, "Unsupported algorithm #{algorithm}"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def rsa_pss?
|
60
|
-
cose_algorithm.name.start_with?("PS")
|
61
|
-
end
|
62
|
-
|
63
|
-
def validate
|
64
|
-
if !cose_algorithm
|
65
|
-
raise UnsupportedAlgorithm, "Unsupported algorithm #{algorithm}"
|
66
|
-
elsif !supported_algorithms.include?(cose_algorithm.name)
|
67
|
-
raise UnsupportedAlgorithm, "Unsupported algorithm #{algorithm}"
|
68
|
-
elsif !KTY_MAP[cose_key_type].include?(public_key.class)
|
69
|
-
raise("Incompatible algorithm and key")
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def supported_algorithms
|
74
|
-
WebAuthn.configuration.algorithms
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|