webauthn 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8dd2e6fbccb0b180e0a36f4980939a1ba3a66d0cc744a7d50b140feb01917a35
4
- data.tar.gz: 403281bfe63aa4ca9929bd0ca2e8cc9ff3af4ae66b21251f26118138fb355051
3
+ metadata.gz: 14d13c4bce35ebbe6cde4332ab9f5af2b5e0a9592fdc1fcb6d902954764ff656
4
+ data.tar.gz: 28f671cb2e1baeffa0f0662863867e6c12c05338fd5d4a780c2e8f6bc54344f1
5
5
  SHA512:
6
- metadata.gz: 4ab428637bed52191bdee14a96a9676df44019170ffab49862bc28e84c59202f3fb8302b36fd0bc29321608352712ea18cdecbe0311dfc02a167da1b2bf1d3b5
7
- data.tar.gz: cb98ae9cbfbe66804e2bea396121da2874b667b6e25ee58790195dbfd2a6b6d936cca70e50d7b9d796f2af0928c164cbdd3093987a202171f19e365bbdefd6a1
6
+ metadata.gz: c44f926b6046f13b9ff0b71646a8ce72ff87ac064b82cfc8e1a273889d1878567655455d874619361aa1c9906cdc06234e4e5502736c18148e3721e36c790fff
7
+ data.tar.gz: ac6e06366d290ef51ad1257386d3a44a0b9eae9a3fd7e4071392c73a0a1cd39784da6bf942ac984fd84d0ef2100bff4cf0dbaf83df064cc6df5f2cdffa5ddc22
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.4.0] - 2018-10-11
4
+
5
+ ### Added
6
+
7
+ - _Registration_ ceremony
8
+ - `WebAuthn::AuthenticatorAttestationResponse.valid?` supports `android-safetynet` attestation statements. Thank you @bdewater!
9
+
3
10
  ## [v1.3.0] - 2018-10-11
4
11
 
5
12
  ### Added
@@ -78,6 +85,7 @@ Note: Both additions should help making it compatible with Chrome for Android 70
78
85
  - `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
79
86
  - Works with ruby 2.5
80
87
 
88
+ [v1.4.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.3.0...v1.4.0/
81
89
  [v1.3.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.2.0...v1.3.0/
82
90
  [v1.2.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.1.0...v1.2.0/
83
91
  [v1.1.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.0.0...v1.1.0/
@@ -7,6 +7,7 @@ module WebAuthn
7
7
  ATTESTATION_FORMAT_NONE = "none"
8
8
  ATTESTATION_FORMAT_FIDO_U2F = "fido-u2f"
9
9
  ATTESTATION_FORMAT_PACKED = 'packed'
10
+ ATTESTATION_FORMAT_ANDROID_SAFETYNET = "android-safetynet"
10
11
 
11
12
  def self.from(format, statement)
12
13
  case format
@@ -19,6 +20,9 @@ module WebAuthn
19
20
  when ATTESTATION_FORMAT_PACKED
20
21
  require "webauthn/attestation_statement/packed"
21
22
  WebAuthn::AttestationStatement::Packed.new(statement)
23
+ when ATTESTATION_FORMAT_ANDROID_SAFETYNET
24
+ require "webauthn/attestation_statement/android_safetynet"
25
+ WebAuthn::AttestationStatement::AndroidSafetynet.new(statement)
22
26
  else
23
27
  raise FormatNotSupportedError, "Unsupported attestation format '#{format}'"
24
28
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "jwt"
4
+ require "openssl"
5
+ require "webauthn/attestation_statement/base"
6
+
7
+ module WebAuthn
8
+ module AttestationStatement
9
+ # Implements https://www.w3.org/TR/2018/CR-webauthn-20180807/#android-safetynet-attestation
10
+ class AndroidSafetynet < Base
11
+ def self.default_trust_store
12
+ OpenSSL::X509::Store.new.tap { |trust_store| trust_store.set_default_paths }
13
+ end
14
+
15
+ def valid?(authenticator_data, client_data_hash, trust_store: self.class.default_trust_store)
16
+ trusted_attestation_certificate?(trust_store) &&
17
+ valid_signature? &&
18
+ valid_attestation_domain? &&
19
+ valid_version? &&
20
+ valid_nonce?(authenticator_data, client_data_hash) &&
21
+ cts_profile_match?
22
+ end
23
+
24
+ private
25
+
26
+ def trusted_attestation_certificate?(trust_store)
27
+ signing_certificates.each do |certificate|
28
+ trust_store.add_cert(certificate)
29
+ end
30
+ trust_store.verify(attestation_certificate)
31
+ end
32
+
33
+ def valid_signature?
34
+ signed_payload, _, base64_signature = statement["response"].rpartition(".")
35
+ signature = Base64.urlsafe_decode64(base64_signature)
36
+ attestation_certificate.public_key.verify(OpenSSL::Digest::SHA256.new, signature, signed_payload)
37
+ end
38
+
39
+ def valid_attestation_domain?
40
+ subject = attestation_certificate.subject.to_a
41
+ subject.assoc('CN')[1] == "attest.android.com"
42
+ end
43
+
44
+ # TODO: improve once the spec has clarifications https://github.com/w3c/webauthn/issues/968
45
+ def valid_version?
46
+ !statement["ver"].empty?
47
+ end
48
+
49
+ def valid_nonce?(authenticator_data, client_data_hash)
50
+ nonce = unverified_jws_result[0]["nonce"]
51
+ nonce == verification_data(authenticator_data, client_data_hash)
52
+ end
53
+
54
+ def cts_profile_match?
55
+ unverified_jws_result[0]["ctsProfileMatch"]
56
+ end
57
+
58
+ def verification_data(authenticator_data, client_data_hash)
59
+ Digest::SHA256.base64digest(authenticator_data.data + client_data_hash)
60
+ end
61
+
62
+ def attestation_certificate
63
+ attestation_certificate_chain[0]
64
+ end
65
+
66
+ def signing_certificates
67
+ attestation_certificate_chain[1..-1]
68
+ end
69
+
70
+ def attestation_certificate_chain
71
+ @attestation_certificate_chain ||= unverified_jws_result[1]["x5c"].map do |cert|
72
+ OpenSSL::X509::Certificate.new(Base64.strict_decode64(cert))
73
+ end
74
+ end
75
+
76
+ def unverified_jws_result
77
+ @unverified_jws_result ||= JWT.decode(statement["response"], nil, false)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebAuthn
4
- VERSION = "1.3.0"
4
+ VERSION = "1.4.0"
5
5
  end
data/webauthn.gemspec CHANGED
@@ -27,8 +27,11 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
29
 
30
+ spec.required_ruby_version = ">= 2.4"
31
+
30
32
  spec.add_dependency "cbor", "~> 0.5.9.2"
31
33
  spec.add_dependency "cose", "~> 0.1.0"
34
+ spec.add_dependency "jwt", [">= 1.5", "< 3.0"]
32
35
 
33
36
  spec.add_development_dependency "bundler", "~> 1.16"
34
37
  spec.add_development_dependency "byebug", "~> 10.0"
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.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gonzalo Rodriguez
@@ -39,6 +39,26 @@ dependencies:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
41
  version: 0.1.0
42
+ - !ruby/object:Gem::Dependency
43
+ name: jwt
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '1.5'
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '3.0'
52
+ type: :runtime
53
+ prerelease: false
54
+ version_requirements: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '1.5'
59
+ - - "<"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
42
62
  - !ruby/object:Gem::Dependency
43
63
  name: bundler
44
64
  requirement: !ruby/object:Gem::Requirement
@@ -131,6 +151,7 @@ files:
131
151
  - lib/cose/ecdsa.rb
132
152
  - lib/webauthn.rb
133
153
  - lib/webauthn/attestation_statement.rb
154
+ - lib/webauthn/attestation_statement/android_safetynet.rb
134
155
  - lib/webauthn/attestation_statement/base.rb
135
156
  - lib/webauthn/attestation_statement/fido_u2f.rb
136
157
  - lib/webauthn/attestation_statement/none.rb
@@ -160,7 +181,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
160
181
  requirements:
161
182
  - - ">="
162
183
  - !ruby/object:Gem::Version
163
- version: '0'
184
+ version: '2.4'
164
185
  required_rubygems_version: !ruby/object:Gem::Requirement
165
186
  requirements:
166
187
  - - ">="
@@ -168,7 +189,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
168
189
  version: '0'
169
190
  requirements: []
170
191
  rubyforge_project:
171
- rubygems_version: 2.7.7
192
+ rubygems_version: 2.7.6
172
193
  signing_key:
173
194
  specification_version: 4
174
195
  summary: WebAuthn in ruby ― Ruby implementation of a WebAuthn Relying Party