Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] feat: validate fido-u2f attestation response #13

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
[WIP] feat: validate fido-u2f attestation response
  • Loading branch information
grzuy committed May 22, 2018
commit b9e789748ecc3c90bcfddaf7d5e0b05f16fad4c0
51 changes: 51 additions & 0 deletions lib/webauthn/statement_validator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
require "openssl"

module WebAuthn
class StatementValidator
VALID_ATTESTATION_CERTIFICATE_COUNT = 1

def initialize(statement)
@statement = statement
end

def valid?
valid_format? && valid_attestation_public_key? && valid_signature?
end

private

attr_reader :statement

def valid_format?
!!(raw_attestation_certificates && signature) && valid_attestation_certificate_count?
end

def valid_attestation_public_key?
attestation_public_key.is_a?(OpenSSL::PKey::EC) && attestation_public_key.check_key
end

def valid_signature?
raise NotImplementedError
end

def valid_attestation_certificate_count?
raw_attestation_certificates.length == VALID_ATTESTATION_CERTIFICATE_COUNT
end

def attestation_certificate
@attestation_certificate ||= OpenSSL::X509::Certificate.new(raw_attestation_certificates[0])
end

def attestation_public_key
attestation_certificate.public_key
end

def raw_attestation_certificates
statement["x5c"]
end

def signature
statement["sig"]
end
end
end
11 changes: 10 additions & 1 deletion lib/webauthn/validator.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# frozen_string_literal: true

require "cbor"
require "webauthn/statement_validator"

module WebAuthn
class Validator
ATTESTATION_FORMAT_NONE = "none"
ATTESTATION_FORMAT_FIDO_U2F = "fido-u2f"
AUTHENTICATOR_DATA_MIN_LENGTH = 37
USER_PRESENT_BIT_POSITION = 0

Expand Down Expand Up @@ -39,8 +41,11 @@ def valid_authenticator_data?
end

def valid_attestation_statement?
if attestation_format == ATTESTATION_FORMAT_NONE
case attestation_format
when ATTESTATION_FORMAT_NONE
true
when ATTESTATION_FORMAT_FIDO_U2F
WebAuthn::StatementValidator.new(attestation_statement).valid?
else
raise "Unsupported attestation format '#{attestation_format}'"
end
Expand Down Expand Up @@ -73,6 +78,10 @@ def attestation_format
attestation["fmt"]
end

def attestation_statement
attestation["attStmt"]
end

def attestation
@attestation ||= CBOR.decode(Base64.urlsafe_decode64(attestation_object))
end
Expand Down
9 changes: 9 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ def seeds
attestation_object: 'o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjESZYN5YgOjGh0NBcPZHZgW4/krrmihjLHmVzzuoMdl2NBAAAAAAAAAAAAAAAAAAAAAAAAAAAAQN+zoWcbFDyyOvchxWedAB6FwzMqB0Fmmr+VnWlMzR9lqhoPSb/1388CluAR/JDTSykFMwzxT+EASYD5w/djXNulAQIDJiABIVggxTGmnso/zNWSp7ZSOm7hQqfUtJZylvCj+7fYoi7UG54iWCCJi3gYqD9rYJEfiAlRKYVGqqtp1mmur1OCS2Tgno7Qxg==',
client_data_json: 'eyJjaGFsbGVuZ2UiOiJBYWc5UEpMUXZDMml4d1pDSHpzMll3IiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9'
}
},
security_key_direct: {
credential_creation_options: {
challenge: '11CzaFXezx7YszNaYE3pag=='
},
authenticator_attestation_response: {
attestation_object: 'o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEYwRAIgekOQZSd0/dNZZ3iBBaKWUVaYx49+w37LunPGKthcYG8CICFt3JdafYmqC3oAHDeFkLYM0eQjWPjZkh7WBqvRCcR9Y3g1Y4FZAsIwggK+MIIBpqADAgECAgR0hv3CMA0GCSqGSIb3DQEBCwUAMC4xLDAqBgNVBAMTI1l1YmljbyBVMkYgUm9vdCBDQSBTZXJpYWwgNDU3MjAwNjMxMCAXDTE0MDgwMTAwMDAwMFoYDzIwNTAwOTA0MDAwMDAwWjBvMQswCQYDVQQGEwJTRTESMBAGA1UECgwJWXViaWNvIEFCMSIwIAYDVQQLDBlBdXRoZW50aWNhdG9yIEF0dGVzdGF0aW9uMSgwJgYDVQQDDB9ZdWJpY28gVTJGIEVFIFNlcmlhbCAxOTU1MDAzODQyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElV3zrfckfTF17/2cxPMaToeOuuGBCVZhUPs4iy5fZSe/V0CapYGlDQrFLxhEXAoTVIoTU8ik5ZpwTlI7wE3r7aNsMGowIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjEwEwYLKwYBBAGC5RwCAQEEBAMCBSAwIQYLKwYBBAGC5RwBAQQEEgQQ+KAR84wKTRWABhcRH57cfTAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAxXEiA5ppSfjhmib1p/Qqob0nrnk6FRUFVb6rQCzoAih3cAflsdvZoNhqR4jLIEKecYwdMm256RusdtdhcREifhop2Q9IqXIYuwD8D5YSL44B9es1V+OGuHuITrHOrSyDj+9UmjLB7h4AnHR9L4OXdrHNNOliXvU1zun81fqIIyZ2KTSkC5gl6AFxNyQTcChgSDgr30Az8lpoohuWxsWHz7cvGd6Z41/tTA5zNoYa+NLpTMZUjQ51/2Upw8jBiG5PEzkJo0xdNlDvGrj/JN8LeQ9a0TiEVPfhQkl+VkGIuvEbg6xjGQfD+fm8qCamykHcZ9i5hNaGQMqITwJi3KDzuaGF1dGhEYXRhWMRJlg3liA6MaHQ0Fw9kdmBbj+SuuaKGMseZXPO6gx2XY0EAAAAAAAAAAAAAAAAAAAAAAAAAAABA2Nc6mqO+eIH0eIAhy1xfIJcjHtlOAsRLHxf4u5apXnhI6j8oGbmF87Qz6L8AvGjlHQLjGhAXjLpBFb2aeVowSqUBAgMmIAEhWCBsj3dTr9jqWWOwuDzWAQOqqugB1YGYKpE/YqHfRB3GrCJYIPiyHJ4rYZRaqfJQKAInKzINuxkQARzVdNcChyszi/Pr',
client_data_json: 'eyJjaGFsbGVuZ2UiOiIxMUN6YUZYZXp4N1lzek5hWUUzcGFnIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9'
}
}
}
end
13 changes: 13 additions & 0 deletions spec/webauthn/validator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,17 @@
validator.valid?
}.to raise_exception(RuntimeError, "Missing client_data_bin")
end

it "validates fido-u2f attestation" do
original_challenge = seeds[:security_key_direct][:credential_creation_options][:challenge]
response = seeds[:security_key_direct][:authenticator_attestation_response]

validator = WebAuthn::Validator.new(
original_challenge: original_challenge,
attestation_object: response[:attestation_object],
client_data_bin: response[:client_data_json]
)

expect(validator.valid?).to eq(true)
end
end