webauthn 1.16.0 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -3
- data/CHANGELOG.md +8 -0
- data/README.md +9 -2
- data/lib/cose/algorithm.rb +6 -0
- data/lib/tpm/constants.rb +1 -0
- data/lib/webauthn/attestation_statement/tpm.rb +1 -1
- data/lib/webauthn/attestation_statement/tpm/pub_area.rb +2 -1
- data/lib/webauthn/authenticator_assertion_response.rb +16 -0
- data/lib/webauthn/fake_authenticator.rb +3 -1
- data/lib/webauthn/fake_client.rb +3 -2
- data/lib/webauthn/signature_verifier.rb +2 -2
- data/lib/webauthn/version.rb +1 -1
- data/webauthn.gemspec +1 -1
- metadata +5 -5
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: d4cc833d8288e0519614728a71e26e4e7842ec0c597bd7fc839fe9bacbb44c61
         | 
| 4 | 
            +
              data.tar.gz: 712c9ad093705954409facf4ee171752ba76865cbca831121a0f88a4c4d9430c
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 6fd66258429cadca7660ce7c69640b630b13bd21ac4b690d60c37834edcf4b6ce368688186f1b1a23fba8dc4856767314f7a7308e1ae9932f2f51776fabe89cb
         | 
| 7 | 
            +
              data.tar.gz: a28362aa5cf1bd451a5b0303750bb55ffd80f2b47c63c9ef04b7f04e300c8b4f997ec0d6a808361503ecb0b780c263d2447c36bde0239657bc3cc5fd6b106719
         | 
    
        data/.rubocop.yml
    CHANGED
    
    
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,12 @@ | |
| 1 1 | 
             
            # Changelog
         | 
| 2 2 |  | 
| 3 | 
            +
            ## [v1.17.0] - 2019-06-18
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ### Added
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            - Support ES384, ES512, PS384, PS512, RS384 and RS512 credentials. Off by default. Enable by adding any of them to `WebAuthn.configuration.algorithms` array. Thank you @bdewater.
         | 
| 8 | 
            +
            - Support [Signature Counter](https://www.w3.org/TR/webauthn/#signature-counter) verification. Thank you @bdewater.
         | 
| 9 | 
            +
             | 
| 3 10 | 
             
            ## [v1.16.0] - 2019-06-13
         | 
| 4 11 |  | 
| 5 12 | 
             
            ### Added
         | 
| @@ -187,6 +194,7 @@ Note: Both additions should help making it compatible with Chrome for Android 70 | |
| 187 194 | 
             
              - `WebAuthn::AuthenticatorAttestationResponse.valid?` can be used to validate fido-u2f attestations returned by the browser
         | 
| 188 195 | 
             
            - Works with ruby 2.5
         | 
| 189 196 |  | 
| 197 | 
            +
            [v1.17.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.16.0...v1.17.0/
         | 
| 190 198 | 
             
            [v1.16.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.15.0...v1.16.0/
         | 
| 191 199 | 
             
            [v1.15.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.14.0...v1.15.0/
         | 
| 192 200 | 
             
            [v1.14.0]: https://github.com/cedarcode/webauthn-ruby/compare/v1.13.0...v1.14.0/
         | 
    
        data/README.md
    CHANGED
    
    | @@ -127,11 +127,12 @@ begin | |
| 127 127 | 
             
              attestation_response.verify(expected_challenge)
         | 
| 128 128 |  | 
| 129 129 | 
             
              # 1. Register the new user and
         | 
| 130 | 
            -
              # 2. Keep Credential ID  | 
| 130 | 
            +
              # 2. Keep Credential ID, Credential Public Key and Sign Count under storage
         | 
| 131 131 | 
             
              #    for future authentications
         | 
| 132 132 | 
             
              #    Access by invoking:
         | 
| 133 133 | 
             
              #      `attestation_response.credential.id`
         | 
| 134 134 | 
             
              #      `attestation_response.credential.public_key`
         | 
| 135 | 
            +
              #      `attestation_response.authenticator_data.sign_count`
         | 
| 135 136 | 
             
            rescue WebAuthn::VerificationError => e
         | 
| 136 137 | 
             
              # Handle error
         | 
| 137 138 | 
             
            end
         | 
| @@ -171,11 +172,13 @@ Assuming you have the previously stored Credential Public Key, now in variable ` | |
| 171 172 | 
             
            #
         | 
| 172 173 | 
             
            # E.g. in https://github.com/cedarcode/webauthn-rails-demo-app we use `Base64.strict_decode64`
         | 
| 173 174 | 
             
            # on the user-agent encoded data before calling `#verify`
         | 
| 175 | 
            +
            selected_credential_id = "..."
         | 
| 174 176 | 
             
            authenticator_data = "..."
         | 
| 175 177 | 
             
            client_data_json = "..."
         | 
| 176 178 | 
             
            signature = "..."
         | 
| 177 179 |  | 
| 178 180 | 
             
            assertion_response = WebAuthn::AuthenticatorAssertionResponse.new(
         | 
| 181 | 
            +
              credential_id: selected_credential_id,
         | 
| 179 182 | 
             
              authenticator_data: authenticator_data,
         | 
| 180 183 | 
             
              client_data_json: client_data_json,
         | 
| 181 184 | 
             
              signature: signature
         | 
| @@ -185,7 +188,8 @@ assertion_response = WebAuthn::AuthenticatorAssertionResponse.new( | |
| 185 188 | 
             
            # previously stored credential for the user that is attempting to sign in.
         | 
| 186 189 | 
             
            allowed_credential = {
         | 
| 187 190 | 
             
              id: credential_id,
         | 
| 188 | 
            -
              public_key: credential_public_key
         | 
| 191 | 
            +
              public_key: credential_public_key,
         | 
| 192 | 
            +
              sign_count: sign_count,
         | 
| 189 193 | 
             
            }
         | 
| 190 194 |  | 
| 191 195 | 
             
            begin
         | 
| @@ -195,6 +199,9 @@ begin | |
| 195 199 | 
             
            rescue WebAuthn::VerificationError => e
         | 
| 196 200 | 
             
              # Handle error
         | 
| 197 201 | 
             
            end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
            # Find the selected credential in your data storage using `selected_credential_id`
         | 
| 204 | 
            +
            # Update the stored sign count with the value from `assertion_response.authenticator_data.sign_count`
         | 
| 198 205 | 
             
            ```
         | 
| 199 206 |  | 
| 200 207 | 
             
            ## Attestation Statement Formats
         | 
    
        data/lib/cose/algorithm.rb
    CHANGED
    
    | @@ -27,6 +27,12 @@ module COSE | |
| 27 27 | 
             
            end
         | 
| 28 28 |  | 
| 29 29 | 
             
            COSE::Algorithm.register(-7, "ES256", "SHA256", COSE::Key::EC2::KTY_EC2, "prime256v1")
         | 
| 30 | 
            +
            COSE::Algorithm.register(-35, "ES384", "SHA384", COSE::Key::EC2::KTY_EC2, "prime256v1")
         | 
| 31 | 
            +
            COSE::Algorithm.register(-36, "ES512", "SHA512", COSE::Key::EC2::KTY_EC2, "prime256v1")
         | 
| 30 32 | 
             
            COSE::Algorithm.register(-37, "PS256", "SHA256", COSE::Key::RSA::KTY_RSA)
         | 
| 33 | 
            +
            COSE::Algorithm.register(-38, "PS384", "SHA384", COSE::Key::RSA::KTY_RSA)
         | 
| 34 | 
            +
            COSE::Algorithm.register(-39, "PS512", "SHA512", COSE::Key::RSA::KTY_RSA)
         | 
| 31 35 | 
             
            COSE::Algorithm.register(-257, "RS256", "SHA256", COSE::Key::RSA::KTY_RSA)
         | 
| 36 | 
            +
            COSE::Algorithm.register(-258, "RS384", "SHA384", COSE::Key::RSA::KTY_RSA)
         | 
| 37 | 
            +
            COSE::Algorithm.register(-259, "RS512", "SHA512", COSE::Key::RSA::KTY_RSA)
         | 
| 32 38 | 
             
            COSE::Algorithm.register(-65535, "RS1", "SHA1", COSE::Key::RSA::KTY_RSA)
         | 
    
        data/lib/tpm/constants.rb
    CHANGED
    
    
| @@ -40,7 +40,7 @@ module WebAuthn | |
| 40 40 | 
             
                  def valid_signature?
         | 
| 41 41 | 
             
                    WebAuthn::SignatureVerifier
         | 
| 42 42 | 
             
                      .new(algorithm, attestation_certificate.public_key)
         | 
| 43 | 
            -
                      .verify(signature, verification_data)
         | 
| 43 | 
            +
                      .verify(signature, verification_data, rsa_pss_salt_length: :auto)
         | 
| 44 44 | 
             
                  end
         | 
| 45 45 |  | 
| 46 46 | 
             
                  def valid_attestation_certificate?
         | 
| @@ -17,7 +17,8 @@ module WebAuthn | |
| 17 17 | 
             
                    }.freeze
         | 
| 18 18 |  | 
| 19 19 | 
             
                    COSE_RSA_TO_TPM_ALG = {
         | 
| 20 | 
            -
                      COSE::Algorithm.by_name("RS256").id => ::TPM::ALG_RSASSA
         | 
| 20 | 
            +
                      COSE::Algorithm.by_name("RS256").id => ::TPM::ALG_RSASSA,
         | 
| 21 | 
            +
                      COSE::Algorithm.by_name("PS256").id => ::TPM::ALG_RSAPSS,
         | 
| 21 22 | 
             
                    }.freeze
         | 
| 22 23 |  | 
| 23 24 | 
             
                    COSE_TO_TPM_CURVE = {
         | 
| @@ -10,6 +10,7 @@ require "webauthn/signature_verifier" | |
| 10 10 | 
             
            module WebAuthn
         | 
| 11 11 | 
             
              class CredentialVerificationError < VerificationError; end
         | 
| 12 12 | 
             
              class SignatureVerificationError < VerificationError; end
         | 
| 13 | 
            +
              class SignCountVerificationError < VerificationError; end
         | 
| 13 14 |  | 
| 14 15 | 
             
              class AuthenticatorAssertionResponse < AuthenticatorResponse
         | 
| 15 16 | 
             
                def initialize(credential_id:, authenticator_data:, signature:, **options)
         | 
| @@ -25,6 +26,7 @@ module WebAuthn | |
| 25 26 |  | 
| 26 27 | 
             
                  verify_item(:credential, allowed_credentials)
         | 
| 27 28 | 
             
                  verify_item(:signature, credential_cose_key(allowed_credentials))
         | 
| 29 | 
            +
                  verify_item(:sign_count, allowed_credentials)
         | 
| 28 30 |  | 
| 29 31 | 
             
                  true
         | 
| 30 32 | 
             
                end
         | 
| @@ -43,6 +45,20 @@ module WebAuthn | |
| 43 45 | 
             
                    .verify(signature, authenticator_data_bytes + client_data.hash)
         | 
| 44 46 | 
             
                end
         | 
| 45 47 |  | 
| 48 | 
            +
                def valid_sign_count?(allowed_credentials)
         | 
| 49 | 
            +
                  matched_credential = allowed_credentials.find do |credential|
         | 
| 50 | 
            +
                    credential[:id] == credential_id
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                  # TODO: make passing sign count mandatory in next major version
         | 
| 53 | 
            +
                  stored_sign_count = matched_credential.fetch(:sign_count, 0)
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  if authenticator_data.sign_count.nonzero? || stored_sign_count.nonzero?
         | 
| 56 | 
            +
                    authenticator_data.sign_count > stored_sign_count
         | 
| 57 | 
            +
                  else
         | 
| 58 | 
            +
                    true
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 46 62 | 
             
                def valid_credential?(allowed_credentials)
         | 
| 47 63 | 
             
                  allowed_credential_ids = allowed_credentials.map { |credential| credential[:id] }
         | 
| 48 64 |  | 
| @@ -35,7 +35,8 @@ module WebAuthn | |
| 35 35 | 
             
                  client_data_hash:,
         | 
| 36 36 | 
             
                  user_present: true,
         | 
| 37 37 | 
             
                  user_verified: false,
         | 
| 38 | 
            -
                  aaguid: AuthenticatorData::AAGUID
         | 
| 38 | 
            +
                  aaguid: AuthenticatorData::AAGUID,
         | 
| 39 | 
            +
                  sign_count: 0
         | 
| 39 40 | 
             
                )
         | 
| 40 41 | 
             
                  credential_options = credentials[rp_id]
         | 
| 41 42 |  | 
| @@ -47,6 +48,7 @@ module WebAuthn | |
| 47 48 | 
             
                      user_present: user_present,
         | 
| 48 49 | 
             
                      user_verified: user_verified,
         | 
| 49 50 | 
             
                      aaguid: aaguid,
         | 
| 51 | 
            +
                      sign_count: sign_count,
         | 
| 50 52 | 
             
                    ).serialize
         | 
| 51 53 |  | 
| 52 54 | 
             
                    signature = credential_key.sign("SHA256", authenticator_data + client_data_hash)
         | 
    
        data/lib/webauthn/fake_client.rb
    CHANGED
    
    | @@ -41,7 +41,7 @@ module WebAuthn | |
| 41 41 | 
             
                  }
         | 
| 42 42 | 
             
                end
         | 
| 43 43 |  | 
| 44 | 
            -
                def get(challenge: fake_challenge, rp_id: nil, user_present: true, user_verified: false)
         | 
| 44 | 
            +
                def get(challenge: fake_challenge, rp_id: nil, user_present: true, user_verified: false, sign_count: 0)
         | 
| 45 45 | 
             
                  rp_id ||= URI.parse(origin).host
         | 
| 46 46 |  | 
| 47 47 | 
             
                  client_data_json = data_json_for(:get, challenge)
         | 
| @@ -51,7 +51,8 @@ module WebAuthn | |
| 51 51 | 
             
                    rp_id: rp_id,
         | 
| 52 52 | 
             
                    client_data_hash: client_data_hash,
         | 
| 53 53 | 
             
                    user_present: user_present,
         | 
| 54 | 
            -
                    user_verified: user_verified
         | 
| 54 | 
            +
                    user_verified: user_verified,
         | 
| 55 | 
            +
                    sign_count: sign_count,
         | 
| 55 56 | 
             
                  )
         | 
| 56 57 |  | 
| 57 58 | 
             
                  {
         | 
| @@ -22,10 +22,10 @@ module WebAuthn | |
| 22 22 | 
             
                  validate
         | 
| 23 23 | 
             
                end
         | 
| 24 24 |  | 
| 25 | 
            -
                def verify(signature, verification_data)
         | 
| 25 | 
            +
                def verify(signature, verification_data, rsa_pss_salt_length: :digest)
         | 
| 26 26 | 
             
                  if rsa_pss?
         | 
| 27 27 | 
             
                    public_key.verify_pss(cose_algorithm.hash, signature, verification_data,
         | 
| 28 | 
            -
                                          salt_length:  | 
| 28 | 
            +
                                          salt_length: rsa_pss_salt_length, mgf1_hash: cose_algorithm.hash)
         | 
| 29 29 | 
             
                  else
         | 
| 30 30 | 
             
                    public_key.verify(cose_algorithm.hash, signature, verification_data)
         | 
| 31 31 | 
             
                  end
         | 
    
        data/lib/webauthn/version.rb
    CHANGED
    
    
    
        data/webauthn.gemspec
    CHANGED
    
    | @@ -43,5 +43,5 @@ Gem::Specification.new do |spec| | |
| 43 43 | 
             
              spec.add_development_dependency "byebug", "~> 11.0"
         | 
| 44 44 | 
             
              spec.add_development_dependency "rake", "~> 12.3"
         | 
| 45 45 | 
             
              spec.add_development_dependency "rspec", "~> 3.8"
         | 
| 46 | 
            -
              spec.add_development_dependency "rubocop", "0. | 
| 46 | 
            +
              spec.add_development_dependency "rubocop", "0.71.0"
         | 
| 47 47 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: webauthn
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1. | 
| 4 | 
            +
              version: 1.17.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Gonzalo Rodriguez
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: exe
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2019-06- | 
| 12 | 
            +
            date: 2019-06-18 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: bindata
         | 
| @@ -183,14 +183,14 @@ dependencies: | |
| 183 183 | 
             
                requirements:
         | 
| 184 184 | 
             
                - - '='
         | 
| 185 185 | 
             
                  - !ruby/object:Gem::Version
         | 
| 186 | 
            -
                    version: 0. | 
| 186 | 
            +
                    version: 0.71.0
         | 
| 187 187 | 
             
              type: :development
         | 
| 188 188 | 
             
              prerelease: false
         | 
| 189 189 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 190 190 | 
             
                requirements:
         | 
| 191 191 | 
             
                - - '='
         | 
| 192 192 | 
             
                  - !ruby/object:Gem::Version
         | 
| 193 | 
            -
                    version: 0. | 
| 193 | 
            +
                    version: 0.71.0
         | 
| 194 194 | 
             
            description: |-
         | 
| 195 195 | 
             
              WebAuthn ruby server library ― Make your application a W3C Web Authentication conformant
         | 
| 196 196 | 
             
                  Relying Party and allow your users to authenticate with U2F and FIDO 2.0 authenticators.
         | 
| @@ -283,7 +283,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 283 283 | 
             
                - !ruby/object:Gem::Version
         | 
| 284 284 | 
             
                  version: '0'
         | 
| 285 285 | 
             
            requirements: []
         | 
| 286 | 
            -
            rubygems_version: 3.0. | 
| 286 | 
            +
            rubygems_version: 3.0.4
         | 
| 287 287 | 
             
            signing_key: 
         | 
| 288 288 | 
             
            specification_version: 4
         | 
| 289 289 | 
             
            summary: WebAuthn ruby server library
         |