Как сохранить ключ после закрытия activity при шифровании

      Encryption encryption = Encryption.getDefault("Key", "Salt", new byte[16]);

encrypted = encryption.encryptOrNull(encrypted);
 decrypted = encryption.decryptOrNull(encrypted);

Так не получается

сохранение

SharedPreferences settings = getSharedPreferences("AppSettings", MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor.putString("key", String.valueOf(encryption));
        editor.apply();

загрузка

SharedPreferences settings = getSharedPreferences("AppSettings", MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        String encryption = (settings.getString("key", ""));
        editor.apply();

        decrypted=encryption;

Ответы (1 шт):

Автор решения: Barmaley Red Star
  1. Ключ нельзя сохранять (точка)
  2. Если очень хочется сохранить ключ (см. п.1)
  3. Если все равно хочется сохранить ключ еще раз посмотрите на п.1

Теперь более серьезно. Используются в общем случае 3 подхода как сохранять ключи (в случае Android)

1)Универсальный подход: ключ генерируется на основе пароля заданного юзером. Берем пароль и на его основе генерируем ключ. Процедура описана в т.н. PBKDF2 (Password Based Key Generation Function v.2). В коде выглядит примерно так:

public static String generateKey(String password, String salt) {
        char[] chars = password.toCharArray();
        byte[] salt = salt.getBytes();

        PBEKeySpec spec = new PBEKeySpec(chars, salt, 1010101,
                20 * Byte.SIZE);
        SecretKeyFactory skf = SecretKeyFactory
                .getInstance("PBKDF2WithHmacSHA1");
        byte[] hash = skf.generateSecret(spec).getEncoded();

        return toHex(salt) + ":" + toHex(hash);
}

То есть ничего не храним. Юзер задает пароль из пароля генерируем ключ и шифруем/дешифруем. Если ключ не подошел - ну извините.

2)В качестве пароля используем уникальный идентификатор устройства ANDROID_ID - обратите внимание:

64-bit number (expressed as a hexadecimal string), unique to each combination of app-signing key, user, and device. Values of ANDROID_ID are scoped by signing key and user.

то есть идентификатор генерируется для конкретного устройства и конкретного приложения + юзера устройства. То есть на другом приложении он будет другой. При хард ресете устройства он генерируется заново (что иногда может стать проблемой).

3)Используем Android Keystore - по сути криптографически защищенное устройство для хранения данных. Проблема в том, что некоторые Android девайсы предоставляют заведомо ущербные софтверные реализации. Настоящая реализация должна поддерживать т.н. TEE (Trusted Execution Environment) - защищенная среда исполнения (как правило, в виде специального чипа/процессора, внутри которого проводятся крипто-операции) - например Samsung KNOX или Titan M в Google Pixel. Проверить наличие хардверной реализации можно примерно так:

PrivateKey key = ...; // Android KeyStore key
KeyFactory factory = KeyFactory.getInstance(key.getAlgorithm(), "AndroidKeyStore");
KeyInfo keyInfo = factory.getKeySpec(key, KeyInfo.class);
boolean isHardwareBacked = keyInfo.isInsideSecureHardware();
→ Ссылка