Как зашифровать данные в приложении
Что проверяют
Понимаете ли вы, что шифрование упирается в ключ: зашифровать AES умеют все, а где хранится ключ, решает, есть ли защита вообще. Следом обычно спрашивают, от какой угрозы вы защищаетесь и как привязать расшифровку к биометрии.
Как отвечать
Начните с модели угроз. Системное шифрование хранилища на современных устройствах уже есть, а песочница закрывает данные от других приложений. Своё шифрование нужно против root, извлечения через бэкап и доступа к украденному разблокированному телефону.
Дальше каркас:
- ключ в Android Keystore:
KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore")сKeyGenParameterSpec. Ключ не извлекается, операции идут в TEE, а где есть, в StrongBox (setIsStrongBoxBacked(true)); - алгоритм:
AES/GCM/NoPadding, ключ 256 бит. GCM даёт и шифрование, и проверку целостности. IV уникален для каждой операции: Keystore генерирует его сам, вы берётеcipher.ivи храните рядом с шифртекстом; - привязка к пользователю:
setUserAuthenticationRequired(true)иBiometricPromptсCryptoObject, ключ доступен только после отпечатка или PIN; - готовые обёртки: Tink с мастер-ключом в Keystore, часто вместе с DataStore; для Room SQLCipher. Jetpack Security с
EncryptedSharedPreferencesобъявлен устаревшим, новый код на него не строят; - RSA: только для маленьких данных и оборачивания симметричного ключа.
Пароли не шифруют, а хешируют, а на устройстве лучше хранить не пароль, а токен.
Где спотыкаются
Пишут Cipher.getInstance("AES"). У стандартных провайдеров это режим ECB без IV: одинаковые блоки дают одинаковый шифртекст.
Хранят ключ в коде, BuildConfig или в тех же SharedPreferences рядом с данными. Декомпиляция APK достаёт его за минуты, и шифрование превращается в обфускацию.
Используют один IV на все записи. В GCM повтор IV с тем же ключом ломает и конфиденциальность, и защиту целостности.