Прежде чем перейти к описанию методов скрытия информации в приложении, важно подчеркнуть: встраивать критически важные данные в код — крайне нежелательно. Это следует делать только в исключительных случаях, когда альтернативы действительно нет. Любые, даже самые изощренные техники обфускации, шифрования или сокрытия файлов внутри приложения не дают абсолютной защиты. Опытный специалист с достаточной квалификацией и мотивацией сможет извлечь скрытые данные.
Поэтому пароли, ключи шифрования и другую критически важную информацию не стоит жестко прописывать в коде приложения. Вместо этого следует использовать более безопасные архитектурные подходы. Например, если приложению нужен доступ к веб-сервису, используйте его API для динамического получения токена при подключении. Если используется скрытый API, пусть приложение запрашивает его уникальный URL у самого сервиса для каждой установки. Для приложений, шифрующих файлы, пароль должен вводиться пользователем. Главная цель — исключить из кода приложения любую информацию, компрометация которой может привести к взлому аккаунтов, сервисов или утечке данных пользователей.
Если же избежать встраивания данных в код невозможно, ниже представлены методы их сокрытия — от простых к сложным.
Хранение строк в strings.xml
Это базовый метод. Вместо объявления строки как константы в Java-коде, что сделает её легко обнаружимой после декомпиляции, её можно разместить в ресурсном файле res/values/strings.xml:
<resources>
...
<string name="password">MyPassword</string>
...
</resources>
Обращение из кода осуществляется через getResources():
String password = getResources().getString(R.string.password);
Поскольку инструменты реверс-инжиниринга часто позволяют просматривать strings.xml, имя строки (например, "password") лучше заменить на что-то нейтральное. Сам пароль можно замаскировать под диагностическое сообщение (например, "Error 8932777") и использовать только его часть, разделив строку методом split():
String[] strings = getResources().getString(R.string.password).split(" ");
String password = strings[1];
Также стоит давать переменным неочевидные имена или использовать обфускатор ProGuard, который сократит их до коротких комбинаций букв.
Разделение строк на части
Строку можно разбить на несколько фрагментов и распределить их по разным методам или классам. Например, чтобы скрыть строку "MyLittlePony":
String a = "MyLi";
String b = "ttle";
String c = "Pony";
...
String password = a + b + c;
Важно помнить, что компилятор может оптимизировать такой код, собрав строку воедино для повышения производительности. Чтобы избежать этого, не следует применять к переменным модификаторы static и final.
Кодирование данных с помощью операции XOR
Это популярный метод для запутывания строк. Его суть: строка и ключ преобразуются в байты, над которыми выполняется операция исключающего ИЛИ (XOR). Результат — закодированная строка, которую можно декодировать, повторно применив XOR с тем же ключом. Пример реализации в классе StringXOR:
// Кодируем строку
public static String encode(String s, String key) {
return Base64.encodeToString(xor(s.getBytes(), key.getBytes()), 0);
}
// Декодируем строку
public static String decode(String s, String key) {
return new String(xor(Base64.decode(s, 0), key.getBytes()));
}
// Сама операция XOR
private static byte[] xor(byte[] a, byte[] key) {
byte[] out = new byte[a.length];
for (int i = 0; i < a.length; i++) {
out[i] = (byte) (a[i] ^ key[i % key.length]);
}
return out;
}
После кодирования строк (например, "password1" и "password2" с ключом "1234") в логах появятся строки вида RVRCRQ== и ACHBDS==. Именно их нужно поместить в код, а при необходимости использовать декодирование:
String password1 = StringXOR.decode(encodedPassword1, "1234");
Этот метод скрывает строки от простого просмотра, но не является криптографически стойким. Ключ также требует защиты.
Обратите внимание: Майнинг на андроид.
Использование реального шифрования
Более надежный подход — применение алгоритмов симметричного шифрования, например, AES. Понадобятся функции для шифрования, дешифрования и управления ключами:
public static byte[] encryptString(String message, SecretKey secret) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secret);
return cipher.doFinal(message.getBytes("UTF-8"));
}
public static String decryptString(byte[] cipherText, SecretKey secret) throws Exception {
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secret);
return new String(cipher.doFinal(cipherText), "UTF-8");
}
Ключ генерируется случайным образом, затем преобразуется в строку для удобства хранения и обратно. На этапе разработки ключ и зашифрованные с его помощью строки выводятся в лог, а затем их строковые представления встраиваются в код. При использовании вместе с обфускатором ProGuard, логика сборки и расшифровки строк становится сложной для анализа.
Хранение данных в нативном коде (C/C++)
Наиболее сложный для анализа метод — вынесение критических данных в нативный код, который компилируется в машинные инструкции (ARM/ARM64). Дизассемблированный нативный код читать и понимать гораздо сложнее, чем декомпилированный Java-код.
Для этого создается Java-класс-обертка с объявлением native-метода, например, getPassword(). Реализация метода пишется на языке C в отдельном файле (например, secret.c), который затем компилируется в библиотеку .so. Хотя извлечь простую строку из скомпилированной библиотеки можно утилитой strings, комбинирование этого метода с предыдущими (разделение строк, XOR, шифрование) на уровне C/C++-кода значительно повышает сложность реверс-инжиниринга. Однако это требует навыков разработки на C/C++ и усложняет сборку проекта.
Итоги и рекомендации
Технически возможно спрятать данные в приложении, но к этому следует прибегать лишь в крайних случаях. Даже нативный код можно анализировать с помощью отладчика, установив точку останова на вызов метода, возвращающего секрет. Поэтому приоритет должен оставаться за архитектурными решениями, которые не требуют хранения секретов в коде клиентского приложения.
Читайте Самые полезные и интересные материалы про Безопасность на Канале! 😎
#безопасность и мир #безопасность #интернет #шифрование #анроид #защита и взлом #данные #телефон
Больше интересных статей здесь: Гаджеты.
Источник статьи: Шифрование данных пользователя в приложениях Андроид!.