webauthn 1.16.0 → 1.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42985c0e7686cf588be02d1afef8e315e0692561533f076e36419cd2ef3b2c74
4
- data.tar.gz: 3970cd2424034f2a28e1ffb92954151aa1ae113391731f63f9d1734c10a61bce
3
+ metadata.gz: d4cc833d8288e0519614728a71e26e4e7842ec0c597bd7fc839fe9bacbb44c61
4
+ data.tar.gz: 712c9ad093705954409facf4ee171752ba76865cbca831121a0f88a4c4d9430c
5
5
  SHA512:
6
- metadata.gz: 6993542bbc3ec899929f6ba5e13b34a347692f13da9efd7cab541de38e0473f2271c0c9e67085bd5e22439c59c97c7dc86680b7579cf578fd973eabc23fea2c4
7
- data.tar.gz: c30c9f9e9c43fddf01621eff5f1068b9ecc280649801a53ba7daa736fb1eb88724efaf8e50e4d8768544ce8b2a725318693eec3b84c6d8cef0137d8d712f6e85
6
+ metadata.gz: 6fd66258429cadca7660ce7c69640b630b13bd21ac4b690d60c37834edcf4b6ce368688186f1b1a23fba8dc4856767314f7a7308e1ae9932f2f51776fabe89cb
7
+ data.tar.gz: a28362aa5cf1bd451a5b0303750bb55ffd80f2b47c63c9ef04b7f04e300c8b4f997ec0d6a808361503ecb0b780c263d2447c36bde0239657bc3cc5fd6b106719
@@ -24,9 +24,6 @@ Metrics/LineLength:
24
24
  Naming:
25
25
  Enabled: true
26
26
 
27
- Performance:
28
- Enabled: true
29
-
30
27
  Security:
31
28
  Enabled: true
32
29
 
@@ -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 and Credential Public Key under storage
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
@@ -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)
@@ -13,6 +13,7 @@ module TPM
13
13
  ALG_SHA256 = 0x000B
14
14
  ALG_NULL = 0x0010
15
15
  ALG_RSASSA = 0x0014
16
+ ALG_RSAPSS = 0x0016
16
17
  ALG_ECDSA = 0x0018
17
18
  ALG_ECC = 0x0023
18
19
 
@@ -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)
@@ -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: :digest, mgf1_hash: cose_algorithm.hash)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebAuthn
4
- VERSION = "1.16.0"
4
+ VERSION = "1.17.0"
5
5
  end
@@ -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.67.2"
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.16.0
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-13 00:00:00.000000000 Z
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.67.2
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.67.2
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.3
286
+ rubygems_version: 3.0.4
287
287
  signing_key:
288
288
  specification_version: 4
289
289
  summary: WebAuthn ruby server library