webauthn 1.16.0 → 1.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -3
- data/CHANGELOG.md +8 -0
- data/README.md +9 -2
- data/lib/cose/algorithm.rb +6 -0
- data/lib/tpm/constants.rb +1 -0
- data/lib/webauthn/attestation_statement/tpm.rb +1 -1
- data/lib/webauthn/attestation_statement/tpm/pub_area.rb +2 -1
- data/lib/webauthn/authenticator_assertion_response.rb +16 -0
- data/lib/webauthn/fake_authenticator.rb +3 -1
- data/lib/webauthn/fake_client.rb +3 -2
- data/lib/webauthn/signature_verifier.rb +2 -2
- data/lib/webauthn/version.rb +1 -1
- data/webauthn.gemspec +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d4cc833d8288e0519614728a71e26e4e7842ec0c597bd7fc839fe9bacbb44c61
|
4
|
+
data.tar.gz: 712c9ad093705954409facf4ee171752ba76865cbca831121a0f88a4c4d9430c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6fd66258429cadca7660ce7c69640b630b13bd21ac4b690d60c37834edcf4b6ce368688186f1b1a23fba8dc4856767314f7a7308e1ae9932f2f51776fabe89cb
|
7
|
+
data.tar.gz: a28362aa5cf1bd451a5b0303750bb55ffd80f2b47c63c9ef04b7f04e300c8b4f997ec0d6a808361503ecb0b780c263d2447c36bde0239657bc3cc5fd6b106719
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v1.17.0] - 2019-06-18
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Support ES384, ES512, PS384, PS512, RS384 and RS512 credentials. Off by default. Enable by adding any of them to `WebAuthn.configuration.algorithms` array. Thank you @bdewater.
|
8
|
+
- Support [Signature Counter](https://www.w3.org/TR/webauthn/#signature-counter) verification. Thank you @bdewater.
|
9
|
+
|
3
10
|
## [v1.16.0] - 2019-06-13
|
4
11
|
|
5
12
|
### Added
|
@@ -187,6 +194,7 @@ Note: Both additions should help making it compatible with Chrome for Android 70
|
|
187
194
|
- `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
|
188
195
|
- Works with ruby 2.5
|
189
196
|
|
197
|
+
[v1.17.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.16.0...v1.17.0/
|
190
198
|
[v1.16.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.15.0...v1.16.0/
|
191
199
|
[v1.15.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.14.0...v1.15.0/
|
192
200
|
[v1.14.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.13.0...v1.14.0/
|
data/README.md
CHANGED
@@ -127,11 +127,12 @@ begin
|
|
127
127
|
attestation_response.verify(expected_challenge)
|
128
128
|
|
129
129
|
# 1. Register the new user and
|
130
|
-
# 2. Keep Credential ID
|
130
|
+
# 2. Keep Credential ID, Credential Public Key and Sign Count under storage
|
131
131
|
# for future authentications
|
132
132
|
# Access by invoking:
|
133
133
|
# `attestation_response.credential.id`
|
134
134
|
# `attestation_response.credential.public_key`
|
135
|
+
# `attestation_response.authenticator_data.sign_count`
|
135
136
|
rescue WebAuthn::VerificationError => e
|
136
137
|
# Handle error
|
137
138
|
end
|
@@ -171,11 +172,13 @@ Assuming you have the previously stored Credential Public Key, now in variable `
|
|
171
172
|
#
|
172
173
|
# E.g. in https://github.com/cedarcode/webauthn-rails-demo-app we use `Base64.strict_decode64`
|
173
174
|
# on the user-agent encoded data before calling `#verify`
|
175
|
+
selected_credential_id = "..."
|
174
176
|
authenticator_data = "..."
|
175
177
|
client_data_json = "..."
|
176
178
|
signature = "..."
|
177
179
|
|
178
180
|
assertion_response = WebAuthn::AuthenticatorAssertionResponse.new(
|
181
|
+
credential_id: selected_credential_id,
|
179
182
|
authenticator_data: authenticator_data,
|
180
183
|
client_data_json: client_data_json,
|
181
184
|
signature: signature
|
@@ -185,7 +188,8 @@ assertion_response = WebAuthn::AuthenticatorAssertionResponse.new(
|
|
185
188
|
# previously stored credential for the user that is attempting to sign in.
|
186
189
|
allowed_credential = {
|
187
190
|
id: credential_id,
|
188
|
-
public_key: credential_public_key
|
191
|
+
public_key: credential_public_key,
|
192
|
+
sign_count: sign_count,
|
189
193
|
}
|
190
194
|
|
191
195
|
begin
|
@@ -195,6 +199,9 @@ begin
|
|
195
199
|
rescue WebAuthn::VerificationError => e
|
196
200
|
# Handle error
|
197
201
|
end
|
202
|
+
|
203
|
+
# Find the selected credential in your data storage using `selected_credential_id`
|
204
|
+
# Update the stored sign count with the value from `assertion_response.authenticator_data.sign_count`
|
198
205
|
```
|
199
206
|
|
200
207
|
## Attestation Statement Formats
|
data/lib/cose/algorithm.rb
CHANGED
@@ -27,6 +27,12 @@ module COSE
|
|
27
27
|
end
|
28
28
|
|
29
29
|
COSE::Algorithm.register(-7, "ES256", "SHA256", COSE::Key::EC2::KTY_EC2, "prime256v1")
|
30
|
+
COSE::Algorithm.register(-35, "ES384", "SHA384", COSE::Key::EC2::KTY_EC2, "prime256v1")
|
31
|
+
COSE::Algorithm.register(-36, "ES512", "SHA512", COSE::Key::EC2::KTY_EC2, "prime256v1")
|
30
32
|
COSE::Algorithm.register(-37, "PS256", "SHA256", COSE::Key::RSA::KTY_RSA)
|
33
|
+
COSE::Algorithm.register(-38, "PS384", "SHA384", COSE::Key::RSA::KTY_RSA)
|
34
|
+
COSE::Algorithm.register(-39, "PS512", "SHA512", COSE::Key::RSA::KTY_RSA)
|
31
35
|
COSE::Algorithm.register(-257, "RS256", "SHA256", COSE::Key::RSA::KTY_RSA)
|
36
|
+
COSE::Algorithm.register(-258, "RS384", "SHA384", COSE::Key::RSA::KTY_RSA)
|
37
|
+
COSE::Algorithm.register(-259, "RS512", "SHA512", COSE::Key::RSA::KTY_RSA)
|
32
38
|
COSE::Algorithm.register(-65535, "RS1", "SHA1", COSE::Key::RSA::KTY_RSA)
|
data/lib/tpm/constants.rb
CHANGED
@@ -40,7 +40,7 @@ module WebAuthn
|
|
40
40
|
def valid_signature?
|
41
41
|
WebAuthn::SignatureVerifier
|
42
42
|
.new(algorithm, attestation_certificate.public_key)
|
43
|
-
.verify(signature, verification_data)
|
43
|
+
.verify(signature, verification_data, rsa_pss_salt_length: :auto)
|
44
44
|
end
|
45
45
|
|
46
46
|
def valid_attestation_certificate?
|
@@ -17,7 +17,8 @@ module WebAuthn
|
|
17
17
|
}.freeze
|
18
18
|
|
19
19
|
COSE_RSA_TO_TPM_ALG = {
|
20
|
-
COSE::Algorithm.by_name("RS256").id => ::TPM::ALG_RSASSA
|
20
|
+
COSE::Algorithm.by_name("RS256").id => ::TPM::ALG_RSASSA,
|
21
|
+
COSE::Algorithm.by_name("PS256").id => ::TPM::ALG_RSAPSS,
|
21
22
|
}.freeze
|
22
23
|
|
23
24
|
COSE_TO_TPM_CURVE = {
|
@@ -10,6 +10,7 @@ require "webauthn/signature_verifier"
|
|
10
10
|
module WebAuthn
|
11
11
|
class CredentialVerificationError < VerificationError; end
|
12
12
|
class SignatureVerificationError < VerificationError; end
|
13
|
+
class SignCountVerificationError < VerificationError; end
|
13
14
|
|
14
15
|
class AuthenticatorAssertionResponse < AuthenticatorResponse
|
15
16
|
def initialize(credential_id:, authenticator_data:, signature:, **options)
|
@@ -25,6 +26,7 @@ module WebAuthn
|
|
25
26
|
|
26
27
|
verify_item(:credential, allowed_credentials)
|
27
28
|
verify_item(:signature, credential_cose_key(allowed_credentials))
|
29
|
+
verify_item(:sign_count, allowed_credentials)
|
28
30
|
|
29
31
|
true
|
30
32
|
end
|
@@ -43,6 +45,20 @@ module WebAuthn
|
|
43
45
|
.verify(signature, authenticator_data_bytes + client_data.hash)
|
44
46
|
end
|
45
47
|
|
48
|
+
def valid_sign_count?(allowed_credentials)
|
49
|
+
matched_credential = allowed_credentials.find do |credential|
|
50
|
+
credential[:id] == credential_id
|
51
|
+
end
|
52
|
+
# TODO: make passing sign count mandatory in next major version
|
53
|
+
stored_sign_count = matched_credential.fetch(:sign_count, 0)
|
54
|
+
|
55
|
+
if authenticator_data.sign_count.nonzero? || stored_sign_count.nonzero?
|
56
|
+
authenticator_data.sign_count > stored_sign_count
|
57
|
+
else
|
58
|
+
true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
46
62
|
def valid_credential?(allowed_credentials)
|
47
63
|
allowed_credential_ids = allowed_credentials.map { |credential| credential[:id] }
|
48
64
|
|
@@ -35,7 +35,8 @@ module WebAuthn
|
|
35
35
|
client_data_hash:,
|
36
36
|
user_present: true,
|
37
37
|
user_verified: false,
|
38
|
-
aaguid: AuthenticatorData::AAGUID
|
38
|
+
aaguid: AuthenticatorData::AAGUID,
|
39
|
+
sign_count: 0
|
39
40
|
)
|
40
41
|
credential_options = credentials[rp_id]
|
41
42
|
|
@@ -47,6 +48,7 @@ module WebAuthn
|
|
47
48
|
user_present: user_present,
|
48
49
|
user_verified: user_verified,
|
49
50
|
aaguid: aaguid,
|
51
|
+
sign_count: sign_count,
|
50
52
|
).serialize
|
51
53
|
|
52
54
|
signature = credential_key.sign("SHA256", authenticator_data + client_data_hash)
|
data/lib/webauthn/fake_client.rb
CHANGED
@@ -41,7 +41,7 @@ module WebAuthn
|
|
41
41
|
}
|
42
42
|
end
|
43
43
|
|
44
|
-
def get(challenge: fake_challenge, rp_id: nil, user_present: true, user_verified: false)
|
44
|
+
def get(challenge: fake_challenge, rp_id: nil, user_present: true, user_verified: false, sign_count: 0)
|
45
45
|
rp_id ||= URI.parse(origin).host
|
46
46
|
|
47
47
|
client_data_json = data_json_for(:get, challenge)
|
@@ -51,7 +51,8 @@ module WebAuthn
|
|
51
51
|
rp_id: rp_id,
|
52
52
|
client_data_hash: client_data_hash,
|
53
53
|
user_present: user_present,
|
54
|
-
user_verified: user_verified
|
54
|
+
user_verified: user_verified,
|
55
|
+
sign_count: sign_count,
|
55
56
|
)
|
56
57
|
|
57
58
|
{
|
@@ -22,10 +22,10 @@ module WebAuthn
|
|
22
22
|
validate
|
23
23
|
end
|
24
24
|
|
25
|
-
def verify(signature, verification_data)
|
25
|
+
def verify(signature, verification_data, rsa_pss_salt_length: :digest)
|
26
26
|
if rsa_pss?
|
27
27
|
public_key.verify_pss(cose_algorithm.hash, signature, verification_data,
|
28
|
-
salt_length:
|
28
|
+
salt_length: rsa_pss_salt_length, mgf1_hash: cose_algorithm.hash)
|
29
29
|
else
|
30
30
|
public_key.verify(cose_algorithm.hash, signature, verification_data)
|
31
31
|
end
|
data/lib/webauthn/version.rb
CHANGED
data/webauthn.gemspec
CHANGED
@@ -43,5 +43,5 @@ Gem::Specification.new do |spec|
|
|
43
43
|
spec.add_development_dependency "byebug", "~> 11.0"
|
44
44
|
spec.add_development_dependency "rake", "~> 12.3"
|
45
45
|
spec.add_development_dependency "rspec", "~> 3.8"
|
46
|
-
spec.add_development_dependency "rubocop", "0.
|
46
|
+
spec.add_development_dependency "rubocop", "0.71.0"
|
47
47
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webauthn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gonzalo Rodriguez
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-06-
|
12
|
+
date: 2019-06-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bindata
|
@@ -183,14 +183,14 @@ dependencies:
|
|
183
183
|
requirements:
|
184
184
|
- - '='
|
185
185
|
- !ruby/object:Gem::Version
|
186
|
-
version: 0.
|
186
|
+
version: 0.71.0
|
187
187
|
type: :development
|
188
188
|
prerelease: false
|
189
189
|
version_requirements: !ruby/object:Gem::Requirement
|
190
190
|
requirements:
|
191
191
|
- - '='
|
192
192
|
- !ruby/object:Gem::Version
|
193
|
-
version: 0.
|
193
|
+
version: 0.71.0
|
194
194
|
description: |-
|
195
195
|
WebAuthn ruby server library ― Make your application a W3C Web Authentication conformant
|
196
196
|
Relying Party and allow your users to authenticate with U2F and FIDO 2.0 authenticators.
|
@@ -283,7 +283,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
283
283
|
- !ruby/object:Gem::Version
|
284
284
|
version: '0'
|
285
285
|
requirements: []
|
286
|
-
rubygems_version: 3.0.
|
286
|
+
rubygems_version: 3.0.4
|
287
287
|
signing_key:
|
288
288
|
specification_version: 4
|
289
289
|
summary: WebAuthn ruby server library
|