class WebAuthn::AttestationStatement::AndroidSafetynet
def attestation_response
def attestation_response @attestation_response ||= SafetyNetAttestation::Statement.new(statement["response"]) end
def attestation_type
def attestation_type WebAuthn::AttestationStatement::ATTESTATION_TYPE_BASIC end
def certificates
def certificates attestation_response.certificate_chain[0..-2] end
def cts_profile_match?
def cts_profile_match? attestation_response.cts_profile_match? end
def default_root_certificates
def default_root_certificates SafetyNetAttestation::Statement::GOOGLE_ROOT_CERTIFICATES end
def time
def time Time.now end
def valid?(authenticator_data, client_data_hash)
def valid?(authenticator_data, client_data_hash) valid_response?(authenticator_data, client_data_hash) && valid_version? && cts_profile_match? && trustworthy?(aaguid: authenticator_data.aaguid) && [attestation_type, attestation_trust_path] end
def valid_certificate_chain?(**_)
def valid_certificate_chain?(**_) # Already performed as part of #valid_response? true end
def valid_response?(authenticator_data, client_data_hash)
def valid_response?(authenticator_data, client_data_hash) nonce = Digest::SHA256.base64digest(authenticator_data.data + client_data_hash) begin attestation_response .verify(nonce, trusted_certificates: root_certificates(aaguid: authenticator_data.aaguid), time: time) rescue SafetyNetAttestation::Error false end end
def valid_version?
def valid_version? !statement["ver"].empty? end