class WebAuthn::FakeAuthenticator::AuthenticatorData

def attested_credential_data

def attested_credential_data
  @attested_credential_data ||=
    if credential
      @aaguid +
        [credential[:id].length].pack("n*") +
        credential[:id] +
        cose_credential_public_key
    else
      ""
    end
end

def attested_credential_data_included_bit

def attested_credential_data_included_bit
  if attested_credential_data.empty?
    "0"
  else
    "1"
  end
end

def bit(flag)

def bit(flag)
  if context[flag]
    "1"
  else
    "0"
  end
end

def context

def context
  {
    user_present: user_present,
    user_verified: user_verified,
    backup_eligibility: backup_eligibility,
    backup_state: backup_state
  }
end

def cose_credential_public_key

def cose_credential_public_key
  case credential[:public_key]
  when OpenSSL::PKey::RSA
    key = COSE::Key::RSA.from_pkey(credential[:public_key])
    key.alg = -257
  when OpenSSL::PKey::EC::Point
    alg = {
      COSE::Key::Curve.by_name("P-256").id => -7,
      COSE::Key::Curve.by_name("P-384").id => -35,
      COSE::Key::Curve.by_name("P-521").id => -36
    }
    key = COSE::Key::EC2.from_pkey(credential[:public_key])
    key.alg = alg[key.crv]
  when OpenSSL::PKey::PKey
    key = COSE::Key::OKP.from_pkey(credential[:public_key])
    key.alg = -8
  end
  key.serialize
end

def extension_data

def extension_data
  if extensions
    CBOR.encode(extensions)
  else
    ""
  end
end

def extension_data_included_bit

def extension_data_included_bit
  if extension_data.empty?
    "0"
  else
    "1"
  end
end

def flags

def flags
  [
    [
      bit(:user_present),
      reserved_for_future_use_bit,
      bit(:user_verified),
      bit(:backup_eligibility),
      bit(:backup_state),
      reserved_for_future_use_bit,
      attested_credential_data_included_bit,
      extension_data_included_bit
    ].join
  ].pack("b*")
end

def initialize(

def initialize(
  rp_id_hash:,
  credential: {
    id: SecureRandom.random_bytes(16),
    public_key: OpenSSL::PKey::EC.generate("prime256v1").public_key
  },
  sign_count: 0,
  user_present: true,
  user_verified: !user_present,
  backup_eligibility: false,
  backup_state: false,
  aaguid: AAGUID,
  extensions: { "fakeExtension" => "fakeExtensionValue" }
)
  @rp_id_hash = rp_id_hash
  @credential = credential
  @sign_count = sign_count
  @user_present = user_present
  @user_verified = user_verified
  @backup_eligibility = backup_eligibility
  @backup_state = backup_state
  @aaguid = aaguid
  @extensions = extensions
end

def key_bytes(public_key)

def key_bytes(public_key)
  public_key.to_bn.to_s(2)
end

def reserved_for_future_use_bit

def reserved_for_future_use_bit
  "0"
end

def serialize

def serialize
  rp_id_hash + flags + serialized_sign_count + attested_credential_data + extension_data
end

def serialized_sign_count

def serialized_sign_count
  [sign_count].pack('L>')
end