webauthn 1.2.0 → 1.3.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: ae88f2e29c3d4c734f5d7efec59b6dd3824a2976a10c5cb7bc03ff525d79852c
4
- data.tar.gz: b62bcde957604db6eb660ccd515c66bdb894178a3e6173a783483a0ee0378ac2
3
+ metadata.gz: 8dd2e6fbccb0b180e0a36f4980939a1ba3a66d0cc744a7d50b140feb01917a35
4
+ data.tar.gz: 403281bfe63aa4ca9929bd0ca2e8cc9ff3af4ae66b21251f26118138fb355051
5
5
  SHA512:
6
- metadata.gz: 6b40ec846092c70e19e79656325e24f1ed43231b911b37fe3fb9be20afbcd276b8d1e46f2e3bd719c92f0f031738f364581514db542c981028369ffbca28afe3
7
- data.tar.gz: dd26ac18ca8db8ae98007a9f566e521a7d24998f244583099ff7f7bac4a8776d5ab2fa8f76fc2f2c8d7291d3119b21efcb422d46ee892dea6e83045c51b85878
6
+ metadata.gz: 4ab428637bed52191bdee14a96a9676df44019170ffab49862bc28e84c59202f3fb8302b36fd0bc29321608352712ea18cdecbe0311dfc02a167da1b2bf1d3b5
7
+ data.tar.gz: cb98ae9cbfbe66804e2bea396121da2874b667b6e25ee58790195dbfd2a6b6d936cca70e50d7b9d796f2af0928c164cbdd3093987a202171f19e365bbdefd6a1
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.3.0] - 2018-10-11
4
+
5
+ ### Added
6
+
7
+ - _Registration_ ceremony
8
+ - `WebAuthn::AuthenticatorAttestationResponse.valid?` supports `packed` attestation statements. Thank you @sorah!
9
+
3
10
  ## [v1.2.0] - 2018-10-08
4
11
 
5
12
  ### Added
@@ -71,6 +78,7 @@ Note: Both additions should help making it compatible with Chrome for Android 70
71
78
  - `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
72
79
  - Works with ruby 2.5
73
80
 
81
+ [v1.3.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.2.0...v1.3.0/
74
82
  [v1.2.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.1.0...v1.2.0/
75
83
  [v1.1.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.0.0...v1.1.0/
76
84
  [v1.0.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.2.0...v1.0.0/
data/README.md CHANGED
@@ -21,7 +21,7 @@ This gem will help your ruby server act as a conforming [_Relying-Party_](https:
21
21
  Currently supporting [Web Authentication API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API):
22
22
  - [Mozilla Firefox](https://www.mozilla.org/firefox/) 60+
23
23
  - [Google Chrome](https://www.google.com/chrome/) 67+
24
- - Google Chrome 65 & 66 (Disabled by default, go to chrome://flags to enable Web Authentication API feature)
24
+ - [Google Chrome for Android Beta](https://play.google.com/store/apps/details?id=com.chrome.beta) 70+
25
25
 
26
26
  ### A conforming Authenticator
27
27
 
@@ -2,8 +2,11 @@
2
2
 
3
3
  module WebAuthn
4
4
  module AttestationStatement
5
+ class FormatNotSupportedError < StandardError; end
6
+
5
7
  ATTESTATION_FORMAT_NONE = "none"
6
8
  ATTESTATION_FORMAT_FIDO_U2F = "fido-u2f"
9
+ ATTESTATION_FORMAT_PACKED = 'packed'
7
10
 
8
11
  def self.from(format, statement)
9
12
  case format
@@ -13,8 +16,11 @@ module WebAuthn
13
16
  when ATTESTATION_FORMAT_FIDO_U2F
14
17
  require "webauthn/attestation_statement/fido_u2f"
15
18
  WebAuthn::AttestationStatement::FidoU2f.new(statement)
19
+ when ATTESTATION_FORMAT_PACKED
20
+ require "webauthn/attestation_statement/packed"
21
+ WebAuthn::AttestationStatement::Packed.new(statement)
16
22
  else
17
- raise "Unsupported attestation format '#{attestation_format}'"
23
+ raise FormatNotSupportedError, "Unsupported attestation format '#{format}'"
18
24
  end
19
25
  end
20
26
  end
@@ -3,11 +3,13 @@
3
3
  module WebAuthn
4
4
  module AttestationStatement
5
5
  class Base
6
+ class NotSupportedError < StandardError; end
7
+
6
8
  def initialize(statement)
7
9
  @statement = statement
8
10
  end
9
11
 
10
- def valid?(*_args)
12
+ def valid?(_authenticator_data, _client_data_hash)
11
13
  raise NotImpelementedError
12
14
  end
13
15
 
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+ require "webauthn/attestation_statement/base"
5
+
6
+ module WebAuthn
7
+ # Implements https://www.w3.org/TR/2018/CR-webauthn-20180807/#packed-attestation
8
+ # ECDAA attestation is unsupported.
9
+ module AttestationStatement
10
+ class Packed < Base
11
+ # Follows "Verification procedure"
12
+ def valid?(authenticator_data, client_data_hash)
13
+ check_unsupported_feature
14
+
15
+ valid_format? &&
16
+ valid_certificate_chain?(authenticator_data.credential) &&
17
+ meet_certificate_requirement? &&
18
+ valid_signature?(authenticator_data, client_data_hash)
19
+ end
20
+
21
+ private
22
+
23
+ def algorithm
24
+ statement["alg"]
25
+ end
26
+
27
+ def signature
28
+ statement["sig"]
29
+ end
30
+
31
+ def raw_attestation_certificates
32
+ statement["x5c"]
33
+ end
34
+
35
+ def raw_ecdaa_key_id
36
+ statement["ecdaaKeyId"]
37
+ end
38
+
39
+ def valid_format?
40
+ algorithm && signature && (
41
+ [raw_attestation_certificates, raw_ecdaa_key_id].compact.size < 2
42
+ )
43
+ end
44
+
45
+ def check_unsupported_feature
46
+ if raw_ecdaa_key_id
47
+ raise NotSupportedError, "ecdaaKeyId of the packed attestation format is not implemented yet"
48
+ end
49
+ end
50
+
51
+ def attestation_certificate_chain
52
+ @attestation_certificate_chain ||= raw_attestation_certificates&.map do |cert|
53
+ OpenSSL::X509::Certificate.new(cert)
54
+ end
55
+ end
56
+
57
+ def attestation_certificate
58
+ attestation_certificate_chain&.first
59
+ end
60
+
61
+ def valid_certificate_chain?(credential)
62
+ public_keys = attestation_certificate_chain&.map(&:public_key) || [credential.public_key_object]
63
+ public_keys.all? do |public_key|
64
+ public_key.is_a?(OpenSSL::PKey::EC) && public_key.check_key
65
+ end
66
+ end
67
+
68
+ # Check https://www.w3.org/TR/2018/CR-webauthn-20180807/#packed-attestation-cert-requirements
69
+ def meet_certificate_requirement?
70
+ return true unless attestation_certificate
71
+ subject = attestation_certificate.subject.to_a
72
+
73
+ attestation_certificate.version == 2 &&
74
+ subject.assoc('OU')&.at(1) == "Authenticator Attestation" &&
75
+ attestation_certificate.extensions.find { |ext| ext.oid == 'basicConstraints' }&.value == 'CA:FALSE'
76
+ end
77
+
78
+ def valid_signature?(authenticator_data, client_data_hash)
79
+ (attestation_certificate&.public_key || authenticator_data.credential.public_key_object).verify(
80
+ "SHA256",
81
+ signature,
82
+ verification_data(authenticator_data, client_data_hash)
83
+ )
84
+ end
85
+
86
+ def verification_data(authenticator_data, client_data_hash)
87
+ authenticator_data.data + client_data_hash
88
+ end
89
+ end
90
+ end
91
+ end
@@ -12,7 +12,18 @@ module WebAuthn
12
12
  UINT16_BIG_ENDIAN_FORMAT = "n*"
13
13
 
14
14
  # FIXME: use keyword_init when we dropped Ruby 2.4 support
15
- Credential = Struct.new(:id, :public_key)
15
+ Credential = Struct.new(:id, :public_key) do
16
+ def public_key_object
17
+ group = OpenSSL::PKey::EC::Group.new("prime256v1")
18
+ key = OpenSSL::PKey::EC.new(group)
19
+
20
+ bn = OpenSSL::BN.new(public_key, 2)
21
+ point = OpenSSL::PKey::EC::Point.new(group, bn)
22
+ key.public_key = point
23
+
24
+ key
25
+ end
26
+ end
16
27
 
17
28
  def initialize(data)
18
29
  @data = data
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebAuthn
4
- VERSION = "1.2.0"
4
+ VERSION = "1.3.0"
5
5
  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.2.0
4
+ version: 1.3.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: 2018-10-08 00:00:00.000000000 Z
12
+ date: 2018-10-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cbor
@@ -134,6 +134,7 @@ files:
134
134
  - lib/webauthn/attestation_statement/base.rb
135
135
  - lib/webauthn/attestation_statement/fido_u2f.rb
136
136
  - lib/webauthn/attestation_statement/none.rb
137
+ - lib/webauthn/attestation_statement/packed.rb
137
138
  - lib/webauthn/authenticator_assertion_response.rb
138
139
  - lib/webauthn/authenticator_attestation_response.rb
139
140
  - lib/webauthn/authenticator_data.rb