Все решения, которые вы упомянули, в какой-то степени действительны, и комбинация, скорее всего, является лучшим ответом. Вашему приложению необходим доступ к этим API-ключам, поэтому хакер не может получить полный контроль вашего приложения и не получить контроль над API-ключами. Полный контроль является ключевой частью - вам может быть намного сложнее добраться до них.
Шифрование
Вам нужно было бы зашифровать их, а не хешировать, чем-то вроде AES. Поскольку вы должны иметь возможность расшифровать их и использовать их в ваших запросах к третьим лицам. Это поможет вам защитить, например, от утечка базы данных - если кто-то получит вашу базу данных, ему придется взломать шифрование, чтобы получить к ним доступ (при условии, что шифрование правильно реализовано). Ключ шифрования / дешифрования, конечно, должен быть НЕ в базе данных, иначе все это не имеет смысла:)
Разделение
Различная база данных также имеет смысл - если кто-то сбросит вашу основную базу данных, он не получит доступ к базе данных ключей API и должен будет глубже проникнуть в приложение для доступа к этой базе данных (в идеале это будет совершенно отдельный сервер БД, доступный только из ваше заявление).
Архитектура решения также имеет значение - у вас может быть один сервер, изображающий из себя веб-интерфейс, обращенный к интернету, который будет взаимодействовать с внутренним сервером, который не подключен к интернету, через некоторый ограниченный (насколько это возможно) API для снижения поверхность атаки. Только бэкэнд-сервер будет иметь доступ к базе данных ключей и будет выполнять запросы к третьим сторонам. Теперь злоумышленнику нужно перепрыгнуть через несколько серверов, чтобы приблизиться к ключам.
Объединение вышеперечисленного обеспечит получение полного контроля вашего приложения (и всех его частей), чтобы получить ключи, ключ шифрования и обойти любую другую защиту, которую вы можете установить место.