Подтвердить что ты не робот

Как защитить открытый ключ Google Play при выполнении InApp Billing

На самом деле это немного глупо о защите открытого ключа (что такое определение открытого ключа?), но согласно документации от Google:

Чтобы ваш открытый ключ был защищен от вредоносных пользователей и хакеров, не вставлять его в любой код как литеральную строку. Вместо этого постройте строка во время выполнения из фрагментов или использовать манипуляции с битами (например, XOR с некоторой другой строкой), чтобы скрыть фактический ключ. Сам ключ а не секретную информацию, но вы не хотите хакер или злоумышленник, чтобы заменить открытый ключ другим ключом.

Есть ли какой-нибудь рекомендуемый способ сделать это?

Я знаю, что есть много способов сделать это, я просто не хочу следовать точно так же, как люди обрабатывают хэширование паролей в прошлом (например, md5, sha1 и т.д.), я хочу знать наилучшую практику в приведенном выше использование случай.

4b9b3361

Ответ 1

Это очень много здесь. Идея, содержащаяся в параграфе, который вы цитируете, заключается в том, что для того, чтобы биллинг в приложении был безопасным, вам необходимо проверить сигнатуры транзакций. Они подписаны с закрытым ключом, связанным с вашей учетной записью разработчика. Ключ находится на серверах Google, поэтому достаточно безопасно предположить, что никто другой не может подписать данные с ним. Чтобы проверить это, вам нужен ваш открытый ключ, который вы можете скопировать с консоли разработчика. Если кто-то заменил его в своем приложении, они могли бы обмануть его, чтобы принимать транзакции биллинга в приложении из несанкционированных источников, потому что, если они устанавливают открытый ключ, они, вероятно, также контролируют соответствующий закрытый ключ. На практике, однако, гораздо проще просто изменить свой код в правильных местах, чтобы всегда возвращать true для isLicensed(), hasItem() или аналогичных методов, которые у вас могут быть, и никто этого не делает.

Лучший способ защитить ключ - это, конечно, вовсе не иметь ключ в вашем приложении. Переместите всю логику проверки транзакций на ваш сервер и используйте HTTPS для подключения к ней. Правильно проверьте цепочку сертификатов, чтобы убедиться, что вы разговариваете со своим собственным сервером. В противном случае кто-то может столкнуться с DNS и обмануть ваше приложение, чтобы подключиться к своим серверам. Аналогичная атака на покупку iOS была анонсирована пару недель назад.

Следующее лучшее - это каким-то образом запутать ключ и включить его в ваше приложение. Это имеет то преимущество, что вам не нужен сервер, но недостатком является то, что если кто-то будет достаточно определен, они поймут это, так как они всегда могут отменить байтовый код вашего приложения. Поэтому лучше всего придумать свой собственный оригинальный способ сделать это, не появляясь на публичных форумах:) Чтобы сделать это немного сложнее, вы можете реализовать часть проверки в собственном коде, что сложнее (но не невозможно) проанализировать. Тем не менее, как упоминалось выше, исправление байтового кода в правильных местах намного проще, чем попытка заменить открытый ключ, так что это будет делать большинство крекеров.

Ответ 2

Сделайте хотя бы простое текстовое преобразование. Идея состоит в том, что разоблачение простого dex не будет раскрывать ваш открытый ключ.

Здесь пример функции, которая упрощает строковое кодирование/декодирование:

/**
 * Simple String transformation by XOR-ing all characters by value.
 */
static String stringTransform(String s, int i) {
   char[] chars = s.toCharArray();
   for(int j = 0; j<chars.length; j++)
      chars[j] = (char)(chars[j] ^ i);
   return String.valueOf(chars);
}

Затем ваш закрытый ключ хранится в источнике как закодированная строка (кодирует его с помощью этой функции) и декодируется во время выполнения с помощью той же функции. Это своего рода метод "XOR", предложенный Google.

Вы сами делаете параметр "i", любое случайное, такое как 0x27 или другое, будет работать. Если вы спрячете больше строк таким образом, используйте разные "i" для каждого преобразования.

Ответ 3

Как альтернатива запутыванию ключа вручную, вы также можете позволить обфускатору сделать это автоматически. ProGuard является частью Android SDK, но в основном он запутывает имена классов/полей/методов, а не строки. Его специализированный брат для Android, DexGuard, может добавлять больше уровней обфускации, применяя шифрование строк, шифрование классов и отражение. Это не бесплатно, но это экономит время и, вероятно, более эффективно, чем делать это вручную.

(Я разработчик ProGuard и DexGuard)

Ответ 4

Сохраните свой открытый ключ на стороне сервера и как только вы получите ответ от игры Google, чтобы проверить, что ключ отправляет этот ответ серверу и выполняет вашу операцию там на сервере.

Ответ 5

Открытый ключ кодируется base64 ([a-zA-Z0-9+/]), поэтому вы можете легко избежать необходимости избегать запутанной строки вообще, так как это раздражает проблема в решении @PointerNull.

Вместо этого вы можете выполнить обфускацию, сначала преобразуя рассматриваемый символ в 6-битный int. Затем выполните манипуляции с битами (например, XOR-ing), а затем преобразуйте обратно в base64-кодированный char. Гарантировано, что не требуется экранирование персонажа.