1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
# frozen_string_literal: true
require "webauthn/authenticator_data"
require "webauthn/authenticator_response"
require "webauthn/encoder"
require "webauthn/public_key"
module WebAuthn
class SignatureVerificationError < VerificationError; end
class SignCountVerificationError < VerificationError; end
class AuthenticatorAssertionResponse < AuthenticatorResponse
def self.from_client(response)
encoder = WebAuthn.configuration.encoder
user_handle =
if response["userHandle"]
encoder.decode(response["userHandle"])
end
new(
authenticator_data: encoder.decode(response["authenticatorData"]),
client_data_json: encoder.decode(response["clientDataJSON"]),
signature: encoder.decode(response["signature"]),
user_handle: user_handle
)
end
attr_reader :user_handle
def initialize(authenticator_data:, signature:, user_handle: nil, **options)
super(**options)
@authenticator_data_bytes = authenticator_data
@signature = signature
@user_handle = user_handle
end
def verify(expected_challenge, expected_origin = nil, public_key:, sign_count:, user_verification: nil, rp_id: nil)
super(expected_challenge, expected_origin, user_verification: user_verification, rp_id: rp_id)
verify_item(:signature, WebAuthn::PublicKey.deserialize(public_key))
verify_item(:sign_count, sign_count)
true
end
def authenticator_data
@authenticator_data ||= WebAuthn::AuthenticatorData.deserialize(authenticator_data_bytes)
end
private
attr_reader :authenticator_data_bytes, :signature
def valid_signature?(webauthn_public_key)
webauthn_public_key.verify(signature, authenticator_data_bytes + client_data.hash)
end
def valid_sign_count?(stored_sign_count)
normalized_sign_count = stored_sign_count || 0
if authenticator_data.sign_count.nonzero? || normalized_sign_count.nonzero?
authenticator_data.sign_count > normalized_sign_count
else
true
end
end
def type
WebAuthn::TYPES[:get]
end
end
end
|