class WebAuthn::AttestationStatement::AndroidSafetynet

Implements www.w3.org/TR/webauthn-1/#sctn-android-safetynet-attestation

Public Instance Methods

valid?(authenticator_data, client_data_hash) click to toggle source
# File lib/webauthn/attestation_statement/android_safetynet.rb, line 11
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

Private Instance Methods

attestation_response() click to toggle source
# File lib/webauthn/attestation_statement/android_safetynet.rb, line 55
def attestation_response
  @attestation_response ||= SafetyNetAttestation::Statement.new(statement["response"])
end
attestation_type() click to toggle source
# File lib/webauthn/attestation_statement/android_safetynet.rb, line 46
def attestation_type
  WebAuthn::AttestationStatement::ATTESTATION_TYPE_BASIC
end
certificates() click to toggle source

SafetyNetAttestation returns full chain including root, WebAuthn expects only the x5c certificates

# File lib/webauthn/attestation_statement/android_safetynet.rb, line 51
def certificates
  attestation_response.certificate_chain[0..-2]
end
cts_profile_match?() click to toggle source
# File lib/webauthn/attestation_statement/android_safetynet.rb, line 37
def cts_profile_match?
  attestation_response.cts_profile_match?
end
default_root_certificates() click to toggle source
# File lib/webauthn/attestation_statement/android_safetynet.rb, line 59
def default_root_certificates
  SafetyNetAttestation::Statement::GOOGLE_ROOT_CERTIFICATES
end
time() click to toggle source
# File lib/webauthn/attestation_statement/android_safetynet.rb, line 63
def time
  Time.now
end
valid_certificate_chain?(**_) click to toggle source
# File lib/webauthn/attestation_statement/android_safetynet.rb, line 41
def valid_certificate_chain?(**_)
  # Already performed as part of #valid_response?
  true
end
valid_response?(authenticator_data, client_data_hash) click to toggle source
# File lib/webauthn/attestation_statement/android_safetynet.rb, line 21
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
valid_version?() click to toggle source

TODO: improve once the spec has clarifications github.com/w3c/webauthn/issues/968

# File lib/webauthn/attestation_statement/android_safetynet.rb, line 33
def valid_version?
  !statement["ver"].empty?
end