class WebAuthn::AttestationStatement::Packed
def attestation_type
def attestation_type if attestation_trust_path WebAuthn::AttestationStatement::ATTESTATION_TYPE_BASIC_OR_ATTCA # FIXME: use metadata if available else WebAuthn::AttestationStatement::ATTESTATION_TYPE_SELF end end
def meet_certificate_requirement?
def meet_certificate_requirement? if attestation_certificate subject = attestation_certificate.subject.to_a attestation_certificate.version == 2 && subject.assoc('OU')&.at(1) == "Authenticator Attestation" && attestation_certificate.find_extension('basicConstraints')&.value == 'CA:FALSE' else true end end
def self_attestation?
def self_attestation? !raw_certificates end
def valid?(authenticator_data, client_data_hash)
def valid?(authenticator_data, client_data_hash) valid_format? && valid_algorithm?(authenticator_data.credential) && valid_ec_public_keys?(authenticator_data.credential) && meet_certificate_requirement? && matching_aaguid?(authenticator_data.attested_credential_data.raw_aaguid) && valid_signature?(authenticator_data, client_data_hash) && trustworthy?(aaguid: authenticator_data.aaguid) && [attestation_type, attestation_trust_path] end
def valid_algorithm?(credential)
def valid_algorithm?(credential) !self_attestation? || algorithm == COSE::Key.deserialize(credential.public_key).alg end
def valid_ec_public_keys?(credential)
def valid_ec_public_keys?(credential) (certificates&.map(&:public_key) || [credential.public_key_object]) .select { |pkey| pkey.is_a?(OpenSSL::PKey::EC) } .all? { |pkey| pkey.check_key } end
def valid_format?
def valid_format? algorithm && signature end
def valid_signature?(authenticator_data, client_data_hash)
def valid_signature?(authenticator_data, client_data_hash) super( authenticator_data, client_data_hash, attestation_certificate&.public_key || authenticator_data.credential.public_key_object ) end