webauthn 2.4.1 → 2.5.2

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: e1ffc928d4b54cc4c19c946a30e3e0d1e6a56b317d9d82376bb7f7f9693ee88a
4
- data.tar.gz: fe42ab966c5ec4ef20089f147276ba485496b8bcf284c1a16a05606c217a434a
3
+ metadata.gz: f07d44a7778995c6bd2531b26f61e8974ba6ccc8dcf5ff1f21886f353423d598
4
+ data.tar.gz: ecb287679447b3074065f2b06cb0f38b20c9a94114ed2b592d93e99874dfda1a
5
5
  SHA512:
6
- metadata.gz: bd77e2c99e1a08f63dc1986edef737e64872f48108e5e664c8517c7bea11e22a9b4c2bf6e07f7d370d09c3ba3ba3264dff309fd792a47c239d359b27bdd070db
7
- data.tar.gz: 36a50f38e8c7dac6e33e0494d9ebeac33587ace21d4cad022be1984bd7f915112ba99c6fb975186e63d2757156c09014538a8cfda55db8edeac5ef0327c42bc0
6
+ metadata.gz: 98811fdbdb15cd80defb95a75de555a3775864bb1c1f1ac94af4a605af2fa3acf7908d91a120b5c3e214af890469d5f2194e5e037a9f8a40b03935159be6a1f1
7
+ data.tar.gz: 8d90a9d37fb83a0ecf5e0c29e8f5154a0ee2170da994238b55fcc4042cb84f6b7fb4e09386e704a2d83f363ef0864fb1fa60c913eea3ae2754e5189435302570
@@ -0,0 +1,32 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: build
9
+
10
+ on: push
11
+
12
+ jobs:
13
+ test:
14
+ runs-on: ubuntu-20.04
15
+ strategy:
16
+ fail-fast: false
17
+ matrix:
18
+ ruby:
19
+ - '3.1'
20
+ - '3.0'
21
+ - '2.7'
22
+ - '2.6'
23
+ - '2.5'
24
+ - '2.4'
25
+ - truffleruby
26
+ steps:
27
+ - uses: actions/checkout@v2
28
+ - uses: ruby/setup-ruby@v1
29
+ with:
30
+ ruby-version: ${{ matrix.ruby }}
31
+ bundler-cache: true
32
+ - run: bundle exec rake
@@ -0,0 +1,21 @@
1
+ # Syntax reference:
2
+ # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions
3
+ name: Git Checks
4
+
5
+ on:
6
+ pull_request:
7
+ types: [opened, synchronize]
8
+
9
+ jobs:
10
+ # Fixup commits are OK in pull requests, but should generally be squashed
11
+ # before merging to master, e.g. using `git rebase -i --autosquash master`.
12
+ # See https://github.com/marketplace/actions/block-autosquash-commits
13
+ block-fixup:
14
+ runs-on: ubuntu-latest
15
+
16
+ steps:
17
+ - uses: actions/checkout@v2.0.0
18
+ - name: Block autosquash commits
19
+ uses: xt0rted/block-autosquash-commits-action@v2
20
+ with:
21
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
data/.rubocop.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  require:
2
2
  - rubocop-rspec
3
+ - rubocop-rake
3
4
 
4
5
  inherit_mode:
5
6
  merge:
@@ -8,6 +9,7 @@ inherit_mode:
8
9
  AllCops:
9
10
  TargetRubyVersion: 2.4
10
11
  DisabledByDefault: true
12
+ NewCops: disable
11
13
  Exclude:
12
14
  - "gemfiles/**/*"
13
15
  - "vendor/**/*"
@@ -24,6 +26,9 @@ Layout:
24
26
  Layout/ClassStructure:
25
27
  Enabled: true
26
28
 
29
+ Layout/EmptyLineBetweenDefs:
30
+ AllowAdjacentOneLineDefs: true
31
+
27
32
  Layout/EmptyLinesAroundAttributeAccessor:
28
33
  Enabled: true
29
34
 
@@ -92,6 +97,9 @@ Lint/UnreachableLoop:
92
97
  Naming:
93
98
  Enabled: true
94
99
 
100
+ Naming/VariableNumber:
101
+ Enabled: false
102
+
95
103
  RSpec/Be:
96
104
  Enabled: true
97
105
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,38 @@
1
1
  # Changelog
2
2
 
3
+ ## [v3.0.0.alpha1] - 2020-06-27
4
+
5
+ ### Added
6
+
7
+ - Ability to define multiple relying parties with the introduction of the `WebAuthn::RelyingParty` class ([@padulafacundo], [@brauliomartinezlm])
8
+
9
+ ## [v2.5.1] - 2022-07-13
10
+
11
+ ### Added
12
+
13
+ - Updated dependencies to make the gem compatible with openssl-3 [@ClearlyClaire]
14
+
15
+ ## [v2.5.1] - 2022-03-20
16
+
17
+ ### Added
18
+
19
+ - Updated openssl support to be ~>2.2 [@bdewater]
20
+
21
+ ### Removed
22
+
23
+ - Removed dependency [secure_compare dependency] (https://rubygems.org/gems/secure_compare/versions/0.0.1) and use OpenSSL#secure_compare instead [@bdewater]
24
+
25
+ ## [v2.5.0] - 2021-03-14
26
+
27
+ ### Added
28
+
29
+ - Support 'apple' attestation statement format ([#343](https://github.com/cedarcode/webauthn-ruby/pull/343) / [@juanarias93], [@santiagorodriguez96])
30
+ - Allow specifying an array of ids as `allow_credentials:` for `FakeClient#get` method ([#335](https://github.com/cedarcode/webauthn-ruby/pull/335) / [@kingjan1999])
31
+
32
+ ### Removed
33
+
34
+ - No longer accept "removed from the WebAuthn spec" options `rp: { icon: }` and `user: { icon: }` for `WebAuthn::Credential.options_for_create` method ([#326](https://github.com/cedarcode/webauthn-ruby/pull/326) / [@santiagorodriguez96])
35
+
3
36
  ## [v2.4.1] - 2021-02-15
4
37
 
5
38
  ### Fixed
@@ -307,6 +340,10 @@ Note: Both additions should help making it compatible with Chrome for Android 70
307
340
  - `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
308
341
  - Works with ruby 2.5
309
342
 
343
+ [v3.0.0.alpha1]: https://github.com/cedarcode/webauthn-ruby/compare/2-stable...v3.0.0.alpha1/
344
+ [v2.5.2]: https://github.com/cedarcode/webauthn-ruby/compare/v2.5.0...v2.5.2/
345
+ [v2.5.1]: https://github.com/cedarcode/webauthn-ruby/compare/v2.5.0...v2.5.1/
346
+ [v2.5.0]: https://github.com/cedarcode/webauthn-ruby/compare/v2.4.1...v2.5.0/
310
347
  [v2.4.1]: https://github.com/cedarcode/webauthn-ruby/compare/v2.4.0...v2.4.1/
311
348
  [v2.4.0]: https://github.com/cedarcode/webauthn-ruby/compare/v2.3.0...v2.4.0/
312
349
  [v2.3.0]: https://github.com/cedarcode/webauthn-ruby/compare/v2.2.1...v2.3.0/
@@ -336,6 +373,7 @@ Note: Both additions should help making it compatible with Chrome for Android 70
336
373
  [v0.2.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.1.0...v0.2.0/
337
374
  [v0.1.0]: https://github.com/cedarcode/webauthn-ruby/compare/v0.0.0...v0.1.0/
338
375
 
376
+ [@brauliomartinezlm]: https://github.com/brauliomartinezlm
339
377
  [@bdewater]: https://github.com/bdewater
340
378
  [@jdongelmans]: https://github.com/jdongelmans
341
379
  [@kalebtesfay]: https://github.com/kalebtesfay
@@ -345,3 +383,8 @@ Note: Both additions should help making it compatible with Chrome for Android 70
345
383
  [@padulafacundo]: https://github.com/padulafacundo
346
384
  [@santiagorodriguez96]: https://github.com/santiagorodriguez96
347
385
  [@lgarron]: https://github.com/lgarron
386
+ [@juanarias93]: https://github.com/juanarias93
387
+ [@kingjan1999]: https://github.com/@kingjan1999
388
+ [@jdongelmans]: https://github.com/jdongelmans
389
+ [@petergoldstein]: https://github.com/petergoldstein
390
+ [@ClearlyClaire]: https://github.com/ClearlyClaire
data/README.md CHANGED
@@ -6,7 +6,7 @@ For the current release version see https://github.com/cedarcode/webauthn-ruby/b
6
6
  ![banner](assets/webauthn-ruby.png)
7
7
 
8
8
  [![Gem](https://img.shields.io/gem/v/webauthn.svg?style=flat-square)](https://rubygems.org/gems/webauthn)
9
- [![Travis](https://img.shields.io/travis/cedarcode/webauthn-ruby/master.svg?style=flat-square)](https://travis-ci.org/cedarcode/webauthn-ruby)
9
+ [![Travis](https://img.shields.io/travis/cedarcode/webauthn-ruby/master.svg?style=flat-square)](https://travis-ci.com/cedarcode/webauthn-ruby)
10
10
  [![Conventional Commits](https://img.shields.io/badge/Conventional%20Commits-1.0.0-informational.svg?style=flat-square)](https://conventionalcommits.org)
11
11
  [![Join the chat at https://gitter.im/cedarcode/webauthn-ruby](https://badges.gitter.im/cedarcode/webauthn-ruby.svg)](https://gitter.im/cedarcode/webauthn-ruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
12
12
 
@@ -96,6 +96,8 @@ If you are migrating an existing application from the legacy FIDO U2F JavaScript
96
96
 
97
97
  ### Configuration
98
98
 
99
+ If you have a multi-tenant application or just need to configure WebAuthn differently for separate parts of your application (e.g. if your users authenticate to different subdomains in the same application), we strongly recommend you look at this [Advanced Configuration](docs/advanced_configuration.md) section instead of this.
100
+
99
101
  For a Rails application this would go in `config/initializers/webauthn.rb`.
100
102
 
101
103
  ```ruby
@@ -408,7 +410,7 @@ credential.authenticator_extension_outputs
408
410
 
409
411
  ## Attestation
410
412
 
411
- ### Attestation Statement Format
413
+ ### Attestation Statement Formats
412
414
 
413
415
  | Attestation Statement Format | Supported? |
414
416
  | -------- | :--------: |
@@ -417,6 +419,7 @@ credential.authenticator_extension_outputs
417
419
  | tpm (x5c attestation) | Yes |
418
420
  | android-key | Yes |
419
421
  | android-safetynet | Yes |
422
+ | apple | Yes |
420
423
  | fido-u2f | Yes |
421
424
  | none | Yes |
422
425
 
data/SECURITY.md CHANGED
@@ -4,9 +4,10 @@
4
4
 
5
5
  | Version | Supported |
6
6
  | ------- | ------------------ |
7
+ | 2.5.z | :white_check_mark: |
7
8
  | 2.4.z | :white_check_mark: |
8
9
  | 2.3.z | :white_check_mark: |
9
- | 2.2.z | :white_check_mark: |
10
+ | 2.2.z | :x: |
10
11
  | 2.1.z | :x: |
11
12
  | 2.0.z | :x: |
12
13
  | 1.18.z | :white_check_mark: |
@@ -0,0 +1,174 @@
1
+ # Advanced Configuration
2
+
3
+ ## Global vs Instance Based Configuration
4
+
5
+ Which approach suits best your needs will depend on the architecture of your application and how do your users need to register and authenticate to it.
6
+
7
+ If you have a multi-tenant application, or any application segmenation, where your users register and authenticate to each of these tenants or segments individuallly using different hostnames, or with different security needs, you need to go through [Instance Based Configuration](#instance-based-configuration).
8
+
9
+ However, if your application is served for just one hostname, or else if your users authenticate to only one subdmain (e.g. your application serves www.example.com and admin.example.com but all you users authenticate through auth.example.com) you can still rely on one [Global Configuration](../README.md#configuration).
10
+
11
+ If you are still not sure, or want to keep your options open, be aware that [Instance Based Configuration](#instance-based-configuration) is also a valid way of defining a single instance configuration and how you share such configuration across your application, it's up to you.
12
+
13
+
14
+ ## Instance Based Configuration
15
+
16
+ Intead of the [Global Configuration](../README.md#configuration) you place in `config/initializers/webauthn.rb`,
17
+ you can now have an on-demand instance of `WebAuthn::RelyingParty` with the same configuration options, that
18
+ you can build anywhere in you application, in the following way:
19
+
20
+ ```ruby
21
+ relying_party = WebAuthn::RelyingParty.new(
22
+ # This value needs to match `window.location.origin` evaluated by
23
+ # the User Agent during registration and authentication ceremonies.
24
+ origin: "https://admin.example.com"
25
+
26
+ # Relying Party name for display purposes
27
+ name: "Admin Site for Example Inc."
28
+
29
+ # Optionally configure a client timeout hint, in milliseconds.
30
+ # This hint specifies how long the browser should wait for any
31
+ # interaction with the user.
32
+ # This hint may be overridden by the browser.
33
+ # https://www.w3.org/TR/webauthn/#dom-publickeycredentialcreationoptions-timeout
34
+ # credential_options_timeout: 120_000
35
+
36
+ # You can optionally specify a different Relying Party ID
37
+ # (https://www.w3.org/TR/webauthn/#relying-party-identifier)
38
+ # if it differs from the default one.
39
+ #
40
+ # In this case the default would be "admin.example.com", but you can set it to
41
+ # the suffix "example.com"
42
+ #
43
+ # rp_id: "example.com"
44
+
45
+ # Configure preferred binary-to-text encoding scheme. This should match the encoding scheme
46
+ # used in your client-side (user agent) code before sending the credential to the server.
47
+ # Supported values: `:base64url` (default), `:base64` or `false` to disable all encoding.
48
+ #
49
+ # encoding: :base64url
50
+
51
+ # Possible values: "ES256", "ES384", "ES512", "PS256", "PS384", "PS512", "RS256", "RS384", "RS512", "RS1"
52
+ # Default: ["ES256", "PS256", "RS256"]
53
+ #
54
+ # algorithms: ["ES384"]
55
+ )
56
+ ```
57
+
58
+ ## Instance Based API
59
+
60
+ **DISCLAIMER: This API was released on version 3.0.0.alpha1 and is still under evaluation. Although it has been throughly tested and it is fully functional it might be changed until the final release of version 3.0.0.**
61
+
62
+ The explanation for each ceremony can be found in depth in [Credential Registration](../README.md#credential-registration) and [Credential Authentication](../README.md#credential-authentication) but if you choose this instance based approach to define your WebAuthn configurations and assuming `relying_party` is the result of an instance you get through `WebAuthn::RelytingParty.new(...)` the code in those explanations needs to be updated to:
63
+
64
+ ### Credential Registration
65
+
66
+ #### Initiation phase
67
+
68
+ ```ruby
69
+ # Generate and store the WebAuthn User ID the first time the user registers a credential
70
+ if !user.webauthn_id
71
+ user.update!(webauthn_id: WebAuthn.generate_user_id)
72
+ end
73
+
74
+ options = relying_party.options_for_create(
75
+ user: { id: user.webauthn_id, name: user.name },
76
+ exclude: user.credentials.map { |c| c.webauthn_id }
77
+ )
78
+
79
+ # Store the newly generated challenge somewhere so you can have it
80
+ # for the verification phase.
81
+ session[:creation_challenge] = options.challenge
82
+
83
+ # Send `options` back to the browser, so that they can be used
84
+ # to call `navigator.credentials.create({ "publicKey": options })`
85
+ #
86
+ # You can call `options.as_json` to get a ruby hash with a JSON representation if needed.
87
+
88
+ # If inside a Rails controller, `render json: options` will just work.
89
+ # I.e. it will encode and convert the options to JSON automatically.
90
+
91
+ # For your frontend code, you might find @github/webauthn-json npm package useful.
92
+ # Especially for handling the necessary decoding of the options, and sending the
93
+ # `PublicKeyCredential` object back to the server.
94
+ ```
95
+
96
+ #### Verification phase
97
+
98
+ ```ruby
99
+ # Assuming you're using @github/webauthn-json package to send the `PublicKeyCredential` object back
100
+ # in params[:publicKeyCredential]:
101
+ begin
102
+ webauthn_credential = relying_party.verify_registration(
103
+ params[:publicKeyCredential],
104
+ params[:create_challenge]
105
+ )
106
+
107
+ # Store Credential ID, Credential Public Key and Sign Count for future authentications
108
+ user.credentials.create!(
109
+ webauthn_id: webauthn_credential.id,
110
+ public_key: webauthn_credential.public_key,
111
+ sign_count: webauthn_credential.sign_count
112
+ )
113
+ rescue WebAuthn::Error => e
114
+ # Handle error
115
+ end
116
+ ```
117
+
118
+ ### Credential Authentication
119
+
120
+ #### Initiation phase
121
+
122
+ ```ruby
123
+ options = relying_party.options_for_get(allow: user.credentials.map { |c| c.webauthn_id })
124
+
125
+ # Store the newly generated challenge somewhere so you can have it
126
+ # for the verification phase.
127
+ session[:authentication_challenge] = options.challenge
128
+
129
+ # Send `options` back to the browser, so that they can be used
130
+ # to call `navigator.credentials.get({ "publicKey": options })`
131
+
132
+ # You can call `options.as_json` to get a ruby hash with a JSON representation if needed.
133
+
134
+ # If inside a Rails controller, `render json: options` will just work.
135
+ # I.e. it will encode and convert the options to JSON automatically.
136
+
137
+ # For your frontend code, you might find @github/webauthn-json npm package useful.
138
+ # Especially for handling the necessary decoding of the options, and sending the
139
+ # `PublicKeyCredential` object back to the server.
140
+ ```
141
+
142
+ #### Verification phase
143
+
144
+ ```ruby
145
+ begin
146
+ # Assuming you're using @github/webauthn-json package to send the `PublicKeyCredential` object back
147
+ # in params[:publicKeyCredential]:
148
+ webauthn_credential, stored_credential = relying_party.verify_authentication(
149
+ params[:publicKeyCredential],
150
+ session[:authentication_challenge]
151
+ ) do
152
+ # the returned object needs to respond to #public_key and #sign_count
153
+ user.credentials.find_by(webauthn_id: webauthn_credential.id)
154
+ end
155
+
156
+ # Update the stored credential sign count with the value from `webauthn_credential.sign_count`
157
+ stored_credential.update!(sign_count: webauthn_credential.sign_count)
158
+
159
+ # Continue with successful sign in or 2FA verification...
160
+
161
+ rescue WebAuthn::SignCountVerificationError => e
162
+ # Cryptographic verification of the authenticator data succeeded, but the signature counter was less then or equal
163
+ # to the stored value. This can have several reasons and depending on your risk tolerance you can choose to fail or
164
+ # pass authentication. For more information see https://www.w3.org/TR/webauthn/#sign-counter
165
+ rescue WebAuthn::Error => e
166
+ # Handle error
167
+ end
168
+ ```
169
+
170
+ ## Moving from Global to Instance Based Configuration
171
+
172
+ Adding a configuration for a new instance does not mean you need to get rid of your Global configuration. They can co-exist in your application and be both available for the different usages you might have. `WebAuthn.configuration.relying_party` will always return the global one while `WebAuthn::RelyingParty.new`, executed anywhere in your codebase, will allow you to create a different instance as you see the need. They will not collide and instead operate in isolation without any shared state.
173
+
174
+ The gem API described in the current [Usage](../README.md#usage) section for the [Global Configuration](../README.md#configuration) approach will still valid but the [Instance Based API](#instance-based-api) also works with the global `relying_party` that is maintain globally at `WebAuthn.configuration.relying_party`.
@@ -82,7 +82,7 @@ During authentication verification phase, you must pass either the original AppI
82
82
 
83
83
  ```ruby
84
84
  assertion_response = WebAuthn::AuthenticatorAssertionResponse.new(
85
- credential_id: params[:id],
85
+ user_handle: params[:response][:userHandle],
86
86
  authenticator_data: params[:response][:authenticatorData],
87
87
  client_data_json: params[:response][:clientDataJSON],
88
88
  signature: params[:response][:signature],
@@ -90,7 +90,8 @@ assertion_response = WebAuthn::AuthenticatorAssertionResponse.new(
90
90
 
91
91
  assertion_response.verify(
92
92
  expected_challenge,
93
- allowed_credentials: [credential],
93
+ public_key: credential.public_key,
94
+ sign_count: credential.count,
94
95
  rp_id: params[:clientExtensionResults][:appid] ? domain.to_s : domain.host,
95
96
  )
96
97
  ```
@@ -20,10 +20,6 @@ module WebAuthn
20
20
 
21
21
  private
22
22
 
23
- def matching_public_key?(authenticator_data)
24
- attestation_certificate.public_key.to_der == authenticator_data.credential.public_key_object.to_der
25
- end
26
-
27
23
  def valid_attestation_challenge?(client_data_hash)
28
24
  android_key_attestation.verify_challenge(client_data_hash)
29
25
  rescue AndroidKeyAttestation::ChallengeMismatchError
@@ -16,10 +16,6 @@ module WebAuthn
16
16
  [attestation_type, attestation_trust_path]
17
17
  end
18
18
 
19
- def attestation_certificate
20
- attestation_trust_path.first
21
- end
22
-
23
19
  private
24
20
 
25
21
  def valid_response?(authenticator_data, client_data_hash)
@@ -52,7 +48,7 @@ module WebAuthn
52
48
  end
53
49
 
54
50
  # SafetyNetAttestation returns full chain including root, WebAuthn expects only the x5c certificates
55
- def attestation_trust_path
51
+ def certificates
56
52
  attestation_response.certificate_chain[0..-2]
57
53
  end
58
54
 
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "openssl"
4
+ require "webauthn/attestation_statement/base"
5
+
6
+ module WebAuthn
7
+ module AttestationStatement
8
+ class Apple < Base
9
+ # Source: https://www.apple.com/certificateauthority/private/
10
+ ROOT_CERTIFICATE =
11
+ OpenSSL::X509::Certificate.new(<<~PEM)
12
+ -----BEGIN CERTIFICATE-----
13
+ MIICEjCCAZmgAwIBAgIQaB0BbHo84wIlpQGUKEdXcTAKBggqhkjOPQQDAzBLMR8w
14
+ HQYDVQQDDBZBcHBsZSBXZWJBdXRobiBSb290IENBMRMwEQYDVQQKDApBcHBsZSBJ
15
+ bmMuMRMwEQYDVQQIDApDYWxpZm9ybmlhMB4XDTIwMDMxODE4MjEzMloXDTQ1MDMx
16
+ NTAwMDAwMFowSzEfMB0GA1UEAwwWQXBwbGUgV2ViQXV0aG4gUm9vdCBDQTETMBEG
17
+ A1UECgwKQXBwbGUgSW5jLjETMBEGA1UECAwKQ2FsaWZvcm5pYTB2MBAGByqGSM49
18
+ AgEGBSuBBAAiA2IABCJCQ2pTVhzjl4Wo6IhHtMSAzO2cv+H9DQKev3//fG59G11k
19
+ xu9eI0/7o6V5uShBpe1u6l6mS19S1FEh6yGljnZAJ+2GNP1mi/YK2kSXIuTHjxA/
20
+ pcoRf7XkOtO4o1qlcaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUJtdk
21
+ 2cV4wlpn0afeaxLQG2PxxtcwDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2cA
22
+ MGQCMFrZ+9DsJ1PW9hfNdBywZDsWDbWFp28it1d/5w2RPkRX3Bbn/UbDTNLx7Jr3
23
+ jAGGiQIwHFj+dJZYUJR786osByBelJYsVZd2GbHQu209b5RCmGQ21gpSAk9QZW4B
24
+ 1bWeT0vT
25
+ -----END CERTIFICATE-----
26
+ PEM
27
+
28
+ NONCE_EXTENSION_OID = "1.2.840.113635.100.8.2"
29
+
30
+ def valid?(authenticator_data, client_data_hash)
31
+ valid_nonce?(authenticator_data, client_data_hash) &&
32
+ matching_public_key?(authenticator_data) &&
33
+ trustworthy? &&
34
+ [attestation_type, attestation_trust_path]
35
+ end
36
+
37
+ private
38
+
39
+ def valid_nonce?(authenticator_data, client_data_hash)
40
+ extension = cred_cert&.find_extension(NONCE_EXTENSION_OID)
41
+
42
+ if extension
43
+ sequence = OpenSSL::ASN1.decode(extension.value_der)
44
+
45
+ sequence.tag == OpenSSL::ASN1::SEQUENCE &&
46
+ sequence.value.size == 1 &&
47
+ sequence.value[0].value[0].value ==
48
+ OpenSSL::Digest::SHA256.digest(authenticator_data.data + client_data_hash)
49
+ end
50
+ end
51
+
52
+ def attestation_type
53
+ WebAuthn::AttestationStatement::ATTESTATION_TYPE_ANONCA
54
+ end
55
+
56
+ def cred_cert
57
+ attestation_certificate
58
+ end
59
+
60
+ def default_root_certificates
61
+ [ROOT_CERTIFICATE]
62
+ end
63
+ end
64
+ end
65
+ end
@@ -16,11 +16,13 @@ module WebAuthn
16
16
  ATTESTATION_TYPE_SELF = "Self"
17
17
  ATTESTATION_TYPE_ATTCA = "AttCA"
18
18
  ATTESTATION_TYPE_BASIC_OR_ATTCA = "Basic_or_AttCA"
19
+ ATTESTATION_TYPE_ANONCA = "AnonCA"
19
20
 
20
21
  ATTESTATION_TYPES_WITH_ROOT = [
21
22
  ATTESTATION_TYPE_BASIC,
22
23
  ATTESTATION_TYPE_BASIC_OR_ATTCA,
23
- ATTESTATION_TYPE_ATTCA
24
+ ATTESTATION_TYPE_ATTCA,
25
+ ATTESTATION_TYPE_ANONCA
24
26
  ].freeze
25
27
 
26
28
  class Base
@@ -42,14 +44,8 @@ module WebAuthn
42
44
  certificates&.first
43
45
  end
44
46
 
45
- def certificate_chain
46
- if certificates
47
- certificates[1..-1]
48
- end
49
- end
50
-
51
47
  def attestation_certificate_key_id
52
- raw_subject_key_identifier&.unpack("H*")&.[](0)
48
+ attestation_certificate.subject_key_identifier&.unpack("H*")&.[](0)
53
49
  end
54
50
 
55
51
  private
@@ -57,17 +53,19 @@ module WebAuthn
57
53
  attr_reader :statement
58
54
 
59
55
  def matching_aaguid?(attested_credential_data_aaguid)
60
- extension = attestation_certificate&.extensions&.detect { |ext| ext.oid == AAGUID_EXTENSION_OID }
56
+ extension = attestation_certificate&.find_extension(AAGUID_EXTENSION_OID)
61
57
  if extension
62
- # `extension.value` mangles data into ASCII, so we must manually compare bytes
63
- # see https://github.com/ruby/openssl/pull/234
64
- extension.to_der[-WebAuthn::AuthenticatorData::AttestedCredentialData::AAGUID_LENGTH..-1] ==
65
- attested_credential_data_aaguid
58
+ aaguid_value = OpenSSL::ASN1.decode(extension.value_der).value
59
+ aaguid_value == attested_credential_data_aaguid
66
60
  else
67
61
  true
68
62
  end
69
63
  end
70
64
 
65
+ def matching_public_key?(authenticator_data)
66
+ attestation_certificate.public_key.to_der == authenticator_data.credential.public_key_object.to_der
67
+ end
68
+
71
69
  def certificates
72
70
  @certificates ||=
73
71
  raw_certificates&.map do |raw_certificate|
@@ -141,15 +139,6 @@ module WebAuthn
141
139
  end
142
140
  end
143
141
 
144
- def raw_subject_key_identifier
145
- extension = attestation_certificate.extensions.detect { |ext| ext.oid == "subjectKeyIdentifier" }
146
- return unless extension
147
-
148
- ext_asn1 = OpenSSL::ASN1.decode(extension.to_der)
149
- ext_value = ext_asn1.value.last
150
- OpenSSL::ASN1.decode(ext_value.value).value
151
- end
152
-
153
142
  def valid_signature?(authenticator_data, client_data_hash, public_key = attestation_certificate.public_key)
154
143
  raise("Incompatible algorithm and key") unless cose_algorithm.compatible_key?(public_key)
155
144
 
@@ -46,7 +46,7 @@ module WebAuthn
46
46
 
47
47
  attestation_certificate.version == 2 &&
48
48
  subject.assoc('OU')&.at(1) == "Authenticator Attestation" &&
49
- attestation_certificate.extensions.find { |ext| ext.oid == 'basicConstraints' }&.value == 'CA:FALSE'
49
+ attestation_certificate.find_extension('basicConstraints')&.value == 'CA:FALSE'
50
50
  else
51
51
  true
52
52
  end
@@ -42,7 +42,7 @@ module WebAuthn
42
42
  OpenSSL::Digest.digest(cose_algorithm.hash_function, certified_extra_data),
43
43
  signature_algorithm: tpm_algorithm[:signature],
44
44
  hash_algorithm: tpm_algorithm[:hash],
45
- root_certificates: root_certificates(aaguid: aaguid)
45
+ trusted_certificates: root_certificates(aaguid: aaguid)
46
46
  )
47
47
 
48
48
  key_attestation.valid? && key_attestation.key && key_attestation.key.to_pem == key.to_pem
@@ -54,7 +54,7 @@ module WebAuthn
54
54
  end
55
55
 
56
56
  def default_root_certificates
57
- ::TPM::KeyAttestation::ROOT_CERTIFICATES
57
+ ::TPM::KeyAttestation::TRUSTED_CERTIFICATES
58
58
  end
59
59
 
60
60
  def tpm_algorithm
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "webauthn/attestation_statement/android_key"
4
4
  require "webauthn/attestation_statement/android_safetynet"
5
+ require "webauthn/attestation_statement/apple"
5
6
  require "webauthn/attestation_statement/fido_u2f"
6
7
  require "webauthn/attestation_statement/none"
7
8
  require "webauthn/attestation_statement/packed"
@@ -18,6 +19,7 @@ module WebAuthn
18
19
  ATTESTATION_FORMAT_ANDROID_SAFETYNET = "android-safetynet"
19
20
  ATTESTATION_FORMAT_ANDROID_KEY = "android-key"
20
21
  ATTESTATION_FORMAT_TPM = "tpm"
22
+ ATTESTATION_FORMAT_APPLE = "apple"
21
23
 
22
24
  FORMAT_TO_CLASS = {
23
25
  ATTESTATION_FORMAT_NONE => WebAuthn::AttestationStatement::None,
@@ -25,7 +27,8 @@ module WebAuthn
25
27
  ATTESTATION_FORMAT_PACKED => WebAuthn::AttestationStatement::Packed,
26
28
  ATTESTATION_FORMAT_ANDROID_SAFETYNET => WebAuthn::AttestationStatement::AndroidSafetynet,
27
29
  ATTESTATION_FORMAT_ANDROID_KEY => WebAuthn::AttestationStatement::AndroidKey,
28
- ATTESTATION_FORMAT_TPM => WebAuthn::AttestationStatement::TPM
30
+ ATTESTATION_FORMAT_TPM => WebAuthn::AttestationStatement::TPM,
31
+ ATTESTATION_FORMAT_APPLE => WebAuthn::AttestationStatement::Apple
29
32
  }.freeze
30
33
 
31
34
  def self.from(format, statement)
@@ -3,7 +3,6 @@
3
3
  require "webauthn/authenticator_data"
4
4
  require "webauthn/client_data"
5
5
  require "webauthn/error"
6
- require "webauthn/security_utils"
7
6
 
8
7
  module WebAuthn
9
8
  TYPES = { create: "webauthn.create", get: "webauthn.get" }.freeze
@@ -79,7 +78,7 @@ module WebAuthn
79
78
  end
80
79
 
81
80
  def valid_challenge?(expected_challenge)
82
- WebAuthn::SecurityUtils.secure_compare(client_data.challenge, expected_challenge)
81
+ OpenSSL.secure_compare(client_data.challenge, expected_challenge)
83
82
  end
84
83
 
85
84
  def valid_origin?(expected_origin)
@@ -16,11 +16,7 @@ module WebAuthn
16
16
  class RootCertificateFinderNotSupportedError < Error; end
17
17
 
18
18
  class Configuration
19
- def self.if_pss_supported(algorithm)
20
- OpenSSL::PKey::RSA.instance_methods.include?(:verify_pss) ? algorithm : nil
21
- end
22
-
23
- DEFAULT_ALGORITHMS = ["ES256", if_pss_supported("PS256"), "RS256"].compact.freeze
19
+ DEFAULT_ALGORITHMS = ["ES256", "PS256", "RS256"].compact.freeze
24
20
 
25
21
  attr_accessor :algorithms
26
22
  attr_accessor :encoding
@@ -39,7 +35,7 @@ module WebAuthn
39
35
  @verify_attestation_statement = true
40
36
  @credential_options_timeout = 120000
41
37
  @silent_authentication = false
42
- @acceptable_attestation_types = ['None', 'Self', 'Basic', 'AttCA', 'Basic_or_AttCA']
38
+ @acceptable_attestation_types = ['None', 'Self', 'Basic', 'AttCA', 'Basic_or_AttCA', 'AnonCA']
43
39
  @attestation_root_certificates_finders = []
44
40
  end
45
41
 
@@ -15,7 +15,7 @@ module WebAuthn
15
15
  rp_id_hash:,
16
16
  credential: {
17
17
  id: SecureRandom.random_bytes(16),
18
- public_key: OpenSSL::PKey::EC.new("prime256v1").generate_key.public_key
18
+ public_key: OpenSSL::PKey::EC.generate("prime256v1").public_key
19
19
  },
20
20
  sign_count: 0,
21
21
  user_present: true,
@@ -50,12 +50,20 @@ module WebAuthn
50
50
  user_verified: false,
51
51
  aaguid: AuthenticatorData::AAGUID,
52
52
  sign_count: nil,
53
- extensions: nil
53
+ extensions: nil,
54
+ allow_credentials: nil
54
55
  )
55
56
  credential_options = credentials[rp_id]
56
57
 
57
58
  if credential_options
58
- credential_id, credential = credential_options.first
59
+ allow_credentials ||= credential_options.keys
60
+ credential_id = (credential_options.keys & allow_credentials).first
61
+ unless credential_id
62
+ raise "No matching credentials (allowed=#{allow_credentials}) " \
63
+ "found for RP #{rp_id} among credentials=#{credential_options}"
64
+ end
65
+
66
+ credential = credential_options[credential_id]
59
67
  credential_key = credential[:credential_key]
60
68
  credential_sign_count = credential[:sign_count]
61
69
 
@@ -87,7 +95,7 @@ module WebAuthn
87
95
  attr_reader :credentials
88
96
 
89
97
  def new_credential
90
- [SecureRandom.random_bytes(16), OpenSSL::PKey::EC.new("prime256v1").generate_key, 0]
98
+ [SecureRandom.random_bytes(16), OpenSSL::PKey::EC.generate("prime256v1"), 0]
91
99
  end
92
100
 
93
101
  def hashed(target)
@@ -74,19 +74,25 @@ module WebAuthn
74
74
  user_verified: false,
75
75
  sign_count: nil,
76
76
  extensions: nil,
77
- user_handle: nil)
77
+ user_handle: nil,
78
+ allow_credentials: nil)
78
79
  rp_id ||= URI.parse(origin).host
79
80
 
80
81
  client_data_json = data_json_for(:get, encoder.decode(challenge))
81
82
  client_data_hash = hashed(client_data_json)
82
83
 
84
+ if allow_credentials
85
+ allow_credentials = allow_credentials.map { |credential| encoder.decode(credential) }
86
+ end
87
+
83
88
  assertion = authenticator.get_assertion(
84
89
  rp_id: rp_id,
85
90
  client_data_hash: client_data_hash,
86
91
  user_present: user_present,
87
92
  user_verified: user_verified,
88
93
  sign_count: sign_count,
89
- extensions: extensions
94
+ extensions: extensions,
95
+ allow_credentials: allow_credentials
90
96
  )
91
97
 
92
98
  {
@@ -5,11 +5,10 @@ require "awrence"
5
5
  module WebAuthn
6
6
  class PublicKeyCredential
7
7
  class Entity
8
- attr_reader :name, :icon
8
+ attr_reader :name
9
9
 
10
- def initialize(name:, icon: nil)
10
+ def initialize(name:)
11
11
  @name = name
12
- @icon = icon
13
12
  end
14
13
 
15
14
  def as_json
@@ -37,7 +36,7 @@ module WebAuthn
37
36
  end
38
37
 
39
38
  def attributes
40
- [:name, :icon]
39
+ [:name]
41
40
  end
42
41
  end
43
42
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module WebAuthn
4
- VERSION = "2.4.1"
4
+ VERSION = "2.5.2"
5
5
  end
data/webauthn.gemspec CHANGED
@@ -38,16 +38,15 @@ Gem::Specification.new do |spec|
38
38
  spec.add_dependency "bindata", "~> 2.4"
39
39
  spec.add_dependency "cbor", "~> 0.5.9"
40
40
  spec.add_dependency "cose", "~> 1.1"
41
- spec.add_dependency "openssl", "~> 2.0"
41
+ spec.add_dependency "openssl", ">= 2.2", "< 3.1"
42
42
  spec.add_dependency "safety_net_attestation", "~> 0.4.0"
43
- spec.add_dependency "securecompare", "~> 1.0"
44
- spec.add_dependency "tpm-key_attestation", "~> 0.10.0"
43
+ spec.add_dependency "tpm-key_attestation", "~> 0.11.0"
45
44
 
46
- spec.add_development_dependency "appraisal", "~> 2.3.0"
47
45
  spec.add_development_dependency "bundler", ">= 1.17", "< 3.0"
48
46
  spec.add_development_dependency "byebug", "~> 11.0"
49
47
  spec.add_development_dependency "rake", "~> 13.0"
50
48
  spec.add_development_dependency "rspec", "~> 3.8"
51
- spec.add_development_dependency "rubocop", "0.89"
52
- spec.add_development_dependency "rubocop-rspec", "~> 1.38.1"
49
+ spec.add_development_dependency "rubocop", "~> 1.9.1"
50
+ spec.add_development_dependency "rubocop-rake", "~> 0.5.1"
51
+ spec.add_development_dependency "rubocop-rspec", "~> 2.2.0"
53
52
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: webauthn
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.1
4
+ version: 2.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gonzalo Rodriguez
8
8
  - Braulio Martinez
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2021-02-15 00:00:00.000000000 Z
12
+ date: 2022-07-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: android_key_attestation
@@ -85,16 +85,22 @@ dependencies:
85
85
  name: openssl
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - "~>"
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '2.2'
91
+ - - "<"
89
92
  - !ruby/object:Gem::Version
90
- version: '2.0'
93
+ version: '3.1'
91
94
  type: :runtime
92
95
  prerelease: false
93
96
  version_requirements: !ruby/object:Gem::Requirement
94
97
  requirements:
95
- - - "~>"
98
+ - - ">="
96
99
  - !ruby/object:Gem::Version
97
- version: '2.0'
100
+ version: '2.2'
101
+ - - "<"
102
+ - !ruby/object:Gem::Version
103
+ version: '3.1'
98
104
  - !ruby/object:Gem::Dependency
99
105
  name: safety_net_attestation
100
106
  requirement: !ruby/object:Gem::Requirement
@@ -109,48 +115,20 @@ dependencies:
109
115
  - - "~>"
110
116
  - !ruby/object:Gem::Version
111
117
  version: 0.4.0
112
- - !ruby/object:Gem::Dependency
113
- name: securecompare
114
- requirement: !ruby/object:Gem::Requirement
115
- requirements:
116
- - - "~>"
117
- - !ruby/object:Gem::Version
118
- version: '1.0'
119
- type: :runtime
120
- prerelease: false
121
- version_requirements: !ruby/object:Gem::Requirement
122
- requirements:
123
- - - "~>"
124
- - !ruby/object:Gem::Version
125
- version: '1.0'
126
118
  - !ruby/object:Gem::Dependency
127
119
  name: tpm-key_attestation
128
120
  requirement: !ruby/object:Gem::Requirement
129
121
  requirements:
130
122
  - - "~>"
131
123
  - !ruby/object:Gem::Version
132
- version: 0.10.0
124
+ version: 0.11.0
133
125
  type: :runtime
134
126
  prerelease: false
135
127
  version_requirements: !ruby/object:Gem::Requirement
136
128
  requirements:
137
129
  - - "~>"
138
130
  - !ruby/object:Gem::Version
139
- version: 0.10.0
140
- - !ruby/object:Gem::Dependency
141
- name: appraisal
142
- requirement: !ruby/object:Gem::Requirement
143
- requirements:
144
- - - "~>"
145
- - !ruby/object:Gem::Version
146
- version: 2.3.0
147
- type: :development
148
- prerelease: false
149
- version_requirements: !ruby/object:Gem::Requirement
150
- requirements:
151
- - - "~>"
152
- - !ruby/object:Gem::Version
153
- version: 2.3.0
131
+ version: 0.11.0
154
132
  - !ruby/object:Gem::Dependency
155
133
  name: bundler
156
134
  requirement: !ruby/object:Gem::Requirement
@@ -217,30 +195,44 @@ dependencies:
217
195
  name: rubocop
218
196
  requirement: !ruby/object:Gem::Requirement
219
197
  requirements:
220
- - - '='
198
+ - - "~>"
221
199
  - !ruby/object:Gem::Version
222
- version: '0.89'
200
+ version: 1.9.1
223
201
  type: :development
224
202
  prerelease: false
225
203
  version_requirements: !ruby/object:Gem::Requirement
226
204
  requirements:
227
- - - '='
205
+ - - "~>"
206
+ - !ruby/object:Gem::Version
207
+ version: 1.9.1
208
+ - !ruby/object:Gem::Dependency
209
+ name: rubocop-rake
210
+ requirement: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - "~>"
213
+ - !ruby/object:Gem::Version
214
+ version: 0.5.1
215
+ type: :development
216
+ prerelease: false
217
+ version_requirements: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - "~>"
228
220
  - !ruby/object:Gem::Version
229
- version: '0.89'
221
+ version: 0.5.1
230
222
  - !ruby/object:Gem::Dependency
231
223
  name: rubocop-rspec
232
224
  requirement: !ruby/object:Gem::Requirement
233
225
  requirements:
234
226
  - - "~>"
235
227
  - !ruby/object:Gem::Version
236
- version: 1.38.1
228
+ version: 2.2.0
237
229
  type: :development
238
230
  prerelease: false
239
231
  version_requirements: !ruby/object:Gem::Requirement
240
232
  requirements:
241
233
  - - "~>"
242
234
  - !ruby/object:Gem::Version
243
- version: 1.38.1
235
+ version: 2.2.0
244
236
  description: |-
245
237
  WebAuthn ruby server library ― Make your application a W3C Web Authentication conformant
246
238
  Relying Party and allow your users to authenticate with U2F and FIDO2 authenticators.
@@ -251,11 +243,11 @@ executables: []
251
243
  extensions: []
252
244
  extra_rdoc_files: []
253
245
  files:
246
+ - ".github/workflows/build.yml"
247
+ - ".github/workflows/git.yml"
254
248
  - ".gitignore"
255
249
  - ".rspec"
256
250
  - ".rubocop.yml"
257
- - ".travis.yml"
258
- - Appraisals
259
251
  - CHANGELOG.md
260
252
  - CONTRIBUTING.md
261
253
  - Gemfile
@@ -265,18 +257,15 @@ files:
265
257
  - SECURITY.md
266
258
  - bin/console
267
259
  - bin/setup
260
+ - docs/advanced_configuration.md
268
261
  - docs/u2f_migration.md
269
- - gemfiles/cose_head.gemfile
270
- - gemfiles/openssl_2_0.gemfile
271
- - gemfiles/openssl_2_1.gemfile
272
- - gemfiles/openssl_2_2.gemfile
273
- - gemfiles/openssl_head.gemfile
274
262
  - lib/cose/rsapkcs1_algorithm.rb
275
263
  - lib/webauthn.rb
276
264
  - lib/webauthn/attestation_object.rb
277
265
  - lib/webauthn/attestation_statement.rb
278
266
  - lib/webauthn/attestation_statement/android_key.rb
279
267
  - lib/webauthn/attestation_statement/android_safetynet.rb
268
+ - lib/webauthn/attestation_statement/apple.rb
280
269
  - lib/webauthn/attestation_statement/base.rb
281
270
  - lib/webauthn/attestation_statement/fido_u2f.rb
282
271
  - lib/webauthn/attestation_statement/fido_u2f/public_key.rb
@@ -313,11 +302,8 @@ files:
313
302
  - lib/webauthn/public_key_credential/user_entity.rb
314
303
  - lib/webauthn/public_key_credential_with_assertion.rb
315
304
  - lib/webauthn/public_key_credential_with_attestation.rb
316
- - lib/webauthn/security_utils.rb
317
305
  - lib/webauthn/u2f_migrator.rb
318
306
  - lib/webauthn/version.rb
319
- - script/ci/install-openssl
320
- - script/ci/install-ruby
321
307
  - webauthn.gemspec
322
308
  homepage: https://github.com/cedarcode/webauthn-ruby
323
309
  licenses:
@@ -326,7 +312,7 @@ metadata:
326
312
  bug_tracker_uri: https://github.com/cedarcode/webauthn-ruby/issues
327
313
  changelog_uri: https://github.com/cedarcode/webauthn-ruby/blob/master/CHANGELOG.md
328
314
  source_code_uri: https://github.com/cedarcode/webauthn-ruby
329
- post_install_message:
315
+ post_install_message:
330
316
  rdoc_options: []
331
317
  require_paths:
332
318
  - lib
@@ -341,8 +327,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
341
327
  - !ruby/object:Gem::Version
342
328
  version: '0'
343
329
  requirements: []
344
- rubygems_version: 3.2.8
345
- signing_key:
330
+ rubygems_version: 3.2.32
331
+ signing_key:
346
332
  specification_version: 4
347
333
  summary: WebAuthn ruby server library
348
334
  test_files: []
data/.travis.yml DELETED
@@ -1,39 +0,0 @@
1
- dist: bionic
2
- language: ruby
3
-
4
- cache:
5
- bundler: true
6
- directories:
7
- - /home/travis/.rvm/
8
-
9
- env:
10
- - LIBSSL=1.1 RB=2.7.1
11
- - LIBSSL=1.1 RB=2.6.6
12
- - LIBSSL=1.1 RB=2.5.8
13
- - LIBSSL=1.1 RB=2.4.10
14
- - LIBSSL=1.1 RB=ruby-head
15
- - LIBSSL=1.0 RB=2.7.1
16
- - LIBSSL=1.0 RB=2.6.6
17
- - LIBSSL=1.0 RB=2.5.8
18
- - LIBSSL=1.0 RB=2.4.10
19
- - LIBSSL=1.0 RB=ruby-head
20
-
21
- gemfile:
22
- - gemfiles/cose_head.gemfile
23
- - gemfiles/openssl_head.gemfile
24
- - gemfiles/openssl_2_2.gemfile
25
- - gemfiles/openssl_2_1.gemfile
26
- - gemfiles/openssl_2_0.gemfile
27
-
28
- matrix:
29
- fast_finish: true
30
- allow_failures:
31
- - env: LIBSSL=1.1 RB=ruby-head
32
- - env: LIBSSL=1.0 RB=ruby-head
33
- - gemfile: gemfiles/cose_head.gemfile
34
- - gemfile: gemfiles/openssl_head.gemfile
35
-
36
- before_install:
37
- - ./script/ci/install-openssl
38
- - ./script/ci/install-ruby
39
- - gem install bundler -v "~> 2.0"
data/Appraisals DELETED
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- appraise "cose_head" do
4
- gem "cose", git: "https://github.com/cedarcode/cose-ruby"
5
- end
6
-
7
- appraise "openssl_head" do
8
- gem "openssl", git: "https://github.com/ruby/openssl"
9
- end
10
-
11
- appraise "openssl_2_2" do
12
- gem "openssl", "~> 2.2.0"
13
- end
14
-
15
- appraise "openssl_2_1" do
16
- gem "openssl", "~> 2.1.0"
17
- end
18
-
19
- appraise "openssl_2_0" do
20
- gem "openssl", "~> 2.0.0"
21
- end
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "cose", git: "https://github.com/cedarcode/cose-ruby"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "openssl", "~> 2.0.0"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "openssl", "~> 2.1.0"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "openssl", "~> 2.2.0"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "openssl", git: "https://github.com/ruby/openssl"
6
-
7
- gemspec path: "../"
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "securecompare"
4
-
5
- module WebAuthn
6
- module SecurityUtils
7
- # Constant time string comparison, for variable length strings.
8
- # This code was adapted from Rails ActiveSupport::SecurityUtils
9
- #
10
- # The values are first processed by SHA256, so that we don't leak length info
11
- # via timing attacks.
12
- def secure_compare(first_string, second_string)
13
- first_string_sha256 = ::Digest::SHA256.digest(first_string)
14
- second_string_sha256 = ::Digest::SHA256.digest(second_string)
15
-
16
- SecureCompare.compare(first_string_sha256, second_string_sha256) && first_string == second_string
17
- end
18
- module_function :secure_compare
19
- end
20
- end
@@ -1,7 +0,0 @@
1
- #!/bin/bash
2
-
3
- set -e
4
-
5
- if [[ "$LIBSSL" == "1.0" ]]; then
6
- sudo apt-get install libssl1.0-dev
7
- fi
@@ -1,13 +0,0 @@
1
- #!/bin/bash
2
-
3
- set -e
4
-
5
- source "$HOME/.rvm/scripts/rvm"
6
-
7
- if [[ "$LIBSSL" == "1.0" ]]; then
8
- rvm use --install $RB --autolibs=read-only --disable-binary
9
- elif [[ "$LIBSSL" == "1.1" ]]; then
10
- rvm use --install $RB --binary --fuzzy
11
- fi
12
-
13
- [[ "`ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION'`" =~ "OpenSSL $LIBSSL" ]] || { echo "Wrong libssl version"; exit 1; }