webauthn 2.1.0 → 2.4.1
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 +4 -4
- data/.rubocop.yml +113 -13
- data/.travis.yml +21 -18
- data/Appraisals +4 -0
- data/CHANGELOG.md +41 -0
- data/CONTRIBUTING.md +0 -5
- data/README.md +70 -8
- data/SECURITY.md +6 -4
- data/gemfiles/openssl_2_2.gemfile +7 -0
- data/lib/cose/rsapkcs1_algorithm.rb +50 -0
- data/lib/webauthn/attestation_object.rb +43 -0
- data/lib/webauthn/attestation_statement.rb +20 -20
- data/lib/webauthn/attestation_statement/android_key.rb +28 -30
- data/lib/webauthn/attestation_statement/android_safetynet.rb +27 -7
- data/lib/webauthn/attestation_statement/base.rb +108 -10
- data/lib/webauthn/attestation_statement/fido_u2f.rb +8 -6
- data/lib/webauthn/attestation_statement/none.rb +7 -1
- data/lib/webauthn/attestation_statement/packed.rb +13 -41
- data/lib/webauthn/attestation_statement/tpm.rb +38 -75
- data/lib/webauthn/authenticator_assertion_response.rb +3 -7
- data/lib/webauthn/authenticator_attestation_response.rb +19 -84
- data/lib/webauthn/authenticator_data.rb +51 -51
- data/lib/webauthn/authenticator_data/attested_credential_data.rb +29 -50
- data/lib/webauthn/authenticator_response.rb +3 -0
- data/lib/webauthn/credential_creation_options.rb +2 -0
- data/lib/webauthn/credential_request_options.rb +2 -0
- data/lib/webauthn/fake_authenticator.rb +7 -3
- data/lib/webauthn/fake_authenticator/attestation_object.rb +7 -3
- data/lib/webauthn/fake_authenticator/authenticator_data.rb +2 -4
- data/lib/webauthn/fake_client.rb +19 -5
- data/lib/webauthn/public_key.rb +21 -2
- data/lib/webauthn/public_key_credential.rb +13 -3
- data/lib/webauthn/u2f_migrator.rb +5 -4
- data/lib/webauthn/version.rb +1 -1
- data/script/ci/install-openssl +7 -0
- data/script/ci/install-ruby +13 -0
- data/webauthn.gemspec +13 -9
- metadata +54 -41
- data/lib/android_safetynet/attestation_response.rb +0 -116
- data/lib/cose/rsassa_algorithm.rb +0 -10
- data/lib/tpm/constants.rb +0 -44
- data/lib/tpm/s_attest.rb +0 -26
- data/lib/tpm/s_attest/s_certify_info.rb +0 -14
- data/lib/tpm/sized_buffer.rb +0 -13
- data/lib/tpm/t_public.rb +0 -32
- data/lib/tpm/t_public/s_ecc_parms.rb +0 -17
- data/lib/tpm/t_public/s_rsa_parms.rb +0 -17
- data/lib/webauthn/attestation_statement/android_key/authorization_list.rb +0 -39
- data/lib/webauthn/attestation_statement/android_key/key_description.rb +0 -37
- data/lib/webauthn/attestation_statement/tpm/cert_info.rb +0 -44
- data/lib/webauthn/attestation_statement/tpm/pub_area.rb +0 -85
- data/lib/webauthn/signature_verifier.rb +0 -77
    
        data/lib/webauthn/public_key.rb
    CHANGED
    
    | @@ -1,11 +1,15 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            require "webauthn/attestation_statement/fido_u2f/public_key"
         | 
| 4 | 
            -
            require "cose/key"
         | 
| 5 3 | 
             
            require "cose/algorithm"
         | 
| 4 | 
            +
            require "cose/error"
         | 
| 5 | 
            +
            require "cose/key"
         | 
| 6 | 
            +
            require "cose/rsapkcs1_algorithm"
         | 
| 7 | 
            +
            require "webauthn/attestation_statement/fido_u2f/public_key"
         | 
| 6 8 |  | 
| 7 9 | 
             
            module WebAuthn
         | 
| 8 10 | 
             
              class PublicKey
         | 
| 11 | 
            +
                class UnsupportedAlgorithm < Error; end
         | 
| 12 | 
            +
             | 
| 9 13 | 
             
                def self.deserialize(public_key)
         | 
| 10 14 | 
             
                  cose_key =
         | 
| 11 15 | 
             
                    if WebAuthn::AttestationStatement::FidoU2f::PublicKey.uncompressed_point?(public_key)
         | 
| @@ -45,5 +49,20 @@ module WebAuthn | |
| 45 49 | 
             
                def alg
         | 
| 46 50 | 
             
                  @cose_key.alg
         | 
| 47 51 | 
             
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                def verify(signature, verification_data)
         | 
| 54 | 
            +
                  cose_algorithm.verify(pkey, signature, verification_data)
         | 
| 55 | 
            +
                rescue COSE::Error
         | 
| 56 | 
            +
                  false
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                private
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                def cose_algorithm
         | 
| 62 | 
            +
                  @cose_algorithm ||= COSE::Algorithm.find(alg) || raise(
         | 
| 63 | 
            +
                    UnsupportedAlgorithm,
         | 
| 64 | 
            +
                    "The public key algorithm #{alg} is not among the available COSE algorithms"
         | 
| 65 | 
            +
                  )
         | 
| 66 | 
            +
                end
         | 
| 48 67 | 
             
              end
         | 
| 49 68 | 
             
            end
         | 
| @@ -4,21 +4,23 @@ require "webauthn/encoder" | |
| 4 4 |  | 
| 5 5 | 
             
            module WebAuthn
         | 
| 6 6 | 
             
              class PublicKeyCredential
         | 
| 7 | 
            -
                attr_reader :type, :id, :raw_id, :response
         | 
| 7 | 
            +
                attr_reader :type, :id, :raw_id, :client_extension_outputs, :response
         | 
| 8 8 |  | 
| 9 9 | 
             
                def self.from_client(credential)
         | 
| 10 10 | 
             
                  new(
         | 
| 11 11 | 
             
                    type: credential["type"],
         | 
| 12 12 | 
             
                    id: credential["id"],
         | 
| 13 13 | 
             
                    raw_id: WebAuthn.configuration.encoder.decode(credential["rawId"]),
         | 
| 14 | 
            +
                    client_extension_outputs: credential["clientExtensionResults"],
         | 
| 14 15 | 
             
                    response: response_class.from_client(credential["response"])
         | 
| 15 16 | 
             
                  )
         | 
| 16 17 | 
             
                end
         | 
| 17 18 |  | 
| 18 | 
            -
                def initialize(type:, id:, raw_id:, response:)
         | 
| 19 | 
            +
                def initialize(type:, id:, raw_id:, client_extension_outputs: {}, response:)
         | 
| 19 20 | 
             
                  @type = type
         | 
| 20 21 | 
             
                  @id = id
         | 
| 21 22 | 
             
                  @raw_id = raw_id
         | 
| 23 | 
            +
                  @client_extension_outputs = client_extension_outputs
         | 
| 22 24 | 
             
                  @response = response
         | 
| 23 25 | 
             
                end
         | 
| 24 26 |  | 
| @@ -30,7 +32,11 @@ module WebAuthn | |
| 30 32 | 
             
                end
         | 
| 31 33 |  | 
| 32 34 | 
             
                def sign_count
         | 
| 33 | 
            -
                   | 
| 35 | 
            +
                  authenticator_data&.sign_count
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                def authenticator_extension_outputs
         | 
| 39 | 
            +
                  authenticator_data.extension_data if authenticator_data&.extension_data_included?
         | 
| 34 40 | 
             
                end
         | 
| 35 41 |  | 
| 36 42 | 
             
                private
         | 
| @@ -43,6 +49,10 @@ module WebAuthn | |
| 43 49 | 
             
                  raw_id && id && raw_id == WebAuthn.standard_encoder.decode(id)
         | 
| 44 50 | 
             
                end
         | 
| 45 51 |  | 
| 52 | 
            +
                def authenticator_data
         | 
| 53 | 
            +
                  response&.authenticator_data
         | 
| 54 | 
            +
                end
         | 
| 55 | 
            +
             | 
| 46 56 | 
             
                def encoder
         | 
| 47 57 | 
             
                  WebAuthn.configuration.encoder
         | 
| 48 58 | 
             
                end
         | 
| @@ -28,10 +28,11 @@ module WebAuthn | |
| 28 28 | 
             
                end
         | 
| 29 29 |  | 
| 30 30 | 
             
                def credential
         | 
| 31 | 
            -
                  @credential ||= | 
| 32 | 
            -
                     | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 31 | 
            +
                  @credential ||=
         | 
| 32 | 
            +
                    begin
         | 
| 33 | 
            +
                      hash = authenticator_data.send(:credential)
         | 
| 34 | 
            +
                      WebAuthn::AuthenticatorData::AttestedCredentialData::Credential.new(hash[:id], hash[:public_key].serialize)
         | 
| 35 | 
            +
                    end
         | 
| 35 36 | 
             
                end
         | 
| 36 37 |  | 
| 37 38 | 
             
                def attestation_type
         | 
    
        data/lib/webauthn/version.rb
    CHANGED
    
    
| @@ -0,0 +1,13 @@ | |
| 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; }
         | 
    
        data/webauthn.gemspec
    CHANGED
    
    | @@ -22,28 +22,32 @@ Gem::Specification.new do |spec| | |
| 22 22 | 
             
                "source_code_uri" => "https://github.com/cedarcode/webauthn-ruby"
         | 
| 23 23 | 
             
              }
         | 
| 24 24 |  | 
| 25 | 
            -
              spec.files = | 
| 26 | 
            -
                 | 
| 27 | 
            -
             | 
| 25 | 
            +
              spec.files =
         | 
| 26 | 
            +
                `git ls-files -z`.split("\x0").reject do |f|
         | 
| 27 | 
            +
                  f.match(%r{^(test|spec|features|assets)/})
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 28 30 | 
             
              spec.bindir        = "exe"
         | 
| 29 31 | 
             
              spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
         | 
| 30 32 | 
             
              spec.require_paths = ["lib"]
         | 
| 31 33 |  | 
| 32 | 
            -
              spec.required_ruby_version = ">= 2. | 
| 34 | 
            +
              spec.required_ruby_version = ">= 2.4"
         | 
| 33 35 |  | 
| 36 | 
            +
              spec.add_dependency "android_key_attestation", "~> 0.3.0"
         | 
| 34 37 | 
             
              spec.add_dependency "awrence", "~> 1.1"
         | 
| 35 38 | 
             
              spec.add_dependency "bindata", "~> 2.4"
         | 
| 36 39 | 
             
              spec.add_dependency "cbor", "~> 0.5.9"
         | 
| 37 | 
            -
              spec.add_dependency "cose", "~>  | 
| 38 | 
            -
              spec.add_dependency "jwt", [">= 1.5", "< 3.0"]
         | 
| 40 | 
            +
              spec.add_dependency "cose", "~> 1.1"
         | 
| 39 41 | 
             
              spec.add_dependency "openssl", "~> 2.0"
         | 
| 42 | 
            +
              spec.add_dependency "safety_net_attestation", "~> 0.4.0"
         | 
| 40 43 | 
             
              spec.add_dependency "securecompare", "~> 1.0"
         | 
| 44 | 
            +
              spec.add_dependency "tpm-key_attestation", "~> 0.10.0"
         | 
| 41 45 |  | 
| 42 | 
            -
              spec.add_development_dependency "appraisal", "~> 2. | 
| 46 | 
            +
              spec.add_development_dependency "appraisal", "~> 2.3.0"
         | 
| 43 47 | 
             
              spec.add_development_dependency "bundler", ">= 1.17", "< 3.0"
         | 
| 44 48 | 
             
              spec.add_development_dependency "byebug", "~> 11.0"
         | 
| 45 49 | 
             
              spec.add_development_dependency "rake", "~> 13.0"
         | 
| 46 50 | 
             
              spec.add_development_dependency "rspec", "~> 3.8"
         | 
| 47 | 
            -
              spec.add_development_dependency "rubocop", "0. | 
| 48 | 
            -
              spec.add_development_dependency " | 
| 51 | 
            +
              spec.add_development_dependency "rubocop", "0.89"
         | 
| 52 | 
            +
              spec.add_development_dependency "rubocop-rspec", "~> 1.38.1"
         | 
| 49 53 | 
             
            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: 2.1 | 
| 4 | 
            +
              version: 2.4.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Gonzalo Rodriguez
         | 
| @@ -9,8 +9,22 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: exe
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date:  | 
| 12 | 
            +
            date: 2021-02-15 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 15 | 
            +
              name: android_key_attestation
         | 
| 16 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 17 | 
            +
                requirements:
         | 
| 18 | 
            +
                - - "~>"
         | 
| 19 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 20 | 
            +
                    version: 0.3.0
         | 
| 21 | 
            +
              type: :runtime
         | 
| 22 | 
            +
              prerelease: false
         | 
| 23 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 24 | 
            +
                requirements:
         | 
| 25 | 
            +
                - - "~>"
         | 
| 26 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 27 | 
            +
                    version: 0.3.0
         | 
| 14 28 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 29 | 
             
              name: awrence
         | 
| 16 30 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -59,48 +73,42 @@ dependencies: | |
| 59 73 | 
             
                requirements:
         | 
| 60 74 | 
             
                - - "~>"
         | 
| 61 75 | 
             
                  - !ruby/object:Gem::Version
         | 
| 62 | 
            -
                    version:  | 
| 76 | 
            +
                    version: '1.1'
         | 
| 63 77 | 
             
              type: :runtime
         | 
| 64 78 | 
             
              prerelease: false
         | 
| 65 79 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 66 80 | 
             
                requirements:
         | 
| 67 81 | 
             
                - - "~>"
         | 
| 68 82 | 
             
                  - !ruby/object:Gem::Version
         | 
| 69 | 
            -
                    version:  | 
| 83 | 
            +
                    version: '1.1'
         | 
| 70 84 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 71 | 
            -
              name:  | 
| 85 | 
            +
              name: openssl
         | 
| 72 86 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 73 87 | 
             
                requirements:
         | 
| 74 | 
            -
                - - " | 
| 75 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 76 | 
            -
                    version: '1.5'
         | 
| 77 | 
            -
                - - "<"
         | 
| 88 | 
            +
                - - "~>"
         | 
| 78 89 | 
             
                  - !ruby/object:Gem::Version
         | 
| 79 | 
            -
                    version: ' | 
| 90 | 
            +
                    version: '2.0'
         | 
| 80 91 | 
             
              type: :runtime
         | 
| 81 92 | 
             
              prerelease: false
         | 
| 82 93 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 83 94 | 
             
                requirements:
         | 
| 84 | 
            -
                - - " | 
| 85 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 86 | 
            -
                    version: '1.5'
         | 
| 87 | 
            -
                - - "<"
         | 
| 95 | 
            +
                - - "~>"
         | 
| 88 96 | 
             
                  - !ruby/object:Gem::Version
         | 
| 89 | 
            -
                    version: ' | 
| 97 | 
            +
                    version: '2.0'
         | 
| 90 98 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 91 | 
            -
              name:  | 
| 99 | 
            +
              name: safety_net_attestation
         | 
| 92 100 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 93 101 | 
             
                requirements:
         | 
| 94 102 | 
             
                - - "~>"
         | 
| 95 103 | 
             
                  - !ruby/object:Gem::Version
         | 
| 96 | 
            -
                    version:  | 
| 104 | 
            +
                    version: 0.4.0
         | 
| 97 105 | 
             
              type: :runtime
         | 
| 98 106 | 
             
              prerelease: false
         | 
| 99 107 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 100 108 | 
             
                requirements:
         | 
| 101 109 | 
             
                - - "~>"
         | 
| 102 110 | 
             
                  - !ruby/object:Gem::Version
         | 
| 103 | 
            -
                    version:  | 
| 111 | 
            +
                    version: 0.4.0
         | 
| 104 112 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 105 113 | 
             
              name: securecompare
         | 
| 106 114 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -115,20 +123,34 @@ dependencies: | |
| 115 123 | 
             
                - - "~>"
         | 
| 116 124 | 
             
                  - !ruby/object:Gem::Version
         | 
| 117 125 | 
             
                    version: '1.0'
         | 
| 126 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 127 | 
            +
              name: tpm-key_attestation
         | 
| 128 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 129 | 
            +
                requirements:
         | 
| 130 | 
            +
                - - "~>"
         | 
| 131 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 132 | 
            +
                    version: 0.10.0
         | 
| 133 | 
            +
              type: :runtime
         | 
| 134 | 
            +
              prerelease: false
         | 
| 135 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 136 | 
            +
                requirements:
         | 
| 137 | 
            +
                - - "~>"
         | 
| 138 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 139 | 
            +
                    version: 0.10.0
         | 
| 118 140 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 119 141 | 
             
              name: appraisal
         | 
| 120 142 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 121 143 | 
             
                requirements:
         | 
| 122 144 | 
             
                - - "~>"
         | 
| 123 145 | 
             
                  - !ruby/object:Gem::Version
         | 
| 124 | 
            -
                    version: 2. | 
| 146 | 
            +
                    version: 2.3.0
         | 
| 125 147 | 
             
              type: :development
         | 
| 126 148 | 
             
              prerelease: false
         | 
| 127 149 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 128 150 | 
             
                requirements:
         | 
| 129 151 | 
             
                - - "~>"
         | 
| 130 152 | 
             
                  - !ruby/object:Gem::Version
         | 
| 131 | 
            -
                    version: 2. | 
| 153 | 
            +
                    version: 2.3.0
         | 
| 132 154 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 133 155 | 
             
              name: bundler
         | 
| 134 156 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -197,28 +219,28 @@ dependencies: | |
| 197 219 | 
             
                requirements:
         | 
| 198 220 | 
             
                - - '='
         | 
| 199 221 | 
             
                  - !ruby/object:Gem::Version
         | 
| 200 | 
            -
                    version: 0. | 
| 222 | 
            +
                    version: '0.89'
         | 
| 201 223 | 
             
              type: :development
         | 
| 202 224 | 
             
              prerelease: false
         | 
| 203 225 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 204 226 | 
             
                requirements:
         | 
| 205 227 | 
             
                - - '='
         | 
| 206 228 | 
             
                  - !ruby/object:Gem::Version
         | 
| 207 | 
            -
                    version: 0. | 
| 229 | 
            +
                    version: '0.89'
         | 
| 208 230 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 209 | 
            -
              name:  | 
| 231 | 
            +
              name: rubocop-rspec
         | 
| 210 232 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 211 233 | 
             
                requirements:
         | 
| 212 234 | 
             
                - - "~>"
         | 
| 213 235 | 
             
                  - !ruby/object:Gem::Version
         | 
| 214 | 
            -
                    version:  | 
| 236 | 
            +
                    version: 1.38.1
         | 
| 215 237 | 
             
              type: :development
         | 
| 216 238 | 
             
              prerelease: false
         | 
| 217 239 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 218 240 | 
             
                requirements:
         | 
| 219 241 | 
             
                - - "~>"
         | 
| 220 242 | 
             
                  - !ruby/object:Gem::Version
         | 
| 221 | 
            -
                    version:  | 
| 243 | 
            +
                    version: 1.38.1
         | 
| 222 244 | 
             
            description: |-
         | 
| 223 245 | 
             
              WebAuthn ruby server library ― Make your application a W3C Web Authentication conformant
         | 
| 224 246 | 
             
                  Relying Party and allow your users to authenticate with U2F and FIDO2 authenticators.
         | 
| @@ -247,21 +269,13 @@ files: | |
| 247 269 | 
             
            - gemfiles/cose_head.gemfile
         | 
| 248 270 | 
             
            - gemfiles/openssl_2_0.gemfile
         | 
| 249 271 | 
             
            - gemfiles/openssl_2_1.gemfile
         | 
| 272 | 
            +
            - gemfiles/openssl_2_2.gemfile
         | 
| 250 273 | 
             
            - gemfiles/openssl_head.gemfile
         | 
| 251 | 
            -
            - lib/ | 
| 252 | 
            -
            - lib/cose/rsassa_algorithm.rb
         | 
| 253 | 
            -
            - lib/tpm/constants.rb
         | 
| 254 | 
            -
            - lib/tpm/s_attest.rb
         | 
| 255 | 
            -
            - lib/tpm/s_attest/s_certify_info.rb
         | 
| 256 | 
            -
            - lib/tpm/sized_buffer.rb
         | 
| 257 | 
            -
            - lib/tpm/t_public.rb
         | 
| 258 | 
            -
            - lib/tpm/t_public/s_ecc_parms.rb
         | 
| 259 | 
            -
            - lib/tpm/t_public/s_rsa_parms.rb
         | 
| 274 | 
            +
            - lib/cose/rsapkcs1_algorithm.rb
         | 
| 260 275 | 
             
            - lib/webauthn.rb
         | 
| 276 | 
            +
            - lib/webauthn/attestation_object.rb
         | 
| 261 277 | 
             
            - lib/webauthn/attestation_statement.rb
         | 
| 262 278 | 
             
            - lib/webauthn/attestation_statement/android_key.rb
         | 
| 263 | 
            -
            - lib/webauthn/attestation_statement/android_key/authorization_list.rb
         | 
| 264 | 
            -
            - lib/webauthn/attestation_statement/android_key/key_description.rb
         | 
| 265 279 | 
             
            - lib/webauthn/attestation_statement/android_safetynet.rb
         | 
| 266 280 | 
             
            - lib/webauthn/attestation_statement/base.rb
         | 
| 267 281 | 
             
            - lib/webauthn/attestation_statement/fido_u2f.rb
         | 
| @@ -269,8 +283,6 @@ files: | |
| 269 283 | 
             
            - lib/webauthn/attestation_statement/none.rb
         | 
| 270 284 | 
             
            - lib/webauthn/attestation_statement/packed.rb
         | 
| 271 285 | 
             
            - lib/webauthn/attestation_statement/tpm.rb
         | 
| 272 | 
            -
            - lib/webauthn/attestation_statement/tpm/cert_info.rb
         | 
| 273 | 
            -
            - lib/webauthn/attestation_statement/tpm/pub_area.rb
         | 
| 274 286 | 
             
            - lib/webauthn/authenticator_assertion_response.rb
         | 
| 275 287 | 
             
            - lib/webauthn/authenticator_attestation_response.rb
         | 
| 276 288 | 
             
            - lib/webauthn/authenticator_data.rb
         | 
| @@ -302,9 +314,10 @@ files: | |
| 302 314 | 
             
            - lib/webauthn/public_key_credential_with_assertion.rb
         | 
| 303 315 | 
             
            - lib/webauthn/public_key_credential_with_attestation.rb
         | 
| 304 316 | 
             
            - lib/webauthn/security_utils.rb
         | 
| 305 | 
            -
            - lib/webauthn/signature_verifier.rb
         | 
| 306 317 | 
             
            - lib/webauthn/u2f_migrator.rb
         | 
| 307 318 | 
             
            - lib/webauthn/version.rb
         | 
| 319 | 
            +
            - script/ci/install-openssl
         | 
| 320 | 
            +
            - script/ci/install-ruby
         | 
| 308 321 | 
             
            - webauthn.gemspec
         | 
| 309 322 | 
             
            homepage: https://github.com/cedarcode/webauthn-ruby
         | 
| 310 323 | 
             
            licenses:
         | 
| @@ -321,14 +334,14 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 321 334 | 
             
              requirements:
         | 
| 322 335 | 
             
              - - ">="
         | 
| 323 336 | 
             
                - !ruby/object:Gem::Version
         | 
| 324 | 
            -
                  version: '2. | 
| 337 | 
            +
                  version: '2.4'
         | 
| 325 338 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 326 339 | 
             
              requirements:
         | 
| 327 340 | 
             
              - - ">="
         | 
| 328 341 | 
             
                - !ruby/object:Gem::Version
         | 
| 329 342 | 
             
                  version: '0'
         | 
| 330 343 | 
             
            requirements: []
         | 
| 331 | 
            -
            rubygems_version: 3. | 
| 344 | 
            +
            rubygems_version: 3.2.8
         | 
| 332 345 | 
             
            signing_key: 
         | 
| 333 346 | 
             
            specification_version: 4
         | 
| 334 347 | 
             
            summary: WebAuthn ruby server library
         | 
| @@ -1,116 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require "base64"
         | 
| 4 | 
            -
            require "jwt"
         | 
| 5 | 
            -
            require "webauthn/security_utils"
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            module AndroidSafetynet
         | 
| 8 | 
            -
              # Decoupled from WebAuthn, candidate for extraction
         | 
| 9 | 
            -
              # Reference: https://developer.android.com/training/safetynet/attestation.html
         | 
| 10 | 
            -
              class AttestationResponse
         | 
| 11 | 
            -
                class VerificationError < StandardError; end
         | 
| 12 | 
            -
                class LeafCertificateSubjectError < VerificationError; end
         | 
| 13 | 
            -
                class NonceMismatchError < VerificationError; end
         | 
| 14 | 
            -
                class SignatureError < VerificationError; end
         | 
| 15 | 
            -
                class ResponseMissingError < VerificationError; end
         | 
| 16 | 
            -
                class TimestampError < VerificationError; end
         | 
| 17 | 
            -
                class TrustworthinessError < VerificationError; end
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                CERTIRICATE_CHAIN_HEADER = "x5c"
         | 
| 20 | 
            -
                VALID_SUBJECT_HOSTNAME = "attest.android.com"
         | 
| 21 | 
            -
                HEADERS_POSITION = 1
         | 
| 22 | 
            -
                PAYLOAD_POSITION = 0
         | 
| 23 | 
            -
                LEEWAY = 60
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                # FIXME: Should probably be limited to only roots published by Google
         | 
| 26 | 
            -
                # See https://github.com/cedarcode/webauthn-ruby/issues/160#issuecomment-487941201
         | 
| 27 | 
            -
                @trust_store = OpenSSL::X509::Store.new.tap { |trust_store| trust_store.set_default_paths }
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                class << self
         | 
| 30 | 
            -
                  attr_accessor :trust_store
         | 
| 31 | 
            -
                end
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                attr_reader :response
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                def initialize(response)
         | 
| 36 | 
            -
                  @response = response
         | 
| 37 | 
            -
                end
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                def verify(nonce, trustworthiness: true)
         | 
| 40 | 
            -
                  if response
         | 
| 41 | 
            -
                    valid_nonce?(nonce) || raise(NonceMismatchError)
         | 
| 42 | 
            -
                    valid_attestation_domain? || raise(LeafCertificateSubjectError)
         | 
| 43 | 
            -
                    valid_signature? || raise(SignatureError)
         | 
| 44 | 
            -
                    valid_timestamp? || raise(TimestampError)
         | 
| 45 | 
            -
                    trustworthy? || raise(TrustworthinessError) if trustworthiness
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                    true
         | 
| 48 | 
            -
                  else
         | 
| 49 | 
            -
                    raise(ResponseMissingError)
         | 
| 50 | 
            -
                  end
         | 
| 51 | 
            -
                end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                def cts_profile_match?
         | 
| 54 | 
            -
                  payload["ctsProfileMatch"]
         | 
| 55 | 
            -
                end
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                def leaf_certificate
         | 
| 58 | 
            -
                  certificate_chain[0]
         | 
| 59 | 
            -
                end
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                def certificate_chain
         | 
| 62 | 
            -
                  @certificate_chain ||= headers[CERTIRICATE_CHAIN_HEADER].map do |cert|
         | 
| 63 | 
            -
                    OpenSSL::X509::Certificate.new(Base64.strict_decode64(cert))
         | 
| 64 | 
            -
                  end
         | 
| 65 | 
            -
                end
         | 
| 66 | 
            -
             | 
| 67 | 
            -
                def valid_timestamp?
         | 
| 68 | 
            -
                  now = Time.now
         | 
| 69 | 
            -
                  Time.at((payload["timestampMs"] / 1000.0).round).between?(now - LEEWAY, now)
         | 
| 70 | 
            -
                end
         | 
| 71 | 
            -
             | 
| 72 | 
            -
                private
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                def valid_nonce?(nonce)
         | 
| 75 | 
            -
                  WebAuthn::SecurityUtils.secure_compare(payload["nonce"], nonce)
         | 
| 76 | 
            -
                end
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                def valid_attestation_domain?
         | 
| 79 | 
            -
                  common_name = leaf_certificate&.subject&.to_a&.assoc('CN')
         | 
| 80 | 
            -
             | 
| 81 | 
            -
                  if common_name
         | 
| 82 | 
            -
                    common_name[1] == VALID_SUBJECT_HOSTNAME
         | 
| 83 | 
            -
                  end
         | 
| 84 | 
            -
                end
         | 
| 85 | 
            -
             | 
| 86 | 
            -
                def valid_signature?
         | 
| 87 | 
            -
                  JWT.decode(response, leaf_certificate.public_key, true, algorithms: ["ES256", "RS256"])
         | 
| 88 | 
            -
                rescue JWT::VerificationError
         | 
| 89 | 
            -
                  false
         | 
| 90 | 
            -
                end
         | 
| 91 | 
            -
             | 
| 92 | 
            -
                def trustworthy?
         | 
| 93 | 
            -
                  !trust_store || trust_store.verify(leaf_certificate, signing_certificates)
         | 
| 94 | 
            -
                end
         | 
| 95 | 
            -
             | 
| 96 | 
            -
                def trust_store
         | 
| 97 | 
            -
                  self.class.trust_store
         | 
| 98 | 
            -
                end
         | 
| 99 | 
            -
             | 
| 100 | 
            -
                def signing_certificates
         | 
| 101 | 
            -
                  certificate_chain[1..-1]
         | 
| 102 | 
            -
                end
         | 
| 103 | 
            -
             | 
| 104 | 
            -
                def headers
         | 
| 105 | 
            -
                  jws_parts[HEADERS_POSITION]
         | 
| 106 | 
            -
                end
         | 
| 107 | 
            -
             | 
| 108 | 
            -
                def payload
         | 
| 109 | 
            -
                  jws_parts[PAYLOAD_POSITION]
         | 
| 110 | 
            -
                end
         | 
| 111 | 
            -
             | 
| 112 | 
            -
                def jws_parts
         | 
| 113 | 
            -
                  @jws_parts ||= JWT.decode(response, nil, false)
         | 
| 114 | 
            -
                end
         | 
| 115 | 
            -
              end
         | 
| 116 | 
            -
            end
         |